Winforms-如何让对话框显示在 MainForm 的中心?这与基于普通窗口默认设置相反,后者将它们显示在屏幕的中心。在我的例子中,我有一个小的
Winforms-如何使对话框显示在 MainForm 的中心?这与基于普通窗口默认设置(将对话框显示在屏幕中心)相反。
在我的例子中,我有一个小的主窗体,例如,它可能被放置在一个角落里,MessageBox 弹出窗口显示在看似很远的地方。
不需要自制消息框或 GetForegroundWindow、EnumWindows、AutomationElement.RootElement.FindAll、SetWindowsHookEx 等。
当消息框打开或者关闭的时候都会向窗体发送WM_ACTIVATE消息,然后就可以得到消息框的窗口句柄(LParam)。
protected override void WndProc(ref Message m)
{
switch (m.Msg) {
case Pinvoke.WM_ACTIVATE:
Debug.WriteLine($"{MethodBase.GetCurrentMethod().Name} {DateTime.Now.ToString("HH:mm:ss.fff")} {m.ToString()}");
if (m.LParam == IntPtr.Zero) break;
if (_messageBoxCaption == null) break; // donot call MessageBox.Show
if ((ushort)m.WParam.ToInt32() != 0/*WA_INACTIVE*/) break; // maybe close messagebox
// check messagebox
if (Pinvoke.GetWindowProcessId(m.LParam) != Process.GetCurrentProcess().Id) break;
string className = Pinvoke.GetClassName(m.LParam);
if (className == null || className != "#32770") break; // not dialog
if (_messageBoxCaption != Pinvoke.GetWindowText(m.LParam)) break; // another caption
// move messagebox
//Debug.WriteLine("messageBox detected");
Rectangle rect = Pinvoke.GetWindowRect(m.LParam);
Pinvoke.MoveWindow(m.LParam, this.Left + this.Width / 2, this.Top + this.Height / 2, rect.Width, rect.Height, true);
break;
}
base.WndProc(ref m);
}
GetWindowProcessId 是 GetWindowThreadProcessId 的包装器。根据需要添加其他 Pinvoke 方法。如果要尽可能减少 P/Invoke,请将其替换为 UIAutomation。
private string _messageBoxCaption = null; // messageBox caption
_messageBoxCaption = caption;
ret = MessageBox.Show(this, text, caption, ...);
_messageBoxCaption = null;