我有一个System.Windows.Form
和一个IntPtr
作为 HWND 的角色。
我希望他们每个人都让对方动起来。我很惊讶我在网上找不到任何带有“Hwnd get/set position c#”和许多变体的东西,也许我忽略了明显的结果。
对于给定的示例,请考虑表单“窗口 A”和 Hwnd“窗口 B”。假设我希望 B 的位置是 A 的位置 + 右侧 50 像素。
更新:您可能还想查看 WinForms 的
NativeWindow
class,它可用于包装本机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);
更难的部分是在 B 移动时让 A 移动。这需要一个 NativeWindow 派生类。使用 AssignHandle 附加您获得的窗口句柄。在 WndProc() 覆盖中,您可以检测到 WM_MOVE 消息,允许您移动 A。和 WM_DESTROY 进行清理。
但是,仅当窗口归您的进程所有时才有效。更典型的情况是,这是一个属于某些您无法控制的代码的窗口,它在另一个程序中运行。如果是这样的话,你就完蛋了,NativeWindow 方法行不通。您需要使用 SetWindowsHookEx() 将非托管 DLL 注入进程,以便监控 WH_CALLWNDPROC。使用某种 IPC 机制将该通知纳入您的流程。很难做到正确,你不能用 C# 编写 DLL 代码。