2009-02-19 12 views
17

Ich habe eine 700w x 300h WPF Anwendung und kann es überall auf meinem großen Bildschirm ziehen.Wie bekomme ich MessageBox.Show() in der Mitte meiner WPF-Anwendung angezeigt?

Wenn meine Anwendung ausführt:

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

die mesage-Box in der Mitte meines Bildschirm erscheint, die nicht einmal in der Nähe der Anwendung sein kann oder sich.

Wie kann ich meine MessageBox stattdessen in der Mitte meiner Anwendung erscheinen lassen?

+2

Edward, konnten Sie dieses Problem lösen? Ich habe versucht, mit Application.Current.MainWindow, aber keine Wirkung, die Nachrichten-Box immer noch auf dem Bildschirm zentriert und nicht meine WPF-Anwendung Hauptfenster. – byte

+0

Hier ist ein Verweis auf einen Stackoverflow Q & A, die tatsächlich funktioniert (für mich) http://StackOverflow.com/Questions/1629213/Messagebox-show – invalidusername

Antwort

-9

Wenn Ihre App mehrere Fenster hat, möchten Sie vielleicht Application.Current.MainWindow verwenden:

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

Funktioniert das tatsächlich? Es tut es nicht für mich – Karsten

+2

Diese Antwort tut nicht, was das OP verlangte. –

+2

Dadurch wird die MessageBox nicht im Hauptfenster zentriert, sondern nur garantiert, dass sie sich vor dem Hauptfenster befindet. – Curtis

6

Das war answered here for Windows.Forms aber mit dem Ihrer Klasse hinzugefügt folgenden, können Sie es in WPF zu arbeiten.

Sie müssen eine Referenz zu System.Windows.Forms & System.Drawing für die Klasse oben hinzufügen, um zu arbeiten und Folgendes zu tun.

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

Dann können Sie MessageBoxEx rufen mit:

MessageBoxEx.Show(this, "Message"); 

Es sollte in der Mitte des Fensters angezeigt.

+0

dies die richtige Antwort markiert werden soll – msnider

14

Hier ist eine Version der Klasse MessageBoxEx Helfer in dem anderen Thread geschrieben, die Nachricht WPF-Stil Boxen verwendet (Beachten Sie, dass Sie noch System.Drawing verweisen müssen):

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

Dies funktioniert gut, obwohl ich nicht sicher bin, warum ' ptStart.X = (ptStart.X <0)? 0: ptStart.X; ' ' ptStart.Y = (ptStart.Y <0)? 0: ptStart.Y; 'ist in' CenterWindow (IntPtr hHHildWnd) ', als ob der Benutzer mehrere Bildschirme hat und sein primärer Bildschirm als etwas anderes als die linke Seite der Anwendung in den Negativen sein könnte und Sie möchten, dass das Meldungsfenster in der angezeigt wird negative x-Position, sonst wird es nicht in der Mitte der Anwendung kommen, wenn es auf einem Bildschirm die linke der primären oder darunter in Bezug auf die Notwendigkeit einer negativen y. – Birdbuster

+0

@Birdbuster hat es wirklich für dich funktioniert? Ich habe es versucht und die Nachrichtenbox erscheint immer in meinem oberen linken Bereich meines Bildschirms (nicht Fenster) – Mirza

+0

@Mirza Ja, total für mich gearbeitet. Sie verwenden die Versionen, die Sie im Besitzerfenster übergeben, oder? Scheint wie eine dumme Frage, aber vielleicht nur eine Übersehung an deinem Ende? Ich änderte auch private statische void CenterWindow (IntPtr hChildWnd) {} wie in meinem Kommentar angegeben, so dass, wenn mein Fenster in der negativen x oder y-Achse in Bezug auf Windows "Haupt" -Bildschirm war es immer noch in der Mitte richtig angezeigt wurde. – Birdbuster

0

Neben Framnk's answer

Dieses Teil funktioniert nicht auf mehreren Bildschirmen

ptStart.X = (ptStart.X < 0) ? 0 : ptStart.X; 
ptStart.Y = (ptStart.Y < 0) ? 0 : ptStart.Y; 

hier ist ein 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

Ein anderer Ansatz wäre, ein eigenes Meldungsfenster zu erstellen und den Startort des Fensters auf den Besitzer des Zentrums zu setzen. Der Vorteil ist, dass Sie Ihre Stile und Anpassungen ohne Haken haben können.

+0

Ihr sollte minimalen Code zur Verfügung stellen, um Ihre Antwort zu stützen. Was auch immer du hier gepostet hast, das kann als Kommentar kommen, aber nicht als Antwort. – Raju

Verwandte Themen