yes visual personalizados personalizado messageboxbuttons ejemplos critical botones winforms messagebox

winforms - personalizados - messagebox visual basic



Winforms: ¿cómo puedo hacer que MessageBox aparezca centrado en MainForm? (4)

Winforms: ¿cómo puedo hacer que los cuadros de diálogo aparezcan centrados en MainForm? Eso es opuesto a estar basado en el valor predeterminado de Windows Normal que los representa en el centro de la pantalla.

En mi caso, tengo un pequeño formulario principal que, por ejemplo, puede colocarse en una esquina, se muestra la ventana emergente MessageBox que parece estar muy lejos.


Es posible con algunas porciones de P / Invoke y la magia proporcionada por Control.BeginInvoke (). Agregue una nueva clase a su proyecto y pegue este código:

using System; using System.Text; using System.Drawing; using System.Windows.Forms; using System.Runtime.InteropServices; class CenterWinDialog : IDisposable { private int mTries = 0; private Form mOwner; public CenterWinDialog(Form owner) { mOwner = owner; owner.BeginInvoke(new MethodInvoker(findDialog)); } private void findDialog() { // Enumerate windows to find the message box if (mTries < 0) return; EnumThreadWndProc callback = new EnumThreadWndProc(checkWindow); if (EnumThreadWindows(GetCurrentThreadId(), callback, IntPtr.Zero)) { if (++mTries < 10) mOwner.BeginInvoke(new MethodInvoker(findDialog)); } } private bool checkWindow(IntPtr hWnd, IntPtr lp) { // Checks if <hWnd> is a dialog StringBuilder sb = new StringBuilder(260); GetClassName(hWnd, sb, sb.Capacity); if (sb.ToString() != "#32770") return true; // Got it Rectangle frmRect = new Rectangle(mOwner.Location, mOwner.Size); RECT dlgRect; GetWindowRect(hWnd, out dlgRect); MoveWindow(hWnd, frmRect.Left + (frmRect.Width - dlgRect.Right + dlgRect.Left) / 2, frmRect.Top + (frmRect.Height - dlgRect.Bottom + dlgRect.Top) / 2, dlgRect.Right - dlgRect.Left, dlgRect.Bottom - dlgRect.Top, true); return false; } public void Dispose() { mTries = -1; } // P/Invoke declarations private delegate bool EnumThreadWndProc(IntPtr hWnd, IntPtr lp); [DllImport("user32.dll")] private static extern bool EnumThreadWindows(int tid, EnumThreadWndProc callback, IntPtr lp); [DllImport("kernel32.dll")] private static extern int GetCurrentThreadId(); [DllImport("user32.dll")] private static extern int GetClassName(IntPtr hWnd, StringBuilder buffer, int buflen); [DllImport("user32.dll")] private static extern bool GetWindowRect(IntPtr hWnd, out RECT rc); [DllImport("user32.dll")] private static extern bool MoveWindow(IntPtr hWnd, int x, int y, int w, int h, bool repaint); private struct RECT { public int Left; public int Top; public int Right; public int Bottom; } }

Uso de muestra:

private void button1_Click(object sender, EventArgs e) { using (new CenterWinDialog(this)) { MessageBox.Show("Nobugz waz here"); } }

Tenga en cuenta que este código funciona para cualquiera de los cuadros de diálogo de Windows. MessageBox, OpenFormDialog, FolderBrowserDialog, PrintDialog, ColorDialog, FontDialog, PageSetupDialog, SaveFileDialog.


Escribe tu propio cuadro de mensajes. Una forma y una etiqueta deberían hacerlo. ¿O también necesitas globalizarlo?


Esto es para Win32 API, escrito en C. Traducirlo como lo necesite ...

case WM_NOTIFY:{ HWND X=FindWindow("#32770",NULL); if(GetParent(X)==H_frame){int Px,Py,Sx,Sy; RECT R1,R2; GetWindowRect(hwnd,&R1); GetWindowRect(X,&R2); Sx=R2.right-R2.left,Px=R1.left+(R1.right-R1.left)/2-Sx/2; Sy=R2.bottom-R2.top,Py=R1.top+(R1.bottom-R1.top)/2-Sy/2; MoveWindow(X,Px,Py,Sx,Sy,1); } } break;

Añádalo al código de WndProc ... Puede establecer la posición que desee, en este caso solo se centra en la ventana principal del programa. Hará esto para cualquier cuadro de mensaje, o abrir archivo / guardar diálogo, y probablemente algunos otros controles nativos. No estoy seguro, pero creo que puede necesitar incluir COMMCTRL o COMMDLG para usar esto, al menos, lo hará si desea abrir / guardar cuadros de diálogo.

Experimenté con mirar los códigos de notificación y hwndFrom de NMHDR, luego decidí que era igual de eficaz, y mucho más fácil, no hacerlo. Si realmente desea ser muy específico, indique a FindWindow que busque un título único (título) que le dé a la ventana que desea que encuentre.

Esto se dispara antes de dibujar el cuadro de mensaje en la pantalla, por lo que si establece un indicador global para indicar cuándo su código realiza la acción y busca un título único, asegúrese de que las acciones que realice solo se produzcan una vez (es probable que haya múltiples notificadores). No he explorado esto en detalle, pero logré que CreateWindow pusiera un cuadro de edición en un cuadro de diálogo de mensaje / Parecía tan fuera de lugar como una oreja de rata injertada en la espina dorsal de un cerdo clonado, pero funciona. Hacer las cosas de esta manera puede ser mucho más fácil que tener que hacer las suyas.

Cuervo.

EDITAR: Corrección pequeña para asegurarse de que se maneja la ventana correcta. Asegúrese de que los controladores de los padres estén de acuerdo en todo momento, y esto debería funcionar bien. Lo hace por mí, incluso con dos instancias del mismo programa ...


La clase demostró ser aplicable a otras dos situaciones. Tenía un FolderBrowserDialog que quería que fuera más grande, y quería que apareciera cerca de la esquina superior izquierda del cuadro de diálogo principal (cerca del botón en el que hago clic para abrirlo).

Copié la clase CenterWinDialog e hice dos nuevas clases. Una clase cambia el tamaño del diálogo, y la otra cambia su posición a un desplazamiento específico de la forma principal. Este es el uso:

using (new OffsetWinDialog(this) { PreferredOffset = new Point(75, 75 )}) using (new SizeWinDialog(this) { PreferredSize = new Size(400, 600)}) { DialogResult result = dlgFolderBrowser.ShowDialog(); if (result == DialogResult.Cancel) return; }

y estas son las dos clases que se basaron en la original.

class OffsetWinDialog : IDisposable { private int mTries = 0; private Form mOwner; public OffsetWinDialog(Form owner) { mOwner = owner; owner.BeginInvoke(new MethodInvoker(findDialog)); } public Point PreferredOffset { get; set; } private void findDialog() { // Enumerate windows to find the message box if (mTries < 0) return; EnumThreadWndProc callback = new EnumThreadWndProc(checkWindow); if (EnumThreadWindows(GetCurrentThreadId(), callback, IntPtr.Zero)) { if (++mTries < 10) mOwner.BeginInvoke(new MethodInvoker(findDialog)); } } private bool checkWindow(IntPtr hWnd, IntPtr lp) { // Checks if <hWnd> is a dialog StringBuilder sb = new StringBuilder(260); GetClassName(hWnd, sb, sb.Capacity); if (sb.ToString() != "#32770") return true; // Got it Rectangle frmRect = new Rectangle(mOwner.Location, mOwner.Size); RECT dlgRect; GetWindowRect(hWnd, out dlgRect); MoveWindow(hWnd, frmRect.Left + PreferredOffset.X, frmRect.Top + PreferredOffset.Y, dlgRect.Right - dlgRect.Left, dlgRect.Bottom - dlgRect.Top, true); return false; } public void Dispose() { mTries = -1; } // P/Invoke declarations private delegate bool EnumThreadWndProc(IntPtr hWnd, IntPtr lp); [DllImport("user32.dll")] private static extern bool EnumThreadWindows(int tid, EnumThreadWndProc callback, IntPtr lp); [DllImport("kernel32.dll")] private static extern int GetCurrentThreadId(); [DllImport("user32.dll")] private static extern int GetClassName(IntPtr hWnd, StringBuilder buffer, int buflen); [DllImport("user32.dll")] private static extern bool GetWindowRect(IntPtr hWnd, out RECT rc); [DllImport("user32.dll")] private static extern bool MoveWindow(IntPtr hWnd, int x, int y, int w, int h, bool repaint); private struct RECT { public int Left; public int Top; public int Right; public int Bottom; } }

y

class SizeWinDialog : IDisposable { private int mTries = 0; private Form mOwner; public SizeWinDialog(Form owner) { mOwner = owner; mOwner.BeginInvoke(new Action(findDialog)); } public Size PreferredSize { get; set; } private void findDialog() { // Enumerate windows to find the message box if (mTries < 0) return; EnumThreadWndProc callback = new EnumThreadWndProc(checkWindow); if (EnumThreadWindows(GetCurrentThreadId(), callback, IntPtr.Zero)) { if (++mTries < 10) mOwner.BeginInvoke(new MethodInvoker(findDialog)); } } private bool checkWindow(IntPtr hWnd, IntPtr lp) { // Checks if <hWnd> is a dialog StringBuilder sb = new StringBuilder(260); GetClassName(hWnd, sb, sb.Capacity); if (sb.ToString() != "#32770") return true; // Got it Rectangle frmRect = new Rectangle(mOwner.Location, mOwner.Size); RECT dlgRect; GetWindowRect(hWnd, out dlgRect); SetWindowPos(new HandleRef(this, hWnd), new HandleRef(), dlgRect.Left, dlgRect.Top, PreferredSize.Width, PreferredSize.Height, 20 | 2); return false; } public void Dispose() { mTries = -1; } // P/Invoke declarations private delegate bool EnumThreadWndProc(IntPtr hWnd, IntPtr lp); [DllImport("user32.dll")] private static extern bool EnumThreadWindows(int tid, EnumThreadWndProc callback, IntPtr lp); [DllImport("kernel32.dll")] private static extern int GetCurrentThreadId(); [DllImport("user32.dll")] private static extern int GetClassName(IntPtr hWnd, StringBuilder buffer, int buflen); [DllImport("user32.dll")] private static extern bool GetWindowRect(IntPtr hWnd, out RECT rc); [DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)] public static extern bool SetWindowPos(HandleRef hWnd, HandleRef hWndInsertAfter, int x, int y, int cx, int cy, int flags); private struct RECT { public int Left; public int Top; public int Right; public int Bottom; } }