开发者

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

开发者 https://www.devze.com 2023-02-05 21:05 出处:网络
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 man

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 positio开发者_如何学编程n + 50 pixels on the right.


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);


The harder part is to get A to move when B moves. That requires a NativeWindow derived class. Use AssignHandle to attach the window handle you got. In the WndProc() override you can detect the WM_MOVE message, allowing you to move A. And WM_DESTROY to clean up.

That however only works if the window is owned by your process. The more typical scenario is that this is a window belonging to some code you don't control, running in another program. You are quite screwed if that's the case, the NativeWindow approach cannot work. You'd need to inject an unmanaged DLL into the process with SetWindowsHookEx() so you can monitor WH_CALLWNDPROC. With some kind of IPC mechanism to get that notification into your process. Very hard to get right, you can't write the DLL code in C#.

0

精彩评论

暂无评论...
验证码 换一张
取 消