2009-02-19 12 views
17

Ho un'applicciazione WPF da 700w x 300h e posso trascinarlo ovunque sul mio grande schermo.Come richiamare MessageBox.Show() nel mezzo della mia applicazione WPF?

Quando la mia applicazione esegue:

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

il mesage appare al centro della mia schermo, che può o non può essere ancora vicino l'applicazione stessa.

Come posso visualizzare il MessageBox nel mezzo dell'applicazione ?

+2

Edward, sei riuscito a risolvere questo problema? Ho provato ad utilizzare Application.Current.MainWindow ma nessun effetto, la casella dei messaggi è ancora centrata nello schermo e non nella finestra principale dell'applicazione WPF. – byte

+0

Ecco un riferimento a una sessione di domande e risposte StackOverflow che funziona effettivamente (per me) http://stackoverflow.com/questions/1629213/messagebox-show – invalidusername

risposta

-9

Se la vostra applicazione ha diverse finestre, si potrebbe desiderare di utilizzare Application.Current.MainWindow:

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

Funziona davvero? Non lo fa per me – Karsten

+2

Questa risposta non fa quello che l'OP chiedeva. –

+2

Questo non centra MessageBox nella finestra principale, solo garantisce che è davanti alla finestra principale. La risposta di – Curtis

6

Questo è stato answered here for Windows.Forms ma con le seguenti aggiunte alla classe, è possibile farlo funzionare in WPF.

È necessario aggiungere un riferimento a System.Windows.Forms & System.Drawing per la classe di cui sopra per funzionare e per eseguire quanto segue.

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

Poi si può chiamare MessageBoxEx con:

MessageBoxEx.Show(this, "Message"); 

dovrebbe mostrare nel mezzo della finestra.

+0

Questo dovrebbe essere contrassegnato la risposta corretta – msnider

14

Ecco una versione della classe di supporto MessageBoxEx pubblicato in altro thread che utilizza finestre di messaggio stile WPF (Si noti che è ancora necessario fare riferimento 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

Questa grande opera, anche se io non sono sicuro perché ' ptStart.X = (ptStart.X <0)? 0: ptStart.X; ' ' ptStart.Y = (ptStart.Y <0)? 0: ptStart.Y; 'si trova in' CenterWindow (IntPtr hHhildWnd) 'come se l'utente avesse più schermi e avesse il suo schermo principale come qualcosa di diverso da quello a sinistra in cui l'applicazione potrebbe trovarsi nei negativi e vorresti che la finestra di messaggio venisse visualizzata nel posizione x negativa altrimenti non si troverà al centro dell'applicazione se si trova su uno schermo a sinistra del primario o sotto di esso in relazione al bisogno di un y negativo. – Birdbuster

+0

@Birdbuster ha funzionato davvero per te? Ho provato questo e la messagebox appare sempre nella mia parte superiore sinistra del mio schermo (non finestra) – Mirza

+0

@Mirza Sì ha funzionato completamente per me. Stai utilizzando le versioni in cui passi nella finestra del proprietario, giusto? Potrebbe sembrare una domanda sciocca, ma forse solo un eccesso di vista sulla tua fine? Ho anche modificato il private static void CenterWindow (IntPtr hChildWnd) {} come indicato nel mio commento in modo tale che se la mia finestra fosse nell'asse xey negativo rispetto alla schermata "main" di Windows, veniva comunque visualizzata correttamente nel mezzo. – Birdbuster

0

Oltre a Framnk's answer

Questa parte non funziona su più schermi

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

ecco una 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

Un altro approccio potrebbe essere quello di creare la finestra della finestra di messaggio e impostare la posizione di avvio della finestra al centro del proprietario. Il vantaggio è che puoi facilmente avere i tuoi stili e personalizzazioni, senza aggancio.

+0

il tuo dovrebbe fornire codice minimo per supportare la tua risposta. qualunque cosa tu abbia postato qui, può essere un commento ma non una risposta. – Raju

Problemi correlati