Определить окна приложения
Я использую CBT Windows Hook для обнаружения событий создания / удаления окна /min-max/move-size.
Я хорошо работаю, но мне нужно отфильтровать, чьи события поступают из обычных виджетов. Практически мне нужно, чтобы CBT-ловушка уведомляла только о тех окнах, которые пользователь считает окнами.
Проблема, с которой я сталкиваюсь, сводит меня с ума, поскольку я постоянно получаю ложные события, даже если я фильтрую окно следующим образом:
BOOL FilterWindowHandle(HWND hwnd)
{
// Filtered window having WS_CHILDWINDOW style
if ((GetWindowLongPtr(hwnd, GWL_STYLE) & WS_CHILDWINDOW) != 0)
return (TRUE);
// Filtered window not having WS_CAPTION style
if ((GetWindowLongPtr(hwnd, GWL_STYLE) & WS_CAPTION) == 0)
return (TRUE);
// Not filtered
return (FALSE);
}
Эти ложные события происходят от теневых эффектов, меню и всего, что отображается на экране.
Есть ли надежный метод для фильтрации реальных окон от его дочерних элементов?
Я избегаю испытания WS_BORDER
или подобное, так как некоторые приложения могут создавать свое главное окно без рамки... или я ошибаюсь?
2 ответа
Для "вещей, которые пользователь считает окнами" хорошо подходит набор окон, отображаемый в списке Alt-Tab (или на панели задач).
Эта статья OldNewThing объясняет правила (хотя правила не являются фиксированными или гарантированно останутся прежними):
Общее правило:
Для каждого видимого окна поднимайтесь по его цепочке владельцев, пока не найдете корневого владельца. Затем спускайтесь вниз по видимой последней активной всплывающей цепочке, пока не найдете видимое окно. Если вы вернулись к тому, с чего начали, поместите окно в список Alt+Tab.
Это можно переопределить с помощью явных стилей окна:
Окно с расширенным стилем WS_EX_TOOLWINDOW обрабатывается так, как если бы оно было невидимым, даже если оно есть. Окно с расширенным стилем WS_EX_APPWINDOW обрабатывается так, как будто оно не имеет владельца, даже если оно имеет.
См. Полный пост OldNewThing, из которого взяты эти две цитаты, для более подробной информации.
Полезный критерий, который я использовал в прошлом, состоит в том, чтобы проверить, является ли окно окном верхнего уровня, то есть его родитель является NULL.