问题定位窗口使用SetParent()时
我想通过PInvoke使用SetParent API将childForm
设置为主Excel窗口的子项:
Form childForm = new MyForm(); IntPtr excelHandle = (IntPtr) excelApplication.Hwnd; SetParent(childForm.Handle, excelHandle); childForm.StartPosition = FormStartPosition.Manual; childForm.Left = 0; childForm.Top = 0;
正如你上面所看到的,我的意图也是把孩子放在Excel窗口的左上angular。 但是,由于某种原因, childForm
总是会在某个奇怪的位置结束。
我做错了什么?
虽然这里的所有答案都提出了完全合乎逻辑的方法,但是没有一个对我有效 然后我尝试MoveWindow。 出于某种原因,我不明白,它做了这个工作。
代码如下:
[DllImport("user32.dll", SetLastError = true)] internal static extern bool MoveWindow(IntPtr hWnd, int X, int Y, int nWidth, int nHeight, bool bRepaint); ... Form childForm = new MyForm(); IntPtr excelHandle = (IntPtr) excelApplication.Hwnd; SetParent(childForm.Handle, excelHandle); MoveWindow(childForm.Handle, 0, 0, childForm.Width, childForm.Height, true);
在当前桌面的子窗体上使用SetParent
时(换句话说,在没有父窗体的窗体上),必须设置WS_CHILD
样式并删除WS_POPUP
样式。 (请参阅MSDN条目的“备注”部分。)Windows要求所有拥有的窗口都设置了WS_CHILD
样式。 这也可能导致左侧属性和顶部属性报告/设置错误的值,因为表单不知道谁是爸爸。 你可以通过在SetParent
之后调用SetWindowLong
来解决这个问题,但在尝试设置位置之前:
//Remove WS_POPUP style and add WS_CHILD style const UInt32 WS_POPUP = 0x80000000; const UInt32 WS_CHILD = 0x40000000; int style = GetWindowLong(this.Handle, GWL_STYLE); style = (style & ~(WS_POPUP)) | WS_CHILD; SetWindowLong(this.Handle, GWL_STYLE, style);
这取决于你的ShowDialog电话我相信。 如果您没有父paremeter调用ShowDialog,父级被重置。
您可以创build一个实现IWin32Window的包装类,并将HWND返回给excel。 然后,您可以将其传递给childForm的ShowDialog调用。
您还可以使用GetWindowPos查询Excel应用程序的位置,然后相应地设置childForm。
尝试几件事来诊断问题:
- 设置Left和Top之后放置一个断点,执行Left和Top读取零点?
- 最后调用SetParent。
- 做一个方法,再次设置Left和Top,然后BeginInvoke方法。
- 确保你的孩子窗口真的是孩子。 要做到这一点,调用ShowDialog,并尝试点击父窗口。 确保窗口防止焦点到父窗口。
假设你知道如何获得你想要设置z顺序的窗口的大小,你可以使用这个pInvoke:
public stati class WindowsApi { [DllImport("user32.dll")] public static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, uint uFlags); } public class WindowZOrderPositioner { public void SetZOrder(IntPtr targetHwnd, IntPtr insertAfter) { IntPtr nextHwnd = IntPtr.Zero; WindowsAPI.SetWindowPos(targetHwnd, insertAfter, 0, 0, 0, 0, SetWindowPosFlags.NoMove | SetWindowPosFlags.NoSize | SetWindowPosFlags.NoActivate); }