Эта программа, "27 LISWatch.exe" (см. листинг на рис. 27-5), полезная утилита, ко торая отслеживает следующие окна: активное, находящееся в фокусе и захватившее мышь. Файлы исходного кода и ресурсов этой программы находятся в каталоге 27 LISWatch на компакт-диске, прилагаемом к книге. После запуска LISWatch открывает диалоговое окно, показанное ниже.
Получив сообщение WM_INITDIALOG, это окно вызывает SetTimer, чтобы создать таймер, срабатывающий два раза в секунду. А когда от таймера поступает сообщение WM_TIMER, обновляется содержимое диалогового окна — сведения об активном окне, окне в фокусе и окне, захватившем мышь В нижней части диалогового окна также сообщается, какое окно находится сейчас на переднем плане. Поэкспериментируйте с этой утилитой, просто щелкая окна, созданные различными приложениями. При этом Вы заметите, что LISWatch корректно сообщает информацию об окнах независимо от того, какой поток создал то или иное окно
Самая интересная часть кода этой программы выполняется при приеме сообще ния. WM_TIMER, поэтому, когда я буду давать пояснения, посматривайте на исходный код функции Dlg_ОпТimеr. И пока считайте, что глобальная переменная g_dwThread IdAttachTo равна 0. Ее назначение я объясню позже.
Так как у каждого потока свой набор переменных локалыюго состояния ввода, Dlg_OnTimer сначала вызывает GetForegroundWindow для определения окна, с которым имеетдело пользователь. GetForegroundWindow всегда возвращаетдействичелышй описатель окна независимо от того, какой поток создал это окно или вызвал эту функцию
Полученный таким образом описатель передается в GetWindowThreadProcessId, чтобы выяснить, какой поток связан с RIT. Далее LISWatch, вызвав AttachThreadInput, подключяется к переменным локального состояния ввода потока, связанного с RIT. После этого поток LISWatch может вызывать GetFocus, GetActiveWindow и GetCapture — любая и,з них возвращает действительный описатель окна. Вспомогательная функция CalcWndText формирует строки с именами классов и заголовками окон Потом эти строки показываются в диалоговом окне LISWatch И, наконец, перед самым возвратом управления Dlg_OnTimer снова вызыват: AttachThreadInput, на этот раз передавая FALSE в последнем параметре и тем самым отключая два потока друг от друга.