Search code examples
c#.netwinformswinapihwnd

How can I make a Form and a HWND mutually reposition?


I have a System.Windows.Form and a IntPtr acting as HWND.

I want each of them to place the other on move. I'm surprised I couldn't find anything on the web with "Hwnd get/set position c#" and many variations, perhaps I'm overlooking obvious results.

For the sake of the given examples, consider the Form "window A" and the Hwnd "window B". Let's also say I want B's position to be A's position + 50 pixels on the right.


Solution

  • Update: You might also want to check out WinForms' NativeWindow class, which can be used to wrap a native HWWND and listen to window messages sent to that window.

    I suppose you'll need the Win32 API function MoveWindow to set the position (and dimensions) of your window B (the HWND one). You can call this API function from .NET via P/Invoke.

    In order to retrieve the current position and size of window B, you may additionally need to call GetWindowRect, also via P/Invoke.


    The following code might not work out of the box, and maybe there are simpler solutions, but it might give you a starting point, together with the above links:

    // the following P/Invoke signatures have been copied from pinvoke.net:
    
    [DllImport("user32.dll", SetLastError = true)]
    internal static extern bool MoveWindow(IntPtr hWnd, 
                                           int X, int Y,
                                           int nWidth, int nHeight, 
                                           bool bRepaint);
    
    [DllImport("user32.dll")]
    [return: MarshalAs(UnmanagedType.Bool)]
    static extern bool GetWindowRect(HandleRef hWnd, out RECT lpRect);
    
    [StructLayout(LayoutKind.Sequential)]
    public struct RECT
    {
        public int Left;        // x position of upper-left corner
        public int Top;         // y position of upper-left corner
        public int Right;       // x position of lower-right corner
        public int Bottom;      // y position of lower-right corner
    }
    
    ...
    
    System.Windows.Form a = ...;
    IntPtr b = ...;
    
    RECT bRect;
    GetWindowRect(b, out bRect);
    
    MoveWindow(b,
               a.Location.X + 50, b.Location.Y,
               bRect.Right - bRect.Left, bRect.Bottom - bRect.Top,
               true);