如何让 MessageBox.Show() 在我的 WPF 应用程序中间弹出?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/564710/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to get MessageBox.Show() to pop up in the middle of my WPF application?
提问by Edward Tanguay
I have a 700w x 300h WPF applciation and can drag it anywhere on my large screen.
我有一个 700w x 300h WPF 应用程序,可以将它拖动到大屏幕上的任何位置。
When my application executes:
当我的应用程序执行时:
MessageBox.Show("Sorry, this function is not yet implemented.");
the mesage box appears in the middle of my screen, which may or may not even be near the application itself.
消息框出现在我的屏幕中间,它可能靠近也可能不靠近应用程序本身。
How can I get my MessageBox to appear in the middle of my applicationinstead?
如何让我的 MessageBox 出现在我的应用程序中间?
采纳答案by chainerlt
If your app has several windows, you might want to use Application.Current.MainWindow
:
如果您的应用程序有多个窗口,您可能需要使用Application.Current.MainWindow
:
MessageBox.Show(Application.Current.MainWindow, "Can't login with given names.", "Login Failure", MessageBoxButton.OK, MessageBoxImage.Error, MessageBoxResult.Cancel);
回答by Framnk
Here's a version of the MessageBoxEx helper class posted in the other thread that uses WPF style message boxes (Note that you still need to reference System.Drawing):
下面是使用 WPF 样式消息框的另一个线程中发布的 MessageBoxEx 帮助器类的一个版本(请注意,您仍然需要引用 System.Drawing):
using System;
using System.Text;
using System.Runtime.InteropServices;
using System.Windows;
using System.Windows.Interop;
using System.Drawing;
public class MessageBoxEx
{
private static IntPtr _owner;
private static HookProc _hookProc;
private static IntPtr _hHook;
public static MessageBoxResult Show(string text)
{
Initialize();
return MessageBox.Show(text);
}
public static MessageBoxResult Show(string text, string caption)
{
Initialize();
return MessageBox.Show(text, caption);
}
public static MessageBoxResult Show(string text, string caption, MessageBoxButton buttons)
{
Initialize();
return MessageBox.Show(text, caption, buttons);
}
public static MessageBoxResult Show(string text, string caption, MessageBoxButton buttons, MessageBoxImage icon)
{
Initialize();
return MessageBox.Show(text, caption, buttons, icon);
}
public static MessageBoxResult Show(string text, string caption, MessageBoxButton buttons, MessageBoxImage icon, MessageBoxResult defResult)
{
Initialize();
return MessageBox.Show(text, caption, buttons, icon, defResult);
}
public static MessageBoxResult Show(string text, string caption, MessageBoxButton buttons, MessageBoxImage icon, MessageBoxResult defResult, MessageBoxOptions options)
{
Initialize();
return MessageBox.Show(text, caption, buttons, icon, defResult, options);
}
public static MessageBoxResult Show(Window owner, string text)
{
_owner = new WindowInteropHelper(owner).Handle;
Initialize();
return MessageBox.Show(owner, text);
}
public static MessageBoxResult Show(Window owner, string text, string caption)
{
_owner = new WindowInteropHelper(owner).Handle;
Initialize();
return MessageBox.Show(owner, text, caption);
}
public static MessageBoxResult Show(Window owner, string text, string caption, MessageBoxButton buttons)
{
_owner = new WindowInteropHelper(owner).Handle;
Initialize();
return MessageBox.Show(owner, text, caption, buttons);
}
public static MessageBoxResult Show(Window owner, string text, string caption, MessageBoxButton buttons, MessageBoxImage icon)
{
_owner = new WindowInteropHelper(owner).Handle;
Initialize();
return MessageBox.Show(owner, text, caption, buttons, icon);
}
public static MessageBoxResult Show(Window owner, string text, string caption, MessageBoxButton buttons, MessageBoxImage icon, MessageBoxResult defResult)
{
_owner = new WindowInteropHelper(owner).Handle;
Initialize();
return MessageBox.Show(owner, text, caption, buttons, icon, defResult);
}
public static MessageBoxResult Show(Window owner, string text, string caption, MessageBoxButton buttons, MessageBoxImage icon, MessageBoxResult defResult, MessageBoxOptions options)
{
_owner = new WindowInteropHelper(owner).Handle;
Initialize();
return MessageBox.Show(owner, text, caption, buttons, icon,
defResult, options);
}
public delegate IntPtr HookProc(int nCode, IntPtr wParam, IntPtr lParam);
public delegate void TimerProc(IntPtr hWnd, uint uMsg, UIntPtr nIDEvent, uint dwTime);
public const int WH_CALLWNDPROCRET = 12;
public enum CbtHookAction : int
{
HCBT_MOVESIZE = 0,
HCBT_MINMAX = 1,
HCBT_QS = 2,
HCBT_CREATEWND = 3,
HCBT_DESTROYWND = 4,
HCBT_ACTIVATE = 5,
HCBT_CLICKSKIPPED = 6,
HCBT_KEYSKIPPED = 7,
HCBT_SYSCOMMAND = 8,
HCBT_SETFOCUS = 9
}
[DllImport("user32.dll")]
private static extern bool GetWindowRect(IntPtr hWnd, ref Rectangle lpRect);
[DllImport("user32.dll")]
private static extern int MoveWindow(IntPtr hWnd, int X, int Y, int nWidth, int nHeight, bool bRepaint);
[DllImport("User32.dll")]
public static extern UIntPtr SetTimer(IntPtr hWnd, UIntPtr nIDEvent, uint uElapse, TimerProc lpTimerFunc);
[DllImport("User32.dll")]
public static extern IntPtr SendMessage(IntPtr hWnd, int Msg, IntPtr wParam, IntPtr lParam);
[DllImport("user32.dll")]
public static extern IntPtr SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hInstance, int threadId);
[DllImport("user32.dll")]
public static extern int UnhookWindowsHookEx(IntPtr idHook);
[DllImport("user32.dll")]
public static extern IntPtr CallNextHookEx(IntPtr idHook, int nCode, IntPtr wParam, IntPtr lParam);
[DllImport("user32.dll")]
public static extern int GetWindowTextLength(IntPtr hWnd);
[DllImport("user32.dll")]
public static extern int GetWindowText(IntPtr hWnd, StringBuilder text, int maxLength);
[DllImport("user32.dll")]
public static extern int EndDialog(IntPtr hDlg, IntPtr nResult);
[StructLayout(LayoutKind.Sequential)]
public struct CWPRETSTRUCT
{
public IntPtr lResult;
public IntPtr lParam;
public IntPtr wParam;
public uint message;
public IntPtr hwnd;
} ;
static MessageBoxEx()
{
_hookProc = new HookProc(MessageBoxHookProc);
_hHook = IntPtr.Zero;
}
private static void Initialize()
{
if (_hHook != IntPtr.Zero)
{
throw new NotSupportedException("multiple calls are not supported");
}
if (_owner != null)
{
_hHook = SetWindowsHookEx(WH_CALLWNDPROCRET, _hookProc, IntPtr.Zero, AppDomain.GetCurrentThreadId());
}
}
private static IntPtr MessageBoxHookProc(int nCode, IntPtr wParam, IntPtr lParam)
{
if (nCode < 0)
{
return CallNextHookEx(_hHook, nCode, wParam, lParam);
}
CWPRETSTRUCT msg = (CWPRETSTRUCT)Marshal.PtrToStructure(lParam, typeof(CWPRETSTRUCT));
IntPtr hook = _hHook;
if (msg.message == (int)CbtHookAction.HCBT_ACTIVATE)
{
try
{
CenterWindow(msg.hwnd);
}
finally
{
UnhookWindowsHookEx(_hHook);
_hHook = IntPtr.Zero;
}
}
return CallNextHookEx(hook, nCode, wParam, lParam);
}
private static void CenterWindow(IntPtr hChildWnd)
{
Rectangle recChild = new Rectangle(0, 0, 0, 0);
bool success = GetWindowRect(hChildWnd, ref recChild);
int width = recChild.Width - recChild.X;
int height = recChild.Height - recChild.Y;
Rectangle recParent = new Rectangle(0, 0, 0, 0);
success = GetWindowRect(_owner, ref recParent);
System.Drawing.Point ptCenter = new System.Drawing.Point(0, 0);
ptCenter.X = recParent.X + ((recParent.Width - recParent.X) / 2);
ptCenter.Y = recParent.Y + ((recParent.Height - recParent.Y) / 2);
System.Drawing.Point ptStart = new System.Drawing.Point(0, 0);
ptStart.X = (ptCenter.X - (width / 2));
ptStart.Y = (ptCenter.Y - (height / 2));
ptStart.X = (ptStart.X < 0) ? 0 : ptStart.X;
ptStart.Y = (ptStart.Y < 0) ? 0 : ptStart.Y;
int result = MoveWindow(hChildWnd, ptStart.X, ptStart.Y, width,
height, false);
}
}
回答by Chuck Savage
This was answered here for Windows.Formsbut with the following added to your class, you can get it to work in WPF.
这是Windows.Forms 的回答here,但是将以下内容添加到您的类中,您可以让它在 WPF 中工作。
You have to add a reference to System.Windows.Forms
& System.Drawing
for the class above to work and to do the following.
您必须为上面的类添加对System.Windows.Forms
&的引用System.Drawing
才能工作并执行以下操作。
public partial class YourWPFWindow : Window, System.Windows.Forms.IWin32Window
{
public IntPtr Handle
{
get { return new WindowInteropHelper(this).Handle; }
}
}
Then you can call MessageBoxEx with:
然后您可以使用以下命令调用 MessageBoxEx:
MessageBoxEx.Show(this, "Message");
It should show up in the middle of your window.
它应该显示在您的窗口中间。
回答by Rajeesh
Another approach would be to create your own message box window and set window's startup location to center owner. The advantage is you can easily have your styles and customization, without hooking.
另一种方法是创建您自己的消息框窗口并将窗口的启动位置设置为中心所有者。优点是您可以轻松拥有自己的样式和自定义,而无需挂钩。
回答by UuDdLrLrSs
If you're open to using external libraries, one option is the Xceed WPF Toolkit which has a MessageBox that will center properly. It is also very consistent with WPF in general, e.g. it can be styled from XAML.
如果您愿意使用外部库,那么一种选择是 Xceed WPF Toolkit,它有一个可以正确居中的 MessageBox。它在一般情况下也与 WPF 非常一致,例如,它可以从 XAML 中设置样式。
https://github.com/xceedsoftware/wpftoolkit/wiki/MessageBox
https://github.com/xceedsoftware/wpftoolkit/wiki/MessageBox
Usage
The MessageBox mimics the behavior of the System.Windows.MessageBox closely. You use similar syntax to create and show a message box.
MessageBoxResult result = Xceed.Wpf.Toolkit.MessageBox.Show("Hello world!", "Extended WPF ToolKit MessageBox", MessageBoxButton.OK, MessageBoxImage.Question); MessageBoxResult result = Xceed.Wpf.Toolkit.MessageBox.Show("Hello world!", "Extended WPF ToolKit MessageBox", MessageBoxButton.OK); MessageBoxResult result = Xceed.Wpf.Toolkit.MessageBox.Show("Hello world!", "Extended WPF ToolKit MessageBox"); MessageBoxResult result = Xceed.Wpf.Toolkit.MessageBox.Show("Hello world!");
用法
MessageBox 密切模仿 System.Windows.MessageBox 的行为。您可以使用类似的语法来创建和显示消息框。
MessageBoxResult result = Xceed.Wpf.Toolkit.MessageBox.Show("Hello world!", "Extended WPF ToolKit MessageBox", MessageBoxButton.OK, MessageBoxImage.Question); MessageBoxResult result = Xceed.Wpf.Toolkit.MessageBox.Show("Hello world!", "Extended WPF ToolKit MessageBox", MessageBoxButton.OK); MessageBoxResult result = Xceed.Wpf.Toolkit.MessageBox.Show("Hello world!", "Extended WPF ToolKit MessageBox"); MessageBoxResult result = Xceed.Wpf.Toolkit.MessageBox.Show("Hello world!");
The centering on parent window appears to be automatic.
以父窗口为中心似乎是自动的。
回答by chainerlt
In addition to Framnk's answer
除了弗兰克的回答
This part doesn't work on multiple screens
这部分在多个屏幕上不起作用
ptStart.X = (ptStart.X < 0) ? 0 : ptStart.X;
ptStart.Y = (ptStart.Y < 0) ? 0 : ptStart.Y;
here's a quickfix:
这是一个快速修复:
var allScreens = System.Windows.Forms.Screen.AllScreens;
ptStart.X = allScreens.All(a => a.WorkingArea.Left > ptStart.X) ? allScreens.Min(a => a.WorkingArea.Left) : ptStart.X;
ptStart.X = allScreens.All(a => a.WorkingArea.Right - width < ptStart.X) ? allScreens.Max(a => a.WorkingArea.Right) - width : ptStart.X;
ptStart.Y = allScreens.All(a => a.WorkingArea.Top > ptStart.Y) ? allScreens.Min(a => a.WorkingArea.Top) : ptStart.Y;
ptStart.Y = allScreens.All(a => a.WorkingArea.Bottom - height < ptStart.Y) ? allScreens.Max(a => a.WorkingArea.Bottom) - height : ptStart.Y;