2009-02-19 24 views
17

Tengo una aplicación WPF de 700w x 300h y puedo arrastrarla a cualquier parte de mi pantalla grande.¿Cómo hacer que MessageBox.Show() aparezca en el medio de mi aplicación WPF?

Cuando mi aplicación ejecuta: aparece

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

el mesage en el medio de la pantalla de mi, que puede o no puede ser incluso cerca de la propia aplicación.

¿Cómo puedo hacer que mi MessageBox aparezca en el medio de mi aplicación ?

+2

Edward, ¿pudo resolver este problema? Intenté usar Application.Current.MainWindow pero sin efecto, el cuadro de mensaje todavía se centra en la pantalla y no en la ventana principal de mi aplicación WPF. – byte

+0

Aquí hay una referencia a un stackoverflow Q & A que realmente funciona (para mí) http://stackoverflow.com/questions/1629213/messagebox-show – invalidusername

Respuesta

-9

Si su aplicación tiene varias ventanas, es posible que desee utilizar Application.Current.MainWindow:

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

¿Esto realmente funciona? No lo hace por mí – Karsten

+2

Esta respuesta no hace lo que el OP solicitó. –

+2

Esto no centra el MessageBox en la ventana principal, solo garantiza que está frente a la ventana principal. Ver respuesta – Curtis

6

Ésta era answered here for Windows.Forms pero con las siguientes añadido a su clase, se puede conseguir que funcione en WPF.

Debe agregar una referencia a System.Windows.Forms & System.Drawing para la clase de arriba para trabajar y para hacer lo siguiente.

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

A continuación, puede llamar MessageBoxEx con:

MessageBoxEx.Show(this, "Message"); 

debe aparecer en el medio de la ventana.

+0

Esto se debe marcar la respuesta correcta – msnider

14

Aquí hay una versión de la clase de ayuda MessageBoxEx publicado en el otro hilo que utiliza cuadros de mensaje estilo WPF (Tenga en cuenta que todavía necesita hacer referencia 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

Esto funciona muy bien, aunque no estoy seguro de por qué ' ptStart.X = (ptStart.X <0)? 0: ptStart.X; ' ' ptStart.Y = (ptStart.Y <0)? 0: ptStart.Y; 'está en' CenterWindow (IntPtr hHhildWnd) 'como si el usuario tiene múltiples pantallas y tiene su pantalla principal como algo distinto de la izquierda más la aplicación podría estar en los negativos y que querría el cuadro de mensaje que aparezca en el posición x negativa de lo contrario no aparecerá en el centro de la aplicación si está en una pantalla a la izquierda de la primaria o debajo de ella en relación con la necesidad de una y negativa. – Birdbuster

+0

@Birdbuster ¿realmente funcionó para ti? Probé esto y el cuadro de mensaje siempre aparece en mi superior izquierda de la pantalla (no ventana) – Mirza

+0

@Mirza Sí totalmente trabajó para mí. Está utilizando las versiones donde pasa en la ventana del propietario, ¿verdad? Puede parecer una pregunta tonta, pero tal vez solo una visión excesiva de tu parte. También he modificado CenterWindow static void privada (IntPtr hChildWnd) {} como se dice en mi comentario de modo que si mi ventana estaba en las x negativas o eje y en relación con las ventanas de la pantalla "principal" todavía apareció en el medio correctamente. – Birdbuster

0

Además de Framnk's answer

Esta parte no funciona en múltiples pantallas

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

aquí hay un 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

Otro enfoque sería crear su propia ventana de cuadro de mensaje y establecer la ubicación de inicio de la ventana como propietario del centro. La ventaja es que puede tener fácilmente sus estilos y personalización, sin enganchar.

+0

debe proporcionar un código mínimo para apoyar su respuesta. lo que haya publicado aquí, puede ir como comentario pero no como respuesta. – Raju

Cuestiones relacionadas