I'm trying to set childForm
as the child of the main Excel window using the SetParent API through PInvoke:
Form childForm = new MyForm();
IntPtr excelHandle = (IntPtr) excelApplication.Hwnd;
SetParent(childForm.Handle, excelHandle);
childForm.StartPosition = FormStartPosition.Manual;
childForm.Left = 0;
childForm.Top = 0;
As you can see above, my intention is also to position the child in the top left corner of Excel window. However, for some reason the childForm
always ends up at some weird location.
What is it that I am doing wrong?
Assuming you know how to get the hwnds of the windows you want to set z-order of, you can use this pInvoke:
When using
SetParent
on a form that is currently a child of the desktop (in other words, one without a parent set), you must set theWS_CHILD
style and remove theWS_POPUP
style. (See the Remarks section of the MSDN entry.) Windows requires that all owned windows have theWS_CHILD
style set. This could also be causing the left and top properties to report/set the wrong values because the form doesn't know who it's daddy is. You can fix this by callingSetWindowLong
afterSetParent
, but before you try to set the location:Try a few things to diagnose the problem:
While all answers here suggest perfectly logical approaches, none of them worked for me. Then I tried MoveWindow. For some reason I don't understand, it did the job.
Here's the code:
It depends on your ShowDialog call I believe. If you call ShowDialog without the parent paremeter, the parent is reset.
You could create a wrapper class that implements IWin32Window and returns the HWND to excel. Then you could pass that to the ShowDialog call of childForm.
You could also query the position of the excel application using GetWindowPos and then set the childForm accordingly.