2009-02-19 1 views
17

У меня есть 700w x 300h WPF-приложение и его можно перетащить в любом месте на моем большом экране.Как заставить MessageBox.Show() появляться в середине моего приложения WPF?

Когда мое приложение выполняет: появляется

MessageBox.Show("Sorry, this function is not yet implemented."); 

окна в электронном письме середины моего экрана, который может или не может даже быть рядом с самим приложением.

Как я могу получить сообщение MessageBox в середине моего приложения вместо этого?

+2

Эдвард, смогли ли вы решить эту проблему? Я попытался использовать Application.Current.MainWindow, но без эффекта, Message Box по-прежнему центрируется на экране, а не в главном окне приложения WPF. – byte

+0

Вот ссылка на QQ, который фактически работает (для меня) http://stackoverflow.com/questions/1629213/messagebox-show – invalidusername

ответ

-9

Если ваше приложение имеет несколько окон, вы можете захотеть использовать Application.Current.MainWindow:

MessageBox.Show(Application.Current.MainWindow, "Can't login with given names.", "Login Failure", MessageBoxButton.OK, MessageBoxImage.Error, MessageBoxResult.Cancel); 
+15

Действительно ли это работает? Это не делает это для меня – Karsten

+2

Этот ответ не делает то, о чем попросил ОП. –

+2

Это не сосредотачивает MessageBox на главном окне, просто гарантирует, что он находится перед Главным окном. Ответ – Curtis

6

Это было answered here for Windows.Forms, но со следующим добавлены в класс, вы можете заставить его работать в WPF.

Вы должны добавить ссылку на System.Windows.Forms & System.Drawing для класса выше, чтобы работать и сделать следующее.

public partial class YourWPFWindow : Window, System.Windows.Forms.IWin32Window 
{ 
    public IntPtr Handle 
    { 
     get { return new WindowInteropHelper(this).Handle; } 
    } 
} 

Тогда вы можете позвонить MessageBoxEx с:

MessageBoxEx.Show(this, "Message"); 

Он должен появиться в середине окна.

+0

Это должно быть маркированы правильный ответ – msnider

14

Вот версия вспомогательного класса MessageBoxEx размещен в другом потоке, который использует WPF стиля окна сообщений (Обратите внимание, что вам все еще нужно ссылаться 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

Это прекрасно работает, хотя я не знаю, почему ' ptStart.X = (ptStart.X <0)? 0: ptStart.X; ' ' ptStart.Y = (ptStart.Y <0)? 0: ptStart.Y; 'находится в' CenterWindow (IntPtr hHhildWnd) ', как если бы у пользователя было несколько экранов и его основной экран был чем-то иным, чем левое большинство приложений могло быть отрицательным, и вы хотели бы, чтобы окно сообщения отображалось в отрицательная позиция x, иначе она не появится в центре приложения, если она на экране слева от первичной или ниже нее в этом отношении в связи с необходимостью отрицательного y. – Birdbuster

+0

@ Birdbuster это действительно сработало для вас? Я пробовал это, и ящик сообщений всегда отображался в моем верхнем левом углу экрана (а не в окне). – Mirza

+0

@Mirza Да, я полностью работал на меня. Вы используете версии, в которых вы проходите прямо в окне владельца? Может быть, это глупый вопрос, но, возможно, просто взгляд на вашем конце? Я также модифицировал private static void CenterWindow (IntPtr hChildWnd) {}, как указано в моем комментарии, так что если мое окно находилось в отрицательной оси x или y по отношению к окну «главный» экран, оно по-прежнему отображалось посередине правильно. – Birdbuster

0

В дополнении к Framnk's answer

Эта часть не работает на нескольких экранах

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; 
1

Другим подходом было бы создать собственное окно окна сообщения и установить место запуска окна для владельца центра. Преимущество заключается в том, что вы можете легко создавать свои стили и настраивать, не зацепляясь.

+0

ваш должен предоставить минимальный код для поддержки вашего ответа. что вы когда-либо публиковали здесь, это может стать комментарием, но не ответом. – Raju

Смежные вопросы