For any custom dialog (form) in a WinForm application I can set its size and position before I display it with:
form.StartPosition = FormStartPosition.Manual
Check out this article on CodeProject. Excerpt:
Here is when the handy .NET NativeWindow comes into the picture, a NativeWindow is a window wrapper where it processes the messages sent by the handle associated to it. It creates a NativeWindow and associates the OpenFileWindow handle to it. From this point, every message sent to OpenFileWindow will be redirected to our own WndProc method in the NativeWindow instead, and we can cancel, modify, or let them pass through.
In our WndProc, we process the message WM_WINDOWPOSCHANGING. If the open dialog is opening, then we will change the original horizontal or vertical size depending of the StartLocation set by the user. It will increment the size of the window to be created. This happens only once when the control is opened.
Also, we will process the message WM_SHOWWINDOW. Here, all controls inside the original OpenFileDialog are created, and we are going to append our control to the open file dialog. This is done by calling a Win32 API SetParent. This API lets you change the parent window. Then, basically what it does is attach our control to the original OpenFileDialog in the location it set, depending on the value of the StartLocation property.
The advantage of it is that we still have complete control over the controls attached to the OpenFileDialog window. This means we can receive events, call methods, and do whatever we want with those controls.
Here's how I did it:
The point where I want to display the OpenFileDialog:
Thread posThread = new Thread(positionOpenDialog);
posThread.Start();
DialogResult dr = ofd.ShowDialog();
The repositioning code:
[DllImport("user32.dll", EntryPoint = "FindWindow", SetLastError = true)]
static extern IntPtr FindWindowByCaption(IntPtr ZeroOnly, string lpWindowName);
[DllImport("user32.dll", EntryPoint = "SetWindowPos")]
public static extern IntPtr SetWindowPos(IntPtr hWnd, int hWndInsertAfter, int x, int Y, int cx, int cy, int wFlags);
/// <summary>
/// Find the OpenFileDialog window when it appears, and position it so
/// that we can see both dialogs at once. There is no easier way to
/// do this (&^%$! Microsoft!).
/// </summary>
private void positionOpenDialog ()
{
int count = 0;
IntPtr zero = (IntPtr)0;
const int SWP_NOSIZE = 0x0001;
IntPtr wind;
while ((wind = FindWindowByCaption(zero, "Open")) == (IntPtr)0)
if (++count > 100)
return; // Find window failed.
else
Thread.Sleep(5);
SetWindowPos(wind, 0, Right, Top, 0, 0, SWP_NOSIZE);
}
I start a thread that looks for a window with the "Open" title. (Typically found in 3 iterations or 15 milliseconds.) Then I set its position with the obtained handle. (See SetWindowPos documentation for the position/size parameters.)
Kludgy.