2012-04-17 2 views
3

У меня есть приложение C# WinForms, которое появляется в системном трее. Приложение скрывает основную форму под нагрузку:PostMessage для скрытой формы не работает в первый раз

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

Для одной и той же основной формы, я переопределен в WndProc, чтобы поймать пользовательское сообщение окна (это сообщение регистрируется в Windows, с помощью Win32 API вызова RegisterWindowMessage).

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: Кажется, что это не имеет никакого отношения к Hide on load. Даже без начального Скрытия моя основная форма WndProc начнет принимать сообщения только после того, как она будет скрыта и повторно показана ...

+0

'SendMessage (HWND_BROADCAST, msg, NULL, NULL)' вместо 'PostMessage' работает с самого начала, но я хочу опубликовать сообщение. –

ответ

6

После создания небольшого тестового приложения, я обнаружил, что PostMessage() к HWND_BROADCAST не приходит в Form.WndProc если Form.ShowInTaskbar установлен в false в то время как SendMessage() к HWND_BROADCAST делают.

Несмотря на то, что заметка MSDN о отправке или отправке сообщений в HWND_BROADCAST точно такая же.

Таким образом, это не имело никакого отношения к скрытию или показу формы, и это похоже на другую недокументированную функцию Windows API.

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.

+0

это даже случается в моем приложении, когда я не скрываю окно в обработчике нагрузки ... Я попытался воссоздать проблему в новом приложении WinForms, и там PostMessage, похоже, работает ... Может быть, есть что-то в моем приложении, которое блокирует цикл сообщения. –

3

Есть что-то еще, вызов Hide() в обработчике событий Load формы фактически не скрывает окно. Попробуйте это с помощью небольшого тестового приложения Winforms, чтобы это увидеть.

Если вы фактически не видите окно, то простое объяснение состоит в том, что окно просто не было создано. Это полностью объясняет, почему сообщение не получено. Переопределите OnHandleCreated() и установите точку останова на ней, чтобы проверить эту теорию. Метод Create() должен быть вызван для создания собственного окна, очевидно, что ваш обработчик событий NotifyIcon является первым. Это происходит, когда вы вызываете Application.Run(), но не передаете экземпляр формы.

Отметьте this answer, чтобы убедиться, что эта форма создана, но не сделана видимой.

+0

+1 Хм, похоже, что 'SetVisibleCore' - это способ получить созданный дескриптор без отображения формы. Это часть знаний, которые мне не хватало. –

+0

Я установил WindowState в Minimized в дизайнере, это оставляет кнопку программы на панели задач. Вызов Hide в обработчике нагрузки, удаляет кнопку из панели задач. –

+1

Я обнаружил, что, когда 'Form.ShowInTaskbar' установлен на' false', форма не получает сообщений. Когда установлено значение «true», он делает это. –