I have two forms, that are connected to each other as for their business logic. I want the second one to come right behind the first one, whenever I focus on the first one and vise versa.

In order to make my problem clearer, I will describe the reasons I want this link. The first form represents a form of a database object and the second one a viewer of a PDF document linked to this specific object. As you can understand, I want to avoid the confusion, that will occur, if a user opens two pairs of forms (two database objects) and in case the first form of the first object shows next to the PDF document of the second object.

Until now I have created a class called FormPair, that contains both forms as properties and I added an event handler on the Focus event of each form, that does the following:

  1. Focus on the other form
  2. Focus again on the form that triggered the event

It kind of works, but it doesn't look good (flickering, it looses focus of the specific subcontrol, etc). Could I somehow play with the z-index of the secondary form and achieve a better result?

有帮助吗?

解决方案

BringToFront() is a good solution, but it flickers a little, when I call it twice (on second form and then again on the first form). I finally used a external method from user32.dll called SetWindowPos, to make a new bringToFront method of my own, that doesn't flicker at all and gives me the feeling that both forms are linked with each other. Here it goes (Everything with X is a custom class/enum/struct) :

public partial class XForm : Form 
{
    [DllImport("user32.dll")]
    [return: MarshalAs(UnmanagedType.Bool)]
    static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, XWindowPositionFlag uFlags);

    public void bringToFront()
    {
        SetWindowPos(this.Handle, XFormZIndex.Top, 0, 0, 0, 0,
            XWindowPositionFlag.SWP_NOMOVE | XWindowPositionFlag.SWP_NOSIZE | XWindowPositionFlag.SWP_NOACTIVATE);
    }
}

where

public struct XFormZIndex
{
    public static IntPtr
    NoTopMost = new IntPtr(-2),
    TopMost = new IntPtr(-1),
    Top = new IntPtr(0),
    Bottom = new IntPtr(1);
}
[Flags]
public enum XWindowPositionFlag : uint
{
    SWP_ASYNCWINDOWPOS = 0x4000,
    SWP_DEFERERASE = 0x2000,
    SWP_DRAWFRAME = 0x0020,
    SWP_FRAMECHANGED = 0x0020,
    SWP_HIDEWINDOW = 0x0080,
    SWP_NOACTIVATE = 0x0010,
    SWP_NOCOPYBITS = 0x0100,
    SWP_NOMOVE = 0x0002,
    SWP_NOOWNERZORDER = 0x0200,
    SWP_NOREDRAW = 0x0008,
    SWP_NOREPOSITION = 0x0200,
    SWP_NOSENDCHANGING = 0x0400,
    SWP_NOSIZE = 0x0001,
    SWP_NOZORDER = 0x0004,
    SWP_SHOWWINDOW = 0x0040,
}

and then in FormPair

public partial class XFormPair
{
    // properties
    public XForm leftForm { get; set; }
    public XForm rightForm { get; set; }

    // events
    private void rightFormActivated(object sender, EventArgs e)
    {
        leftForm.bringToFront();
        rightForm.bringToFront();
    }
    private void leftFormActivated(object sender, EventArgs e)
    {
        rightForm.bringToFront();
        leftForm.bringToFront();
    }

}
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top