Как отменить MessageBox

Есть ли способ отменить окно сообщения, отображаемое MessageBox.Show()?

Я думаю, что это возможно, отправив закрытое "сообщение" (WM_?) В родную очередь сообщений win32? Как именно?

@EdPlunkett, это WinForms ...

Don Box 18.05.2018 15:35

Там есть ссылка на вопрос WPF, но решение этого не очень хорошее, он хочет, чтобы вы создали настраиваемое окно для имитации диалогового окна.

Don Box 18.05.2018 15:37

Упс, я не должен был отказываться от закрытого голосования. Прочтите код в принятом ответе. В winforms нет ничего особенного. Если, как вы говорите в своем вопросе, вы хотите знать, «как именно» вызывать FindWIndow () и SendMessage (), этот ответ скажет вам, как именно. То есть, если WPF не использует класс окна "# 32770"; вы это проверили?

15ee8f99-57ff-4f92-890c-b56153 18.05.2018 15:40
stackoverflow.com/a/12555069/17034
Hans Passant 18.05.2018 15:42

Оконные системы Windows API и WPF не связаны. О чем вы спрашиваете? Однако, независимо от этого, используйте автоматизацию пользовательского интерфейса, если вам нужно автоматизировать пользовательский интерфейс.

IInspectable 18.05.2018 15:42

Я не уверен, что назвал бы это автоматизацией пользовательского интерфейса. Это больше о передаче сообщения в окно, когда у вас нет его дескриптора.

Paul Sanders 18.05.2018 19:01

@PaulSanders: Я не уверен, как бы вы назвали процесс взаимодействия с пользовательским интерфейсом через код. Этот является называется UI Automation. Вы должны настроить WinEvents, чтобы сообщать о создании интересующего окна, а затем вызывать в нем любую операцию, которую вы сочтете нужной. Очевидно, это предполагает фреймворк, основанный на нативных HWND. ОП отметила вопрос о технологиях, использующих разные оконные системы. По-видимому, они не знали, в чем их проблема, и не отвечали, когда их просили уточнить.

IInspectable 19.05.2018 14:12

@IInspectable, извините за то, что не ответил раньше. Да, я полностью осознаю, что Windows API и WPF - это не одно и то же :) Я не уверен, как может работать UI Automation, не могли бы вы предоставить некоторые подробности?

Don Box 19.05.2018 14:34
Автоматизация пользовательского интерфейса. Приятно, что вы объяснили, что вы полностью осознали, что Windows API и WPF - это не одно и то же. Не сразу очевидно, почему вы тогда решили не отвечать на вопрос, который на самом деле был задан: какой из них вы используете?
IInspectable 19.05.2018 14:42

@IInspectable А, ладно, из цитируемого обращения к MessageBox.Show я предположил, что это Winforms, извините. Однако Эта страница, похоже, подразумевает, что даже в WPF это старомодное доброе окно сообщений Win32 за кулисами.

Paul Sanders 19.05.2018 18:53

@IInspectable в моем вопросе есть тег WPF, что означает, что я работаю с приложением WPF. Однако Win32 API можно использовать и в WPF.

Don Box 20.05.2018 15:12
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
12
130
2

Ответы 2

Самым простым решением с использованием WinApi было бы:

    [return: MarshalAs(UnmanagedType.Bool)]
    [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
    static extern bool PostMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);


    [DllImport("user32.dll", SetLastError = true)]
    static extern IntPtr FindWindow(string lpClassName, string lpWindowName);

    private const int WM_CLOSE = 0x10;
    private const string MessageBoxTitle = "UniqueTitle123";

    void CloseMessageBox()
    {
        var hwnd = FindWindow(null, MessageBoxTitle);

        if (hwnd != IntPtr.Zero)
        {
            PostMessage(hwnd, WM_CLOSE, IntPtr.Zero, IntPtr.Zero);
        }
    }

Вам нужно вызвать окно сообщений с помощью MessageBoxTitle:

MessageBox.Show("This gonna close itself", MessageBoxTitle);

А потом где-то:

CloseMessageBox();

Пример использования:

Task.Run(async () =>
{
    await Task.Delay(2000).ConfigureAwait(false);
    CloseMessageBox();
});

MessageBox.Show("This closes in 2 seconds", MessageBoxTitle);

Имейте в виду, что если есть другое окно с тем же заголовком, что и ваше окно сообщения, то вызов CloseMessageBox () закроет это окно вместо вашего окна сообщения. Решение простое, но выберите заголовок msgbox таким образом, чтобы была очень малая вероятность столкновения имени с другими окнами в системе, например. YourAppName-51245 должен быть в порядке.

Спасибо. Довольно близко :) Правильный способ - создать подкласс WndProc и получить HWND окна сообщения

Don Box 18.05.2018 16:42

@DonBox Я не понимаю, как вы это сделаете. Вызов MessageBox.Show является модальным - для подкласса нет «формы». Я делаю это, устанавливая временный оконный крючок, а затем перехватываю WM_INITDIALOG. Вероятно, это проще сделать в машинном коде, чем в .net. Кроме того, этот ответ можно улучшить, если вы знаете имя класса окон сообщений. Вероятно, это номер 32770, сказал бы вам Spy ++.

Paul Sanders 18.05.2018 16:59

PS: Вы также можете отправить WM_COMMAND, который позволит вам имитировать нажатие определенной кнопки.

Paul Sanders 18.05.2018 17:25

@PaulSanders Я не думаю, что вам нужен оконный крючок. Вы можете сделать это: stackoverflow.com/questions/624367/… Моя идея состоит в том, чтобы перехватить событие, отправленное на собственный HWND окна, чтобы получить HWND диалога. Когда у нас есть HWND диалогового окна, мы можем закрыть диалоговое окно, когда это необходимо.

Don Box 18.05.2018 17:48

@DonBox Я думаю, вам нужно немного прояснить это. Я вообще этого не понимаю.

Paul Sanders 18.05.2018 18:06

Я думал, что опубликую решение для этого, поскольку я считаю, что это лучший способ сделать это. Ответ выше хрупкий. Я предоставил код на родном C++, так как мне не хватает навыков .net для ответа на C#. Возможно, кто-нибудь, у кого есть такие навыки, будет переводить. Обратите внимание: код не является потокобезопасным. Если вы создаете окна сообщений более чем в одном потоке, вам придется быть немного умнее.

static HHOOK my_hook;
static HWND message_box_hwnd;

// Hook proc
LRESULT CALLBACK MyHookProc (int code, WPARAM wParam, LPARAM lParam)
{
    if (code < 0)
        return CallNextHookEx (tdata->tcpHook, code, wParam, lParam);

    CWPSTRUCT *msg = (CWPSTRUCT *) lParam;
    LRESULT result = CallNextHookEx (tdata->tcpHook, code, wParam, lParam);

    if (msg->message == WM_INITDIALOG)
    {
        message_box_hwnd = msg->hwnd;
        UnhookWindowsHookEx (my_hook);
        my_hook = NULL;
    }

    return result;
}

my_hook = SetWindowsHookEx (WH_CALLWNDPROC, MyHookProc, NULL, GetCurrentThreadId ());
MessageBox (...);

И, конечно же, в вашей процедуре таймера или что-то еще:

PostMessage (message_box_hwnd, WM_CLOSE, 0, 0);

или (скажем):

PostMessage (message_box_hwnd, WM_COMMAND, IDCANCEL, 0);

Честно говоря, ничего особенного.

Другие вопросы по теме