1

我有一个System.Windows.Form和一个IntPtr作为 HWND 的角色。

我希望他们每个人都让对方动起来。我很惊讶我在网上找不到任何带有“Hwnd get/set position c#”和许多变体的东西,也许我忽略了明显的结果。

对于给定的示例,请考虑表单“窗口 A”和 Hwnd“窗口 B”。假设我希望 B 的位置是 A 的位置 + 右侧 50 像素。

4

2 回答 2

3

更新:您可能还想查看 WinForms 的NativeWindowclass,它可用于包装本机HWWND并侦听发送到该窗口的窗口消息。

我想你需要 Win32 API 函数MoveWindow来设置你的窗口 B(那个)的位置(和尺寸HWND)。您可以通过 P/Invoke从 .NET 调用此 API 函数。

为了检索窗口 B 的当前位置和大小,您可能还需要调用GetWindowRect,也可以通过 P/Invoke。


以下代码可能无法开箱即用,也许有更简单的解决方案,但它可能会为您提供一个起点,以及上面的链接:

// 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);
于 2011-01-20T01:04:53.043 回答
2

更难的部分是在 B 移动时让 A 移动。这需要一个 NativeWindow 派生类。使用 AssignHandle 附加您获得的窗口句柄。在 WndProc() 覆盖中,您可以检测到 WM_MOVE 消息,允许您移动 A。和 WM_DESTROY 进行清理。

但是,仅当窗口归您的进程所有时才有效。更典型的情况是,这是一个属于某些您无法控制的代码的窗口,它在另一个程序中运行。如果是这样的话,你就完蛋了,NativeWindow 方法行不通。您需要使用 SetWindowsHookEx() 将非托管 DLL 注入进程,以便监控 WH_CALLWNDPROC。使用某种 IPC 机制将该通知纳入您的流程。很难做到正确,你不能用 C# 编写 DLL 代码。

于 2011-01-20T01:47:57.623 回答