我希望在父窗体的中心显示我的消息框。如果我移动了窗体并显示消息框,它总是显示在桌面的中心。我希望它能够随着窗体一起出现。 你能给我一些技巧和建议吗?
我基于某个Windows Forms类制作了这个类。
将该类添加到您的WPF项目中,并像下面这样将“this”作为参数提供给辅助方法:
MessageBoxHelper.PrepToCenterMessageBoxOnForm(this)"
然后显示消息框:
MessageBox.Show("Hello there!");
/// <summary>
/// This class makes it possible to center a MessageBox over the parent dialog.
/// Usage example:
/// MessageBoxHelper.PrepToCenterMessageBoxOnForm(this);
/// MessageBox.Show("Hello there!);
/// </summary>
public static class MessageBoxHelper
{
public static void PrepToCenterMessageBoxOnForm(Window window)
{
MessageBoxCenterHelper helper = new MessageBoxCenterHelper();
helper.Prep(window);
}
private class MessageBoxCenterHelper
{
private int messageHook;
private IntPtr parentFormHandle;
public void Prep(Window window)
{
NativeMethods.CenterMessageCallBackDelegate callBackDelegate = new NativeMethods.CenterMessageCallBackDelegate(CenterMessageCallBack);
GCHandle.Alloc(callBackDelegate);
parentFormHandle = new WindowInteropHelper(window).Handle;
messageHook = NativeMethods.SetWindowsHookEx(5, callBackDelegate, new IntPtr(NativeMethods.GetWindowLong(parentFormHandle, -6)), NativeMethods.GetCurrentThreadId()).ToInt32();
}
private int CenterMessageCallBack(int message, int wParam, int lParam)
{
NativeMethods.RECT formRect;
NativeMethods.RECT messageBoxRect;
int xPos;
int yPos;
if (message == 5)
{
NativeMethods.GetWindowRect(parentFormHandle, out formRect);
NativeMethods.GetWindowRect(new IntPtr(wParam), out messageBoxRect);
xPos = (int)((formRect.Left + (formRect.Right - formRect.Left) / 2) - ((messageBoxRect.Right - messageBoxRect.Left) / 2));
yPos = (int)((formRect.Top + (formRect.Bottom - formRect.Top) / 2) - ((messageBoxRect.Bottom - messageBoxRect.Top) / 2));
NativeMethods.SetWindowPos(wParam, 0, xPos, yPos, 0, 0, 0x1 | 0x4 | 0x10);
NativeMethods.UnhookWindowsHookEx(messageHook);
}
return 0;
}
}
private static class NativeMethods
{
internal struct RECT
{
public int Left;
public int Top;
public int Right;
public int Bottom;
}
internal delegate int CenterMessageCallBackDelegate(int message, int wParam, int lParam);
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern bool UnhookWindowsHookEx(int hhk);
[DllImport("user32.dll", SetLastError = true)]
internal static extern int GetWindowLong(IntPtr hWnd, int nIndex);
[DllImport("kernel32.dll")]
internal static extern int GetCurrentThreadId();
[DllImport("user32.dll", SetLastError = true)]
internal static extern IntPtr SetWindowsHookEx(int hook, CenterMessageCallBackDelegate callback, IntPtr hMod, int dwThreadId);
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern bool SetWindowPos(int hWnd, int hWndInsertAfter, int X, int Y, int cx, int cy, int uFlags);
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern bool GetWindowRect(IntPtr hWnd, out RECT lpRect);
}
}
将消息框窗口的所有者设置为您的窗口(使用.Show()
的第一个参数),而不是不设置所有者。
请参见此处进行参考。
this
是什么。恐怕我的经验仅限于本地Win32 MessageBox()
函数,它有点不同,在我意识到你正在使用WinForms之前,我已经回答了一半。因此,我修改了我的答案以适应我在参考文献中找到的内容,但我可能仍然缺少一些细节。 :) - Greg Hewgill这里有一个非常易于使用的解决方案,而且它完美地工作:
步骤:
(在UserControl
或Form
内部)
MessageBoxEx.Show(this, "Please fix the validation errors before saving.", "Validation Errors");
我以前在C#中做过这个。这是我记得的。
定义一个类:
public class IWindowWrapper : System.Windows.Forms.IWin32Window
{
public IWindowWrapper(IntPtr handle)
{
this.Handle= handle;
}
public IntPtr Handle
{
get;
set;
}
}
根据 MessageBox 定义一个类。基于 MessageBox 创建一个新的 Show 方法:
public string Show(IWin32Window owner)
{
if(owner == null)
{
this.ShowDialog();
}
else
{
//parentWindow.
this.StartPosition = FormStartPosition.CenterParent;
this.ShowDialog(owner);
}
}
msgBox.Show(new IWindowWrapper(this.Handle))