使用SetParent()时问题定位窗口

Fre*_*ool 3 c# excel office-automation setparent winforms

我试图childForm通过PInvoke使用SetParent API 设置为主Excel窗口的子项:

Form childForm = new MyForm();
IntPtr excelHandle = (IntPtr) excelApplication.Hwnd;
SetParent(childForm.Handle, excelHandle);
childForm.StartPosition = FormStartPosition.Manual;
childForm.Left = 0;
childForm.Top = 0;
Run Code Online (Sandbox Code Playgroud)

如您所见,我的目的也是将孩子放在Excel窗口的左上角.然而,由于某种原因,childForm总是在一些奇怪的位置结束.

我做错了什么?

Fre*_*ool 7

虽然这里的所有答案都提出了完美的逻辑方法,但它们都不适用于我.然后我尝试了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);
Run Code Online (Sandbox Code Playgroud)

  • +1 这是我建议尝试的下一件事。您正在进行非托管 API 调用来设置窗口的父窗口,因此托管代码用来更改窗口位置的例程很可能无法正常工作。我很高兴这解决了您的问题,但您仍然应该确保窗口样式(添加“WM_CHILD”并删除“WM_POPUP”)设置正确,正如我在之前的回答中提到的那样,以防止将来出现任何问题并与文档。 (2认同)

Cod*_*ray 5

SetParent当前桌面的子窗体上使用的窗体(换句话说,没有父窗口的窗体)时,必须设置WS_CHILD样式并删除WS_POPUP样式.(请参阅MSDN条目的"备注"部分.)Windows要求所有拥有的窗口都WS_CHILD设置了样式.这也可能导致左侧和顶部属性报告/设置错误的值,因为表单不知道它是谁的爸爸.您可以通过调用SetWindowLong之后SetParent但在尝试设置位置之前解决此问题:

//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);
Run Code Online (Sandbox Code Playgroud)