Est-il un moyen facile de centre MessageBox dans le formulaire parent dans .net 2.0
Réponses
Trop de publicités?J'ai vraiment besoin de cela en C# et a constaté Centre MessageBox C#
Voici une bien formaté version
using System;
using System.Windows.Forms;
using System.Text;
using System.Drawing;
using System.Runtime.InteropServices;
public class MessageBoxEx
{
private static IWin32Window _owner;
private static HookProc _hookProc;
private static IntPtr _hHook;
public static DialogResult Show(string text)
{
Initialize();
return MessageBox.Show(text);
}
public static DialogResult Show(string text, string caption)
{
Initialize();
return MessageBox.Show(text, caption);
}
public static DialogResult Show(string text, string caption, MessageBoxButtons buttons)
{
Initialize();
return MessageBox.Show(text, caption, buttons);
}
public static DialogResult Show(string text, string caption, MessageBoxButtons buttons, MessageBoxIcon icon)
{
Initialize();
return MessageBox.Show(text, caption, buttons, icon);
}
public static DialogResult Show(string text, string caption, MessageBoxButtons buttons, MessageBoxIcon icon, MessageBoxDefaultButton defButton)
{
Initialize();
return MessageBox.Show(text, caption, buttons, icon, defButton);
}
public static DialogResult Show(string text, string caption, MessageBoxButtons buttons, MessageBoxIcon icon, MessageBoxDefaultButton defButton, MessageBoxOptions options)
{
Initialize();
return MessageBox.Show(text, caption, buttons, icon, defButton, options);
}
public static DialogResult Show(IWin32Window owner, string text)
{
_owner = owner;
Initialize();
return MessageBox.Show(owner, text);
}
public static DialogResult Show(IWin32Window owner, string text, string caption)
{
_owner = owner;
Initialize();
return MessageBox.Show(owner, text, caption);
}
public static DialogResult Show(IWin32Window owner, string text, string caption, MessageBoxButtons buttons)
{
_owner = owner;
Initialize();
return MessageBox.Show(owner, text, caption, buttons);
}
public static DialogResult Show(IWin32Window owner, string text, string caption, MessageBoxButtons buttons, MessageBoxIcon icon)
{
_owner = owner;
Initialize();
return MessageBox.Show(owner, text, caption, buttons, icon);
}
public static DialogResult Show(IWin32Window owner, string text, string caption, MessageBoxButtons buttons, MessageBoxIcon icon, MessageBoxDefaultButton defButton)
{
_owner = owner;
Initialize();
return MessageBox.Show(owner, text, caption, buttons, icon, defButton);
}
public static DialogResult Show(IWin32Window owner, string text, string caption, MessageBoxButtons buttons, MessageBoxIcon icon, MessageBoxDefaultButton defButton, MessageBoxOptions options)
{
_owner = owner;
Initialize();
return MessageBox.Show(owner, text, caption, buttons, icon,
defButton, 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.Handle, ref recParent);
Point ptCenter = new Point(0, 0);
ptCenter.X = recParent.X + ((recParent.Width - recParent.X) / 2);
ptCenter.Y = recParent.Y + ((recParent.Height - recParent.Y) / 2);
Point ptStart = new 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);
}
}
Depuis le premier résultat retourné par Google:
Un Messagebox est toujours centré sur l'écran. Vous pouvez fournir un propriétaire, mais c'est juste pour l'ordre-Z, pas de centrage. La seule façon est d'utiliser Win32 crochets et centre de vous-même. Vous pouvez trouver le code de le faire en ligne si vous recherchez pour cela.
Beaucoup plus facile est de simplement écrire votre propre boîte de message de la classe et ajouter le centrage de la fonctionnalité. Ensuite, vous pouvez également ajouter de la valeur par défaut de sous-titrage, Ne pas montrer de nouveau-case et de les rendre non modale.
"Win32 crochets" se réfère probablement à l'aide d' SetWindowsHookEx
comme le montre cet exemple.
Mais pourquoi s'arrêter avec MessageBox de mise en œuvre? Utilisation de la classe ci-dessous comme ceci:
private void OnFormClosing(object sender, FormClosingEventArgs e)
{
DialogResult dg;
using (DialogCenteringService centeringService = new DialogCenteringService(this)) // center message box
{
dg = MessageBox.Show(this, "Are you sure?", "Confirm exit", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
}
if (dg == DialogResult.No)
{
e.Cancel = true;
}
}
Le code que vous pouvez utiliser avec n'importe quoi qui montre les fenêtres de dialogue, même s'ils sont détenus par un autre thread (notre application a plusieurs threads UI):
(Ici est la mise à jour du code qui prend de surveiller les zones de travail en compte, de sorte que le dialogue n'est pas centré entre les deux écrans est en partie hors de l'écran. Avec elle, vous aurez besoin d' enum SetWindowPosFlags
, ce qui est en dessous)
public class DialogCenteringService : IDisposable
{
private readonly IWin32Window owner;
private readonly HookProc hookProc;
private readonly IntPtr hHook = IntPtr.Zero;
public DialogCenteringService(IWin32Window owner)
{
if (owner == null) throw new ArgumentNullException("owner");
this.owner = owner;
hookProc = DialogHookProc;
hHook = SetWindowsHookEx(WH_CALLWNDPROCRET, hookProc, IntPtr.Zero, GetCurrentThreadId());
}
private IntPtr DialogHookProc(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);
}
}
return CallNextHookEx(hook, nCode, wParam, lParam);
}
public void Dispose()
{
UnhookWindowsHookEx(hHook);
}
private void CenterWindow(IntPtr hChildWnd)
{
Rectangle recChild = new Rectangle(0, 0, 0, 0);
bool success = GetWindowRect(hChildWnd, ref recChild);
if (!success)
{
return;
}
int width = recChild.Width - recChild.X;
int height = recChild.Height - recChild.Y;
Rectangle recParent = new Rectangle(0, 0, 0, 0);
success = GetWindowRect(owner.Handle, ref recParent);
if (!success)
{
return;
}
Point ptCenter = new Point(0, 0);
ptCenter.X = recParent.X + ((recParent.Width - recParent.X) / 2);
ptCenter.Y = recParent.Y + ((recParent.Height - recParent.Y) / 2);
Point ptStart = new Point(0, 0);
ptStart.X = (ptCenter.X - (width / 2));
ptStart.Y = (ptCenter.Y - (height / 2));
//MoveWindow(hChildWnd, ptStart.X, ptStart.Y, width, height, false);
Task.Factory.StartNew(() => SetWindowPos(hChildWnd, (IntPtr)0, ptStart.X, ptStart.Y, width, height, SetWindowPosFlags.SWP_ASYNCWINDOWPOS | SetWindowPosFlags.SWP_NOSIZE | SetWindowPosFlags.SWP_NOACTIVATE | SetWindowPosFlags.SWP_NOOWNERZORDER | SetWindowPosFlags.SWP_NOZORDER));
}
// some p/invoke
// ReSharper disable InconsistentNaming
public delegate IntPtr HookProc(int nCode, IntPtr wParam, IntPtr lParam);
public delegate void TimerProc(IntPtr hWnd, uint uMsg, UIntPtr nIDEvent, uint dwTime);
private const int WH_CALLWNDPROCRET = 12;
// ReSharper disable EnumUnderlyingTypeIsInt
private enum CbtHookAction : int
// ReSharper restore EnumUnderlyingTypeIsInt
{
// ReSharper disable UnusedMember.Local
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
// ReSharper restore UnusedMember.Local
}
[DllImport("kernel32.dll")]
static extern int GetCurrentThreadId();
[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")]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int x, int y, int cx, int cy, SetWindowPosFlags uFlags);
[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;
};
// ReSharper restore InconsistentNaming
}
[Flags]
public enum SetWindowPosFlags : uint
{
// ReSharper disable InconsistentNaming
/// <summary>
/// If the calling thread and the thread that owns the window are attached to different input queues, the system posts the request to the thread that owns the window. This prevents the calling thread from blocking its execution while other threads process the request.
/// </summary>
SWP_ASYNCWINDOWPOS = 0x4000,
/// <summary>
/// Prevents generation of the WM_SYNCPAINT message.
/// </summary>
SWP_DEFERERASE = 0x2000,
/// <summary>
/// Draws a frame (defined in the window's class description) around the window.
/// </summary>
SWP_DRAWFRAME = 0x0020,
/// <summary>
/// Applies new frame styles set using the SetWindowLong function. Sends a WM_NCCALCSIZE message to the window, even if the window's size is not being changed. If this flag is not specified, WM_NCCALCSIZE is sent only when the window's size is being changed.
/// </summary>
SWP_FRAMECHANGED = 0x0020,
/// <summary>
/// Hides the window.
/// </summary>
SWP_HIDEWINDOW = 0x0080,
/// <summary>
/// Does not activate the window. If this flag is not set, the window is activated and moved to the top of either the topmost or non-topmost group (depending on the setting of the hWndInsertAfter parameter).
/// </summary>
SWP_NOACTIVATE = 0x0010,
/// <summary>
/// Discards the entire contents of the client area. If this flag is not specified, the valid contents of the client area are saved and copied back into the client area after the window is sized or repositioned.
/// </summary>
SWP_NOCOPYBITS = 0x0100,
/// <summary>
/// Retains the current position (ignores X and Y parameters).
/// </summary>
SWP_NOMOVE = 0x0002,
/// <summary>
/// Does not change the owner window's position in the Z order.
/// </summary>
SWP_NOOWNERZORDER = 0x0200,
/// <summary>
/// Does not redraw changes. If this flag is set, no repainting of any kind occurs. This applies to the client area, the nonclient area (including the title bar and scroll bars), and any part of the parent window uncovered as a result of the window being moved. When this flag is set, the application must explicitly invalidate or redraw any parts of the window and parent window that need redrawing.
/// </summary>
SWP_NOREDRAW = 0x0008,
/// <summary>
/// Same as the SWP_NOOWNERZORDER flag.
/// </summary>
SWP_NOREPOSITION = 0x0200,
/// <summary>
/// Prevents the window from receiving the WM_WINDOWPOSCHANGING message.
/// </summary>
SWP_NOSENDCHANGING = 0x0400,
/// <summary>
/// Retains the current size (ignores the cx and cy parameters).
/// </summary>
SWP_NOSIZE = 0x0001,
/// <summary>
/// Retains the current Z order (ignores the hWndInsertAfter parameter).
/// </summary>
SWP_NOZORDER = 0x0004,
/// <summary>
/// Displays the window.
/// </summary>
SWP_SHOWWINDOW = 0x0040,
// ReSharper restore InconsistentNaming
}
Essayez, c'est assez simple, pour justifier le temps...
C'est pour l'API Win32, écrit en C. le Traduire comme vous avez besoin...
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;
Ajoutez à cela l'WndProc code... Vous pouvez définir la position que vous le souhaitez, dans ce cas, il vient de centres sur la fenêtre principale du programme. Il va le faire pour tout messagebox, ou fichier de dialogue ouvrir et enregistrer, et probablement quelques autres contrôles natifs. Je ne suis pas sûr, mais je pense que vous pourriez avoir besoin d'inclure COMMCTRL ou COMMDLG pour l'utiliser, au moins, vous serez, si vous voulez des dialogues ouvrir/enregistrer.
J'ai testé en regardant les informer des codes et des hwndFrom de NMHDR, puis a décidé qu'il était tout aussi efficace, et beaucoup plus facile, ne pas le faire. Si vous voulez vraiment être très précis, dire la fonction FindWindow pour rechercher une légende unique (titre), vous donnez à la fenêtre que vous souhaitez trouver.
Ce feu avant la messagebox est dessiné à l'écran, donc si vous avez défini un indicateur global pour indiquer lorsqu'une action est effectuée par votre code, et de regarder pour une légende unique, vous assurez-vous que les actions que vous prenez ne se fera qu'une fois (il y aura probablement plusieurs déclarants). Je n'ai pas exploré en détail, mais j'ai réussi obtenir CreateWindow de mettre une zone d'édition sur un messagebox boîte de dialogue. Il semblait à sa place comme un rat oreille greffée sur la colonne vertébrale d'un clone de porc, mais il fonctionne. Faire les choses de cette manière peut être beaucoup plus facile que d'avoir à rouler votre propre.
Crow.
EDIT: Petite correction à faire en sorte que le droit de la fenêtre est gérée. Assurez-vous que les parents s'occupe d'accord dans l'ensemble, et cela devrait fonctionner. Pour moi, même avec deux instances du même programme...