如何取消MessageBox

时间:2018-05-18 13:32:02

标签: .net wpf winapi

有没有办法取消MessageBox.Show()显示的消息框?

我在想通过向本机win32消息队列发送一个关闭的“消息”(WM_?)是可能的吗?究竟是怎么回事?

2 个答案:

答案 0 :(得分: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:

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标题的方式是,与系统f.ex中的其他窗口名称冲突的可能性非常小。 YourAppName-51245应该没问题。

答案 1 :(得分:0)

我以为我会发布一个' windows hook'解决这个问题,因为我认为这是最好的方法。上面的答案是脆弱的。我已经在本机C ++中提供了代码,因为我缺乏在C#中回答的.net技能。也许拥有这些技能的人会翻译。注意,代码不是线程安全的。如果你在多个线程上创建消息框,那么你必须更聪明一点。

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

真的没那么多。