web-dev-qa-db-fra.com

Pourquoi MessageBox n'est-il pas TopMost?

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);
}
41
Sayse

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 le MessageBox to Block les fenêtres jusqu'à ce que le message soit fermé normalement ce sera le mode 'application modale'.

Liens de référence

  1. Forum MSDN - Comment afficher un MessageBox comme fenêtre supérieure
  2. SO - C # MessageBox à l'avant lorsque l'application est réduite au platea
29
Harsh Baid

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:

  • la fenêtre est un écran de démarrage et ne doit pas être étroitement associée à votre logique métier
  • la fenêtre est créée par une autre classe ou bibliothèque que l'actuelle
  • la fenêtre est hors de votre contrôle, c'est-à-dire à partir d'une bibliothèque tierce (native)

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 ).

67
Abel

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.

3
Sina Iravanian

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);
        }
    }
1
Alen Wesker

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:

Exemples Top-Most-MessageBox

1
Michael Hall