我有一个700w x 300h的WPF应用程序,可以将它拖到我的大屏幕上的任何地方。
当我的应用程序执行时:
MessageBox.Show("Sorry, this function is not yet implemented.");
消息框出现在我的屏幕的中间,甚至可能在应用程序本身附近。
如何让我的MessageBox出现在应用程序的中间?
答案 0 :(得分:16)
这是在另一个使用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);
}
}
答案 1 :(得分:7)
这是answered here for Windows.Forms但是在您的课程中添加了以下内容后,您可以在WPF中使用它。
您必须添加对System.Windows.Forms
&amp;的引用。 System.Drawing
为上述课程开展工作并执行以下操作。
public partial class YourWPFWindow : Window, System.Windows.Forms.IWin32Window
{
public IntPtr Handle
{
get { return new WindowInteropHelper(this).Handle; }
}
}
然后你可以用:
调用MessageBoxExMessageBoxEx.Show(this, "Message");
它应该显示在窗口中间。
答案 2 :(得分:1)
另一种方法是创建自己的消息框窗口并将窗口的启动位置设置为中心所有者。优点是您可以轻松地进行样式和自定义,而无需挂钩。
答案 3 :(得分:0)
此部分不适用于多个屏幕
ptStart.X = (ptStart.X < 0) ? 0 : ptStart.X;
ptStart.Y = (ptStart.Y < 0) ? 0 : ptStart.Y;
这是一个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;
答案 4 :(得分:0)
如果您愿意使用外部库,则一个选择是Xceed WPF Toolkit,它具有一个MessageBox,它将正确居中。总体而言,它与WPF也非常一致,例如可以从XAML设置样式。
https://github.com/xceedsoftware/wpftoolkit/wiki/MessageBox
用法
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!");
父窗口居中显示为自动。
答案 5 :(得分:-10)
如果您的应用有多个窗口,则可能需要使用Application.Current.MainWindow
:
MessageBox.Show(Application.Current.MainWindow, "Can't login with given names.", "Login Failure", MessageBoxButton.OK, MessageBoxImage.Error, MessageBoxResult.Cancel);