tags:

views:

245

answers:

2

How can I make a window always stay on top of another window that already always stays on top? Not that it has to stay on top of all other windows, I just need it to stay on top of a particular window.

+3  A: 

Don't do this.

That said, you should be able to do it by making your window a child of the other one.

SLaks
I've seen that blog post, but I'm not meaning that I want the window to stay on top of all other windows, just over a particular one.
Zach Johnson
Yes, if your first modal window thne itself spawns another modal window, then that will become the new most on top window. But now you have the original window, and the first modal window sitting behind the new modal window and they can't be moved or dragged, which can be frustrating if the user needs information hiding behind any of those windows.
AaronLS
@aaronls: He isn't making a modal window.
SLaks
My forms are not modal. The user can interact between them as much as they want. The windows sit right next to each other, and I am trying to prevent the shadow of the secondary window from overlapping into the first window when the user interacts with it.
Zach Johnson
SLaks is right. If you use the Form.Show(owner) method, you can keep a child window on top of the "owner" window without blocking the UI of the owner. This is called a "modeless" dialog. Should work for toplevel windows as well.
jdv
Unfortunately, I can't use Form.Show(owner) because the second form technically needs to be the owner of the first, but the second window is shown after the first.
Zach Johnson
+2  A: 

Thanks to SLaks's answer and some of the comments on it, I was able to figure out how set a child-parent relationship between my forms. I couldn't use Form.Show(owner), because the form that I wanted to stay in front was shown before the other form. I used Reflector to examine the code behind Form.Show(owner) and discovered that behind the scenes, it all resolves down to SetWindowLong in the Windows API.

LONG SetWindowLong(      
    HWND hWnd,
    int nIndex,
    LONG dwNewLong
);

Form.Show(owner) calls SetWindowLong with an nIndex of -8. The MSDN online documentation won't tell you about it, but according to Winuser.h one of the constants available for nIndex is GWL_HWNDPARENT, which has a value of -8. Once I connected these dots, the problem was quite easy to solve.

This following is how to set the window's parent, even if it is already shown:

using System.Runtime.InteropServices;

[DllImport("user32.dll")]
public static extern int SetWindowLong(HandleRef hWnd, int nIndex, HandleRef dwNewLong);

public static void SetOwner(IWin32Window child, IWin32Window owner)
{
    NativeMethods.SetWindowLong(
        new HandleRef(child, child.Handle), 
        -8, // GWL_HWNDPARENT
        new HandleRef(owner, owner.Handle));
}
Zach Johnson
Thanks for posting your solution. That's nice!
Jacob Seleznev