PostMessage到隐藏表单第一次不起作用

时间:2012-04-17 12:55:49

标签: c# c++ windows-messages

我有一个出现在系统托盘中的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()隐藏窗体后继续工作。

任何人都可以解释为什么在Hide()事件处理程序的第一个MainForm_Load之后它无效吗?我是否过早隐藏表格?

EDIT1:好像它与加载时隐藏无关。即使没有最初的隐藏,我的主要形式WndProc只会在隐藏并重新显示之后开始接受广播帖子...

3 个答案:

答案 0 :(得分:8)

创建小型测试应用程序后,我发现如果PostMessage()设置为HWND_BROADCAST,则Form.WndProcForm.ShowInTaskbar不会到达false虽然SendMessage()HWND_BROADCAST会这样做。

即使MSDN关于向HWND_BROADCAST发送或发送消息的说明完全相同。

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

答案 1 :(得分:4)

还有其他事情发生,在表单的Load事件处理程序中调用Hide()实际上并不隐藏窗口。尝试使用Winforms应用程序来查看此内容。

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

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

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