【问题标题】:PostMessage to hidden form doesn't work the first timePostMessage 到隐藏表单第一次不起作用
【发布时间】:2012-04-17 12:55:49
【问题描述】:

我有一个出现在系统托盘中的 C# WinForms 应用程序。应用程序在加载时隐藏主窗体:

private void MainForm_Load(object sender, System.EventArgs e)
{
    Hide();
}

对于同一个主窗体,我重写了 WndProc 以捕获自定义窗口消息(该消息通过 RegisterWindowMessage Win32 API 调用注册到 Windows)。

protected override void WndProc(ref Message m)
{
    if (m.Msg == WM_MYCUSTOM_MESSAGE)
    {
        // Handle custom message
    }
}

从外部 C++ 应用程序中,我使用 PostMessage 广播相同的自定义窗口消息。

UINT msg = RegisterWindowMessage(L"WM_MYCUSTOM_MESSAGE");
PostMessage(HWND_BROADCAST, msg, NULL, NULL);

当我在 C# 应用程序首次启动后执行上述代码时,它并没有进入 WndProc。显示主窗体后(通过双击系统托盘图标,本质上是一个Show()),捕获广播消息工作并在使用Hide()隐藏窗体后继续工作。

谁能解释为什么它在MainForm_Load 事件处理程序的第一个Hide() 之后不起作用?我隐藏表格太早了吗?

EDIT1:它似乎与加载时隐藏无关。即使没有初始隐藏,我的主窗体 WndProc 也只会在隐藏并重新显示后开始接受广播帖子...

【问题讨论】:

  • SendMessage(HWND_BROADCAST, msg, NULL, NULL) 而不是 PostMessage 从一开始就有效,但我想发布消息。

标签: c# c++ windows-messages


【解决方案1】:

创建一个小型测试应用程序后,我发现如果 Form.ShowInTaskbar 设置为 falseSendMessage()HWND_BROADCASTPostMessage()HWND_BROADCAST 不会到达 Form.WndProc

尽管关于向 HWND_BROADCAST 发送或发布消息的 MSDN 注释完全相同。

所以它与表单的隐藏或显示无关,这似乎是 Windows API 的另一个未记录的功能。

【讨论】:

    【解决方案2】:

    还有其他事情发生,在表单的 Load 事件处理程序中调用 Hide() 并没有真正隐藏窗口。用一个小的测试 Winforms 应用试试看。

    如果您实际上没有看到该窗口,那么简单的解释是该窗口没有被创建。这完全解释了为什么没有收到消息。覆盖 OnHandleCreated() 并在其上设置断点以仔细检查该理论。必须调用 Show() 方法来创建本机窗口,显然您的 NotifyIcon 事件处理程序是第一个这样做的。当您调用 Application.Run() 但不传递表单实例时会发生这种情况。

    检查this answer 以确保表单已创建但不可见。

    【讨论】:

    • +1 嗯,看起来SetVisibleCore 是在不显示表单的情况下创建句柄的方法。这就是我所缺少的知识。
    • 我已在设计器中将 WindowState 设置为最小化,这会将程序按钮留在任务栏中。在加载处理程序中调用 Hide,从任务栏中删除按钮。
    • 我发现当Form.ShowInTaskbar设置为false时,表单收不到Post广播。当设置为true 时会这样做。
    • "CreateControl 如果控件的 Visible 属性为 false,则不会创建控件句柄。您可以调用 CreateHandle 方法或访问 Handle 属性来创建控件的句柄,而不管控件的可见性如何"
    • @BenVoigt:我发现它与 Hide() 或表单的可见性无关。造成此问题的是“ShowInTaskbar”属性。
    【解决方案3】:

    使用广播,消息被发布到系统中的所有顶级窗口,包括禁用或不可见的无主窗口、重叠窗口和弹出窗口。该消息不会发布到子窗口(根据 MSDN)。使用 WinSpy 之类的应用程序确保您的窗口在初始启动和隐藏后立即处于顶层。此外,这个http://blog.paulbetts.org/index.php/2010/07/20/the-case-of-the-disappearing-onload-exception-user-mode-callback-exceptions-in-x64/ 可能(或可能不会)对 OnLoad 的工作原理提供一些见解......似乎它有点复杂。尝试将 MainForm 隐藏在其他地方,而不是 OnLoad。

    【讨论】:

    • 当我没有在加载处理程序中隐藏窗口时,它甚至发生在我的应用程序中......我试图在新的 WinForms 应用程序中重新创建问题,并且 PostMessage 似乎工作...也许我的应用程序中有一些东西锁定了消息循环。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-12-11
    • 1970-01-01
    • 2011-05-02
    • 1970-01-01
    • 1970-01-01
    • 2017-02-04
    • 1970-01-01
    相关资源
    最近更新 更多