J'ai récemment découvert que par défaut, les MessageBox n'étaient pas le formulaire le plus en haut lorsqu'ils étaient affichés par défaut et je me demandais si quelqu'un connaissait des circonstances où vous ne voudriez pas que la boîte de message soit affichée au-dessus d'autres fenêtres?
J'ai trouvé le problème lorsque j'ai commencé à afficher des écrans de démarrage lors du chargement d'une application, et il semblait que mon programme était toujours en cours d'exécution, mais il y avait un MessageBox
derrière l'écran de démarrage qui attendait une entrée. L'écran de démarrage était montré sur un fil différent du fil qui a appelé la boîte de message, donc j'imagine que c'est pourquoi il n'est pas apparu au-dessus du splash; mais cela n'explique toujours pas pourquoi MessageBox n'a pas le MB_TOPMOST
drapeau par défaut?
Modifier
Pour mieux clarifier: à la fin, j'ai dû faire quelque chose de similaire à la fin pour créer une boîte de message, le code n'est pas exactement correct comme écrit de la mémoire)
[DllImport("User32.dll")]
private int extern MessageBox(windowhandle, message, caption, flag);
public static void MessageBox(windowhandle, string message, string caption)
{
MessageBox(windowhandle, message,caption, MB_TOPMOST);
}
Pour afficher le MessageBox en premier lieu pour l'application
Code
//Should be MessageBox.Show() below
MessageBox.Show(this, "My top most message");
Raison de ne pas être MB_TOPMOST
par défaut
Si MB_TOPMOST sera par défaut, le
MessageBox
s'affichera en mode "système modal" et ce sera exactement au-dessus de cette forme et les effets secondaires sont que le mode "système modal" provoquera leMessageBox
to Block les fenêtres jusqu'à ce que le message soit fermé normalement ce sera le mode 'application modale'.
Liens de référence
Les solutions proposées fonctionnent si vous pouvez obtenir une poignée ou une référence à la fenêtre dans laquelle la boîte de dialogue est censée apparaître. Cependant, cela peut ne pas toujours être possible ou facile à réaliser:
Dans de tels scénarios, vous pourriez utiliser l'API Win232 MessageBox
de User32.dll
, Mais une solution gérée plus simple est également disponible:
MessageBox.Show(new Form { TopMost = true }, "Hello, I'm on top!");
Le code new Form { TopMost = true }
Créera un formulaire masqué avec la propriété MB_TOPMOST
, Héritée par la boîte de dialogue de la boîte de message. En conséquence, il apparaîtra au-dessus de toutes vos autres fenêtres. L'utilisation de new Form()
inline n'a aucun effet secondaire, n'a aucune apparence visuelle et sera détruite normalement via le garbage collector.
Remarque: si vous n'êtes pas déjà dans un formulaire, n'oubliez pas l'espace de noms, c'est System.Windows.Forms.MessageBox
, Pas System.Windows.MessageBox
! (merci, ser1 ).
Lors de l'affichage de MessageBox
, fournissez son propriétaire comme premier argument. Par exemple, lors de l'appel à partir d'un appel d'instance Form
:
MessageBox.Show(this, "Message");
Fournissez une référence à la fenêtre la possédant comme premier argument.
Les boîtes de message (et les formulaires modaux en général) apparaissent pas en haut de toutes les fenêtres de votre application. Ils n'apparaissent qu'au-dessus de leur propriétaire. Si vous souhaitez que votre boîte de message (ou d'autres formulaires modaux) soit au-dessus de votre écran de démarrage, définissez son propriétaire sur l'instance de formulaire de démarrage.
J'essaie de coller un morceau de code plus complet, ça marche vraiment
[CLSCompliant(false)]
[DllImport("user32.dll", EntryPoint = "MessageBox")]
public static extern int MessageBoxUser32(int hWnd, String text, String caption, uint type);
const uint MB_TOPMOST = 0x00040000;
const uint MB_OK = 0x00000000;
const uint MB_OKCANCEL = 0x00000001;
const uint MB_ABORTRETRYIGNORE = 0x00000002;
const uint MB_YESNOCANCEL = 0x00000003;
const uint MB_YESNO = 0x00000004;
const uint MB_RETRYCANCEL = 0x00000005;
public static void ShowMessageBox(string message, bool topMost = true
, string title = null, MessageBoxButtons buttons = MessageBoxButtons.OK)
{
if(topMost)
{
uint mbv = MB_TOPMOST;
if (buttons == MessageBoxButtons.OK)
mbv |= MB_OK;
if (buttons == MessageBoxButtons.OKCancel)
mbv |= MB_OKCANCEL;
if (buttons == MessageBoxButtons.AbortRetryIgnore)
mbv |= MB_ABORTRETRYIGNORE;
if (buttons == MessageBoxButtons.YesNoCancel)
mbv |= MB_YESNOCANCEL;
if (buttons == MessageBoxButtons.YesNo)
mbv |= MB_YESNO;
if (buttons == MessageBoxButtons.RetryCancel)
mbv |= MB_RETRYCANCEL;
MessageBoxUser32(0, message, title == null ? string.Empty : title, MB_TOPMOST);
}
else
{
MessageBox.Show(message, title == null ? string.Empty : title, buttons);
}
}
La réponse donnée ci-dessus est évidemment correcte moins le fait qu'il doit appeler System.iDisposable.Dispose sur l'objet new Form.
MessageBoxButtons buttons = MessageBoxButtons.YesNo;
MessageBoxIcon icon = MessageBoxIcon.Error;
string message = Resources.ResourceManager.GetString("MESSAGE");
string caption = Resources.ResourceManager.GetString("TITLE");
DialogResult result;
Form form;
using (form = new Form())
{
form.TopMost = true;
result = MessageBox.Show(form, caption, message, buttons, icon);
}
if (result == DialogResult.Yes)
{
// do something with the result
}
Pour plus: