I have a C# WinForms application that appears in the system tray. The application is hiding the main form on load:
private void MainForm_Load(object sender, System.EventArgs e)
{
Hide();
}
For the same main form, I've overriden the WndProc to catch a custom window message (that message is registered to Windows with the RegisterWindowMessage
Win32 API call).
protected override void WndProc(ref Message m)
{
if (m.Msg == WM_MYCUSTOM_MESSAGE)
{
// Handle custom message
}
}
From an external C++ application I'm broadcasting the same custom window message with PostMessage.
UINT msg = RegisterWindowMessage(L"WM_MYCUSTOM_MESSAGE");
PostMessage(HWND_BROADCAST, msg, NULL, NULL);
When I execute the above code after the C# application was first started, it doesn't get into the WndProc. After the main form is shown (by a double click on the system tray icon, which in essence does a Show()
), catching the broadcast message works and keeps working after hiding the form with Hide()
.
Can anyone explain me why it doesn't work after the first Hide()
from the MainForm_Load
event handler? Am I hiding the form too early?
EDIT1: It seems like it has nothing to do with the Hide on load. Even without the initial Hide, my main form WndProc will only start accepting broadcast posts after it is hidden and re-shown...
After creating a small test application, I have found out that PostMessage()
to HWND_BROADCAST
doesn't arrive in Form.WndProc
if Form.ShowInTaskbar
is set to false
while SendMessage()
to HWND_BROADCAST
does.
Even though the MSDN note about sending or posting messages to HWND_BROADCAST is exactly the same.
So it had nothing to do with the hiding or showing of the form and this seems like another undocumented feature of the Windows API.
There's something else going on, calling Hide() in the form's Load event handler doesn't actually hide the window. Try it with a little test Winforms app to see this.
If you don't actually see the window then the simple explanation is that the window just wasn't created. Which entirely explains why the message isn't being received. Override OnHandleCreated() and set a breakpoint on it to double-check this theory. The Show() method must be called to create the native window, apparently your NotifyIcon event handler is the first one to do so. Which happens when you call Application.Run() but don't pass a form instance.
Check this answer for a way to ensure that that a form is created but not made visible.
With Broadcast, the message is posted to all top-level windows in the system, including disabled or invisible unowned windows, overlapped windows, and pop-up windows. The message is not posted to child windows (according to MSDN). Use an application, like WinSpy to make sure your windows is a top level one right after the initial startup and hiding. Also this http://blog.paulbetts.org/index.php/2010/07/20/the-case-of-the-disappearing-onload-exception-user-mode-callback-exceptions-in-x64/ might (or might not) give some insights on how the OnLoad works... Seems it's a little bit more complicated. Try to hide the MainForm somewhere else, not on the OnLoad.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With