Закрытие окна, когда оно больше не нужно

Это довольно сложный вопрос для описания, и я искал его около часа, но безрезультатно.

По сути, представьте себе небольшое всплывающее окно, такое как панель управления беспроводной связью Windows 7 или ползунок громкости на панели задач (область уведомлений). Когда вы нажимаете на иконку, приложение всплывает с фокусом, а если вы нажмете на него, окно само себя уничтожает.

Я думал, что это легко решить, просто заставив мое окно самоуничтожиться, когда оно потеряет фокус (я слушал WM_KILLFOCUS), но проблема в том, что если щелкнуть значок, мое окно не всегда получает фокус. Поскольку это не так, если пользователь щелкает мой значок, а затем щелкает, потому что это была ошибка (скажем, на рабочем столе), то как я могу закрыть свое приложение?

Я пытался возиться с SPY ++, но проверка приложений для управления громкостью / беспроводным управлением оказалась сложной, поскольку они исчезают, когда я пытаюсь получить дескрипторы их окон / процессов.

Спасибо!


person Mason Blier    schedule 14.06.2010    source источник


Ответы (3)


Обычно это реализуется запуском таймера при создании окна. Если окно получает фокус до срабатывания таймера, это означает, что пользователь взаимодействовал с окном. В этом случае окно просто остановит таймер и уничтожит себя, когда потеряет фокус. В случае, если окно не получило фокуса до срабатывания таймера, окно уничтожит себя по событию таймера.

Это также обычно сочетается с анимацией непрозрачности, так что окно исчезает в ожидании пользователя. Этакая визуальная обратная связь пользователю о том, что его скоро не будет. Однако анимация непрозрачности используется в основном для всплывающих уведомлений и редко используется для окон управления, таких как регулятор громкости.

Альтернативой является принудительная установка фокуса в вашем окне, когда пользователь взаимодействует с вашим значком на панели задач.

Также обратите внимание, что если ваше окно является окном верхнего уровня, предпочтительным сообщением для прослушивания будет не WM_KILLFOCUS, а WM_ACTIVATE и WM_MOUSEACTIVATE. Вы также можете слушать WM_NCACTIVATE, но это у одного есть некоторые особенности, если вы делаете нестандартную неклиентскую область.

Обновление: вы можете установить фокус на свое окно, вызвав либо SetActiveWindow или SetFocus на нем, когда вы его создаете (или когда вы делаете его видимым, если вы его скрываете).

person Franci Penov    schedule 14.06.2010
comment
Ваша идея таймера будет работать, и я могу ее использовать, но, похоже, это не так, как это делают официальные инструменты Windows. Они принудительно устанавливают фокус, что я не уверен, как это сделать. - person Mason Blier; 15.06.2010

Давным-давно я написал встроенную замену диспетчеру задач Windows 3.1, которая выполняла это, обрабатывая WM_ACTIVATEAPP. Попробуйте.

person Aaron Klotz    schedule 14.06.2010
comment
Мое окно никогда не было активировано, когда оно появилось; Теперь я понимаю, что это потому, что я просто скрывал и показывал это, а не воссоздавал. Я не уверен, какая стратегия лучше, так как для ее воссоздания каждый раз требуется, чтобы скрытое окно всегда было запущено, по крайней мере, насколько я могу судить по WPF. - person Mason Blier; 15.06.2010

Вы смотрели во всплывающем окне? Он исчезнет, ​​как только вы щелкнете за его пределами (если вы не установите для StaysOpen значение true).

person Goblin    schedule 14.06.2010
comment
Как я могу создать всплывающее окно, не создавая окно для начала (но имея значок в трее), потому что, если я могу это сделать, я могу эмулировать поведение с обычным окном независимо. - person Mason Blier; 15.06.2010