5

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

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

对于同一个主窗体,我重写了 WndProc 以捕获自定义窗口消息(该消息通过RegisterWindowMessageWin32 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()

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

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

4

3 回答 3

10

在创建了一个小型测试应用程序后,我发现如果设置为while to do, PostMessage()toHWND_BROADCAST不会到达。Form.WndProcForm.ShowInTaskbarfalseSendMessage()HWND_BROADCAST

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

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

于 2012-04-17T14:22:44.457 回答
4

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

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

检查此答案以确保创建表单但不使其可见。

于 2012-04-17T13:50:43.723 回答
1

使用广播,消息被发布到系统中的所有顶级窗口,包括禁用或不可见的无主窗口、重叠窗口和弹出窗口。该消息不会发布到子窗口(根据 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 上。

于 2012-04-17T13:41:33.267 回答