2. При перехвате каждого сообщения функция-ловушка посылает окну (форме) frmMessages сообщение WM_SPY_NOTIFY (определенное пользователем, точнее, программистом сообщение, листинг 10.12).
Рис. 10.5. Форма перехвата сообщений
Но ведь ловушка предназначена для работы в другом процессе, а если так, то как ей дать знать, какому именно окну посылать сообщения? Для этого и используется именованная проекция файла в память, в которой сохраняются данные, необходимые для ловушки. В проекции файла ловушка также сохраняет информацию о перехваченном сообщении (код и параметры сообщения). Эта информация используется приложением, ведущим слежение. Данные в проекции файла хранятся в виде записи THooklnfo, объявленной в модуле HookData. В этом же модуле объявлены константа с именем проекции файла, код сообщения WM_SPY_NOTIFY (листинг 10.12) и две служебные переменные, использование которых будет пояснено далее.
Листинг 10.12.
Содержимое файла HookData.pas
type
//Структура (запись), которая хранится в разделяемом файле
//и используется для передачи данных между процессами
THookInfo = record
wnd: HWND; //Окно, за которым ведется наблюдение
hook_handle: HHOOK; //Дескриптор ловушки
spy_wnd: HWND; //Окно, уведомляемое о перехвате сообщения
//Следующие поля заполняются при перехвате сообщения
mess: UINT;
wParam: WPARAM;
lParam: LPARAM;
end;
var
//Указатель на разделяемую область памяти
hook_info: ^THookInfo;
//Дескриптор проекции файла в память
hFile: THandle;
const
//Имя проекции файла
strFileMapName = \'TricksDelphi_WinSpy_Mapping\
//Сообщение для уведомления окна-шпиона
WM_SPY_NOTIFY = WM_USER + 1;
Построение фильтра и обработка перехваченных сообщений
Теперь вернемся к приложению-шпиону, а точнее, к той его части, которая отвечает за работу формы, показанной на рис. 10.5.
Начнем с самого простого – управления фильтром сообщений. Он построен по тому же принципу, что управление списками оконных стилей (форма свойств окна, рассмотренная ранее).
Итак, структура, хранящая информацию о сообщении, выглядит следующим образом:
type MessageInfo = record
value: DWORD; //Код сообщения
name: String; //Название сообщения
used: Boolean; //Служебное поле
end;
При написании программы не стояла цель поместить в фильтр все возможные сообщения, поэтому массив messageslist (листинг 10.13) содержит только 16 элементов. При необходимости вы можете добавить нужные сообщения самостоятельно, взяв их обозначения из модуля Windows.