Электронная библиотека книг Александра Фролова и Григория Фролова.
Shop2You.ru Создайте свой интернет-магазин
Библиотека
Братьев
Фроловых

Операционная система Microsoft Windows 3.1 для программиста

© Александр Фролов, Григорий Фролов
Том 13, М.: Диалог-МИФИ, 1993, 284 стр.

[Назад] [Содеожание] [Дальше]

3.6. Фильтры

В операционной системе Windows, в основе которой лежит механизм обмена сообщениями, имеется очень мощное средство, позволяющее организовать фильтрацию или перехват любых сообщений. Причем можно фильтровать сообщения, предназначенные как для некоторых, так и для всех приложений. Вы можете создать свой фильтр, получающий управление до того, как то или иное сообщение достигнет очереди сообщений или перед вызовом соответствующей функции окна. Фильтр может оставить перехваченное сообщение без изменения, изменить его или даже изъять.

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

Для чего можно использовать фильтры?

С помощью фильтров вы можете перехватить сообщения, поступающие в любые диалоговые панели, полосы просмотра, меню и т. п., причем как для отдельного приложения, так и для всех приложений сразу. Можно "отобрать" сообщения у функций GetMessage, PeekMessage, SendMessage. Можно записывать и затем проигрывать события, связанные с перемещением мыши и использованием клавиатуры. Фильтры облегчают создание обучающих приложений, которые работают совместно с обычными приложениями Windows в режиме обучения. Обучающие приложения может контролировать действия пользователя, когда он работает с приложением.

В качестве примера в разделе "Приложение WINHOOK" мы расскажем вам о том, как можно с помощью фильтров переключать раскладку клавиатуры. Мы приведем исходные тексты несложного руссификатора клавиатуры, позволяющего использовать в операционной системе Windows символы кириллицы.

Установка фильтра

Для установки фильтра в операционной системе Windows версии 3.1 следует использовать функцию SetWindowsHookEx (в Windows версии 3.0 для этой цели была предназначена функция SetWindowsHook ):

HHOOK WINAPI SetWindowsHookEx(
  int idHook,            // тип фильтра
  HOOKPROC lpfn,         // адрес функции фильтра
  HINSTANCE hInstance,   // идентификатор приложения
  HTASK hTask); // задача, для которой устанавливается фильтр

Параметр idHook определяет тип встраиваемого фильтра. В качестве значения для этого параметра можно использовать одну из следующих констант:

Константа Назначение фильтра
WH_CALLWNDPROC Для функции окна. Используется в Windows версии 3.0 и 3.1. Можно устанавливать для отдельной задачи или для всей системы
WH_CBT Для обучающих программ. Можно устанавливать для отдельной задачи или для всей системы
WH_DEBUG Для отладкиИспользуется в Windows версии 3.1. Можно устанавливать для отдельной задачи или для всей системы
WH_GETMESSAGE Фильтр сообщений. Получает управление после выборки сообщения функцией GetMessageИспользуется в Windows версии 3.0 и 3.1. Можно устанавливать для отдельной задачи или для всей системы
WH_HARDWARE Фильтр для сообщений, поступающих от нестандартного аппаратного обеспечения, такого как система перьевого ввода. Используется в Windows версии 3.1. Можно устанавливать для отдельной задачи или для всей системы
WH_JOURNALPLAYBACK Фильтр для "проигрывания" событийИспользуется в Windows версии 3.0 и 3.1. Можно устанавливать только для всей системы
WH_JOURNALRECORD Фильтр для записи событийИспользуется в Windows версии 3.0 и 3.1. Можно устанавливать только для всей системы
WH_KEYBOARD Фильтр сообщений, поступающих от клавиатуры. Используется в Windows версии 3.1. Можно устанавливать для отдельной задачи или для всей системы
WH_MOUSE Фильтр сообщений, поступающих от мыши. Используется в Windows версии 3.1. Можно устанавливать для отдельной задачи или для всей системы
WH_MSGFILTER Фильтр сообщений, который получает управление после выборки, но перед обработкой сообщений, поступающих от диалоговых панелей или меню. Используется в Windows версии 3.0 и 3.1. Можно устанавливать для отдельной задачи или для всей системы
WH_SHELL Фильтр для получения различных извещений от операционной системы Windows. Используется в Windows версии 3.1. Можно устанавливать для отдельной задачи или для всей системы
WH_SYSMSGFILTER Фильтр вызывается операционной системой после того, как диалоговая панель или меню получат сообщение, но перед обработкой этого сообщения. Данный фильтр может обрабатывать сообщения для любых запущенных приложений Windows. Используется в Windows версии 3.0 и 3.1. Можно устанавливать только для всей системы

Параметр lpfn функции SetWindowsHookEx должен определять адрес функции встраиваемого фильтра (или, иными словами, функции перехвата сообщений).

Функция фильтра может находиться либо в приложении, устанавливающем фильтр, либо (что значительно лучше) в DLL-библиотеке. Если функция находится в приложении, или в DLL-библиотеке, загружаемой явным образом при помощи функции LoadLibrary, в качестве параметра lpfn следует использовать значение, полученное от функции MakeProcInstance. Если же для импортирования функций из DLL-библиотеки используется библиотека импорта (как в описанном ниже приложении WINHOOK), параметр lpfn может содержать непосредственный указатель на функцию фильтра.

Через параметр hInstance функции SetWindowsHookEx следует передать идентификатор модуля, в котором находится встраиваемая функция фильтра. Если функция фильтра определена внутри приложения, в качестве этого параметра необходимо использовать идентификатор текущей копии приложения, передаваемой через соответствующий параметр функции WinMain. Если же функция фильтра находится в DLL-библиотеке, данный параметр должен содержать идентификатор модуля библиотеки, передаваемый через параметр hInstance функции LibMain.

Последний параметр функции hTask должен содержать идентификатор задачи, для которой определяется функция фильтра. Если последний параметр указан как NULL, фильтр встраивается для всех задач, работающих в системе.

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

HTASK WINAPI GetCurrentTask(void);

Можно определить идентификатор задачи исходя из идентификатора окна, созданного этой задачей. Для этого следует воспользоваться функцией GetWindowTask :

HTASK WINAPI GetWindowTask(HWND hwnd);

Эта функция возвращает идентификатор задачи, создавшей окно с идентификатором hwnd.

Функция SetWindowsHookEx возвращает 32-разрядный идентификатор функции фильтра, который следует сохранить для дальнейшего использования, или NULL при ошибке.

В приведенном ниже фрагменте кода, взятом из приложения WINHOOK, устанавливается фильтр для сообщений, поступающих во все приложения от клавиатуры:

hhook = SetWindowsHookEx(WH_KEYBOARD,
  (HOOKPROC)KbHookProc,
  hInst, NULL); 

Исходный текст функции фильтра приведен (с сильными сокращениями) ниже:

extern "C"
LRESULT CALLBACK KbHookProc(int code,
  WPARAM wParam, LPARAM lParam)
{
  ...
  ...
  ...
  // Вызываем следующий в цепочке перехватчик
  return CallNextHookEx(hhook, code, wParam, lParam);
}

После выполнения всех необходимых действий функция фильтра передает управление по цепочке другим фильтрам (что необязательно). Для этого вызывается функция CallNextHookEx :

LRESULT WINAPI CallNextHookEx(
  HHOOK hHook,
  int code,
  WPARAM wParam,
  LPARAM lParam);

Параметр hHook содержит идентификатор текущей функции фильтра.

Параметр code содержит код фильтра, который должен передаваться следующему фильтру в цепочке.

Параметры wParam и lParam содержат, соответственно, 16- и 32-битовый дополнительные параметры.

Параметры code, wParam и lParam функции CallNextHookEx полностью соответствуют параметрам функции фильтра, которая будет рассмотрена нами позже.

Отмена фильтра

Фильтр, установленный функцией SetWindowsHookEx, можно отменить или удалить при помощи функции UnhookWindowsHookEx :

BOOL WINAPI UnhookWindowsHookEx(HHOOK hHook);

В качестве единственного параметра этой функции следует передать идентификатор функции фильтра, полученный от функции SetWindowsHookEx.

Если отмена фильтра выполнена успешно, функция UnhookWindowsHookEx возвращает значение TRUE. В случае возникновения ошибки возвращается FALSE.

Функции фильтра

Функция фильтра должна иметь следующий прототип:

LRESULT CALLBACK HookProc(
  int code,
  WPARAM wParam,
  LPARAM lParam)

Имя функции фильтра может быть любым, так как при установке фильтра вы должны указать функции SetWindowsHookEx указатель на функцию фильтра.

Параметр code может определять действия, выполняемые функцией фильтра. В операционной системе Windows версии 3.0 этот параметр мог принимать отрицательные значения. В этом случае функция фильтра должна была передавать управление следующему в цепочке фильтру при помощи функции DefHookProc. Операционная система Windows версии 3.1 никогда не вызывает функцию фильтра с отрицательным значением параметра code.

Назначение параметров wParam и lParam зависит от типа фильтра, задаваемого при помощи параметра idHook функции SetWindowsHookEx. Мы не будем подробно описывать все возможные типы фильтров, так как это займет очень много времени. При необходимости вы сможете найти полное описание в документации, поставляющейся вместе с SDK. Рассмотрим в деталях только самые интересные, на наш взгляд, типы фильтров.

Фильтр WH_CALLWNDPROC

Приведем прототип функции фильтра типа WH_CALLWNDPROC (для функции можно использовать любое имя):

LRESULT CALLBACK CallWndProc(
  int code,       // код действия
  WPARAM wParam,  // флаг текущей задачи
  LPARAM lParam)  // адрес структуры с сообщением

Функция CallWndProc обязательно должна находиться DLL-библиотеке. Она вызывается операционной системой Windows после вызова функции SendMessage, но перед тем, как сообщение попадет в функцию окна, для которой оно предназначено. Фильтр может изменить любые параметры сообщения или его код.

Если код действия (параметр code) меньше нуля, функция фильтра должна вызвать функцию CallNextHookEx, не изменяя перехваченное сообщение.

Если сообщение послано текущей задачей, значение параметра wParam отлично от нуля, в противном случае оно равно NULL.

Параметр lParam содержит указатель на структуру, которая описывает перехваченное сообщение (эта структура на описана в файле windows.h):

struct _Msg
{
  LPARAM lParam;  // параметр lParam сообщения
  WPARAM wParam;  // параметр wParam сообщения
  UINT   uMsg;    // код сообщения
  HWND   hWnd;    // идентификатор окна, для которого
};                // предназначено сообщение

Функция фильтра должна всегда возвращать нулевое значение.

Заметим, что после установки фильтра WH_CALLWNDPROC производительность операционной системы Windows заметно уменьшится, поэтому использование такого фильтра оправдано только при отладке приложения или для создания приложений, специально предназначенных для отладки других приложений Windows.

Фильтр WH_CBT

Большинство приложений, созданных фирмой Microsoft для своей операционной системы Windows, имеют встроенные обучающие системы, предназначенные для того, чтобы пользователь мог быстрее освоить работу с приложением. Например, текстовый процессор Microsoft Word for Windows версий 2.0 и 6.0 имеет очень удобную и легкую в использовании обучающую систему. Эта обучающая система не только рассказывает пользователю о том, как надо работать с текстовым процессором, но и, что очень важно, дает ему возможность попробовать выполнить те или иные действия самостоятельно. Когда пользователь пытается работать самостоятельно, все выглядит так, как будто он имеет дело с настоящим текстовым процессором, но при этом его действия ограничиваются обучающей системой.

Для облегчения создания подобных обучающих программ приложения могут установить фильтр WH_CBT, специально предназначенный для организации контроля за действиями пользователя со стороны обучающих программ. Мы не беремся утверждать, что обучающая программа для текстового процессора Microsoft Word for Windows построена с использованием этого фильтра, однако, вполне вероятно, что это так и есть.

Приведем прототип функции фильтра WH_CBT:

LRESULT CALLBACK CBTProc(               
  int code,       // код действия      
  WPARAM wParam,  // назначение зависит от кода действия
  LPARAM lParam); // назначение зависит от кода действия

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

Фильтр может разрешить или запретить выполнение перечисленных выше операций, возвращая соответствующее значение.

В зависимости от параметра code меняется назначение параметров wParam и lParam. Перечислим возможные значения для параметра code и кратко опишем назначение остальных параметров функции фильтра WH_CBT.

Значение параметра code Описание
HCBT_ACTIVATE Фильтр вызывается перед активизацией любого окна. Если функция возвращает FALSE, окно активизируется, если TRUE - нет. Параметр wParam содержит идентификатор активизирующегося окна. Параметр lParam содержит указатель на структуру CBTACTIVATESTRUCT :
typedef struct tagCBTACTIVATESTRUCT { 
  BOOL fMouse;
  HWND hWndActive;
} CBTACTIVATESTRUCT;

Флаг fMouse содержит TRUE, если окно активизируется в результате щелчка мыши, поле hWndActive содержит идентификатор активного окна

HCBT_CREATEWND Фильтр вызывается перед созданием окна. Если функция фильтра возвращает FALSE, создание окна разрешается, если TRUE - нет. Параметр wParam содержит идентификатор создаваемого окна. Параметр lParam содержит дальний указатель LPCREATESTRUCT на структуру CREATESTRUCT :
typedef struct tagCREATESTRUCT
{
    void FAR* lpCreateParams;
    HINSTANCE hInstance;
    HMENU     hMenu;
    HWND      hwndParent;
    int       cy;
    int       cx;
    int       y;
    int       x;
    LONG      style;
    LPCSTR    lpszName;
    LPCSTR    lpszClass;
    DWORD     dwExStyle;
} CREATESTRUCT;




HCBT_DESTROYWND Фильтр вызывается перед уничтожением окна. Если функция возвращает TRUE, уничтожение окна отменяется. Параметр wParam содержит идентификатор уничтожаемого окна. Параметр lParam содержит 0
HCBT_MINMAX Фильтр вызывается перед выполнением минимизации или максимизации окна. Если функция фильтра возвращает TRUE, перечисленные операции не выполняются. Параметр wParam содержит идентификатор окна, для которого выполняется минимизация или максимизация. Старшее слово параметра lParam равно нулю, младшее содержит одну из констант, описанных в файле windows.h с префиксом SW_, такие как SW_HIDE, SW_SHOWNORMAL, SW_SHOWMINIMIZED, SW_SHOWNOACTIVATE, SW_SHOW, SW_MINIMIZE, SW_SHOWMINNOACTIVE, SW_SHOWNA, SW_RESTORE
HCBT_MOVESIZE Фильтр вызывается перед перемещением или изменением размера окна. Если функция фильтра возвращает TRUE, выполнение операции отменяется. Параметр wParam содержит идентификатор окна, для которого выполняется перемещение или изменение размера. Параметр lParam содержит дальний указатель на структуру RECT, описывающую прямоугольную область
HCBT_SYSCOMMAND Фильтр вызывается при обработке системной команды. Вызов функции фильтра выполняется из функции DefWindowProc. Если функция фильтра возвращает TRUE, выполнение системной команды отменяется. Параметр wParam содержит код системной команды, такой, как SC_CLOSE, SC_HSCROLL, SC_MINIMIZE и т. д.Если параметр wParam содержит код команды SC_HOTKEY (активизация окна, связанного с клавишей ускоренного выбора, назначенной приложением), младшее слово параметра lParam содержит идентификатор окна, для которого назначена клавиша ускоренного выбора. Для остальных команд значение этого параметра не определено
HCBT_CLICKSKIPPED Фильтр вызывается при удалении сообщения мыши из системной очереди сообщений, при условии, что дополнительно определен фильтр WH_MOUSE. Параметр wParam содержит код сообщения мыши. Параметр lParam содержит дальний указатель на структуру MOUSEHOOKSTRUCT :
typedef struct tagMOUSEHOOKSTRUCT
{
  POINT pt;
  HWND  hwnd;
  UINT  wHitTestCode;
  DWORD dwExtraInfo;
} MOUSEHOOKSTRUCT;


HCBT_KEYSKIPPED Фильтр вызывается при удалении клавиатурного сообщения из системной очереди сообщений, при условии, что дополнительно определен фильтр WH_KEYBOARD. Параметр wParam содержит виртуальный код клавиши.содержимое параметра lParam аналогично содержимому соответствующего параметра клавиатурных сообщений WM_KEYDOWN и WM_KEYUP
HCBT_SETFOCUS Фильтр вызывается при установке фокуса ввода. Если функция фильтра возвращает значение TRUE, фокус не устанавливается. Параметр wParam содержит идентификатор окна, получающего фокус ввода. Младшее слово парамера lParam содержит идентификатор окна, теряющего фокус ввода. Старшее слово парамера lParam всегда содержит NULL
HCBT_QS Фильтр вызывается при удалении из системной очереди сообщения WM_QUEUESYNC, предназначенного для использования обучающим приложением. Это сообщение позволяет ему определить момент завершения того или иного события в главном приложении. Тех, кого интересуют подробности, мы отсылаем к документации, поставляющейся вместе с SDK

Фильтр WH_DEBUG

Приведем прототип функции фильтра типа WH_DEBUG :

LRESULT CALLBACK DebugProc(
  int code,       // код действия
  WPARAM wParam,  // идентификатор задачи
  LPARAM lParam); // адрес структуры DEBUGHOOKINFO

Фильтр WH_DEBUG предназначен для отладчиков и должен находиться в DLL-библиотеке. Он вызывается перед вызовом других фильтров, установленных функцией SetWindowsHookEx.

Параметр wParam содержит идентификатор задачи, которая установила фильтр.

Параметр lParam содержит дальний указатель на структуру DEBUGHOOKINFO :

typedef struct tagDEBUGHOOKINFO
{
  HMODULE  hModuleHook;
  LPARAM   reserved;
  LPARAM   lParam;
  WPARAM   wParam;
  int      code;
} DEBUGHOOKINFO;

В этой структуре в поле hModuleHook находится идентификатор модуля, содержащего функцию фильтра, поля lParam, wParam, code содержат параметры, передаваемые функции фильтра. Поле reserved не используется.

Функция фильтра типа WH_DEBUG может предотвратить вызов другого фильтра, для чего она должна возвратить значение TRUE. Если она вернет FALSE, управление будет передано соответствующему фильтру.

Фильтр WH_GETMESSAGE

Фильтр WH_GETMESSAGE получает управление, когда функция GetMessage или PeekMessage возвращают выбранное из очереди сообщение. Функция фильтра должна находиться в DLL-библиотеке.

Приведем прототип функции фильтра типа WH_GETMESSAGE:

LRESULT CALLBACK GetMsgProc(
  int code,       // код действия
  WPARAM wParam,  // не определено
  LPARAM lParam); // адрес структуры MSG

Параметр lParam содержит указатель на структуру MSG , содержащую перехваченное сообщение:

typedef struct tagMSG
{
  HWND   hwnd;
  UINT   message;
  WPARAM wParam;
  LPARAM lParam;
  DWORD  time;
  POINT  pt;
} MSG;

Функция фильтра может изменить любой параметр сообщения и даже его код. В последнем случае произойдет замена одного сообщения на другое.

Возвращаемое функцией фильтра значение должно всегда равняться нулю.

Фильтр WH_HARDWARE

Фильтр WH_HARDWARE предназначен для перехвата сообщений, поступающих от нестандартных устройств ввода, таких, как устройства перьевого ввода (клавиатура и мышь - это стандартные устройства ввода). Функция фильтра должна находиться в DLL-библиотеке.

Приведем прототип функции фильтра типа WH_HARDWARE:

LRESULT CALLBACK HardwareProc(
  int code,       // код действия
  WPARAM wParam,  // не определено
  LPARAM lParam); // адрес структуры HARDWAREHOOKSTRUCT

Структура HARDWAREHOOKSTRUCT описана в файле windows.h:

typedef struct tagHARDWAREHOOKSTRUCT
{
   HWND    hWnd;
   UINT    wMessage;
   WPARAM  wParam;
   LPARAM  lParam;
} HARDWAREHOOKSTRUCT;

В этой структуре поле hWnd содержит идентификатор окна, которому предназначено сообщение, поле wMessage содержит код сообщения, поля wParam и lParam содержат дополнительную информацию, зависящую от кода сообщения.

Фильтр WH_JOURNALRECORD

Фильтр WH_JOURNALRECORD вызывается, когда Windows удаляет сообщения из системной очереди. Функция фильтра должна находиться в DLL-библиотеке.

Приведем прототип функции фильтра типа WH_JOURNALRECORD:

LRESULT CALLBACK JournalRecordProc(
  int code,       // код действия
  WPARAM wParam,  // содержит NULL
  LPARAM lParam); // адрес структуры EVENTMSG

Данный фильтр предназначен для записи перехваченных сообщений в память или файл. Он не может изменять или удалять сообщения из системной очереди.

Параметр code может принимать одно из трех значений:

Значение параметра code Описание
HC_ACTION Windows извлекает сообщение из системной очереди
HC_SYSMODALON Windows выводит на экран системную модальную диалоговую панель. Начиная с этого момента приложение должно остановить запись сообщений
HC_SYSMODALOFF Windows удаляет системную модальную диалоговую панель, так что теперь можно продолжить запись сообщений

Структура EVENTMSG описана в файле windows.h:

typedef struct tagEVENTMSG
{
  UINT   message;
  UINT   paramL;
  UINT   paramH;
  DWORD  time;
} EVENTMSG;

Фильтр WH_JOURNALPLAYBACK

Фильтр WH_JOURNALPLAYBACK используется для "проигрывания" сообщений, записанных фильтром WH_JOURNALRECORD. Если установлен этот фильтр, обычный ввод при помощи мыши или клавиатуры отключается. Функция фильтра должна находиться в DLL-библиотеке.

Приведем прототип функции фильтра типа WH_JOURNALPLAYBACK:

LRESULT CALLBACK JournalPlaybackProc(
  int code,       // код действия
  WPARAM wParam,  // содержит NULL
  LPARAM lParam); // адрес структуры EVENTMSG

Перед возвратом управления функция фильтра WH_JOURNALPLAYBACK должна записать по адресу, переданному ей через параметр lParam, структуру данных, записанную ранее функцией фильтра WH_JOURNALRECORD.

Функция фильтра должна вернуть интервал времени ожидания (в машинных тиках) перед тем как Windows начнет обработку сообщения. Если вернуть нулевое значение, ожидание выполняться не будет.

Фильтр WH_KEYBOARD

Фильтр WH_KEYBOARD получает управление, когда функции GetMessage или PeekMessage возвращают сообщения WM_KEYDOWN, WM_KEYUP, WM_SYSKEYDOWN, WM_SYSKEYUP или WM_CHAR. Функция фильтра должна находиться в DLL-библиотеке.

Приведем прототип функции фильтра типа WH_KEYBOARD:

LRESULT CALLBACK KeyboardProc(
  int code,       // код действия
  WPARAM wParam,  // код виртуальной клавиши
  LPARAM lParam); // дополнительная информация

Параметр code может принимать значения HC_ACTION и HC_NOREMOVE. В первом случае перехваченное сообщение после обработки будет удалено из системной очереди сообщений, во втором - останется в этой очереди (т. к. оно было выбрано при помощи функции PeekMessage с параметром PM_NOREMOVE). Если сообщение останется в очереди, таблица состояния клавиатуры, которую можно получить при помощи функции GetKeyboardState, может не отражать состояние клавиатуры на момент выборки сообщения.

Параметры wParam и lParam содержат ту же самую информацию, что и соответствующие параметры клавиатурных сообщений WM_KEYDOWN, WM_KEYUP, WM_SYSKEYDOWN, WM_SYSKEYUP, WM_CHAR.

Параметр wParam содержит код виртуальной клавиши, соответствующей нажатой физической клавише. Именно этот параметр используется приложениями для идентификации нажатой клавиши.

Приведем описание отдельных бит парамера lParam, через который передается дополнительная информация о клавиатурном сообщении .

Бит Описание
0-15 Счетчик повторов. Если нажать клавишу и держать ее в нажатом состоянии, несколько сообщений WM_KEYDOWN и WM_SYSKEYDOWN будут слиты в одно. Количество объединенных таким образом сообщений
16-23 OEM скан-код клавиши. Изготовители аппаратуры (OEM - Original Equipment Manufacturer) могут заложить в своей клавиатуре различное соответствие скан-кодов и обозначений клавиш. Скан-код генерируется клавиатурным контроллером. Это тот самый код, который получают в регистре AH программы MS-DOS, вызывая прерывание INT16h
24 Флаг расширенной клавиатуры. Этот бит установлен в 1, если сообщение соответствует клавише, имеющейся только на расширенной 101- или 102-клавишной клавиатуре. Это может быть одна из следующих клавиш: <Home>, <End>, <PgUp>, <PgDn>, <Insert>, <Delete>, клавиши дополнительной клавиатуры.
25-26 Не используются
27-28 Зарезервированы для использования Windows
29 Код контекста. Этот бит равен 1, если сообщение соответствует комбинации клавиши <Alt> с любой другой, и 0 в противном случае
30 Предыдущее состояние клавиши. Если перед приходом сообщения клавиша, соответствующая сообщению, была в нажатом состоянии, этот бит равен 1. В противном случае бит равен 0
31 Флаг изменения состояния клавиши (transition state). Если клавиша была нажата, бит равен 0, если отпущена - 1

При помощи этого фильтра приложение может удалить клавиатурное сообщение. Для удаления сообщения функция фильтра должна вернуть значение 1. Если же возвращенное значение будет равно 0, сообщение будет обработано системой.

Фильтр WH_MOUSE

Фильтр WH_MOUSE получает управление, когда функции GetMessage или PeekMessage возвращают сообщения мыши. Функция фильтра должна находиться в DLL-библиотеке.

Приведем прототип функции фильтра типа WH_MOUSE:

LRESULT CALLBACK MouseProc(
  int code,       // код действия
  WPARAM wParam,  // код сообщения
  LPARAM lParam); // указатель на структуру MOUSEHOOKSTRUCT

Так же, как и для предыдущего фильтра, параметр code может принимать значения HC_ACTION и HC_NOREMOVE.

Параметр wParam содержит код сообщения, поступившего от мыши.

Через параметр lParam передается указатель на структуру MOUSEHOOKSTRUCT :

typedef struct tagMOUSEHOOKSTRUCT
{
   POINT  pt;
   HWND   hwnd;
   UINT   wHitTestCode;
   DWORD  dwExtraInfo;
} MOUSEHOOKSTRUCT;

Эта структура содержит дополнительную информацию, имеющую отношение к сообщению.

Поле pt является структурой типа POINT, в которой находятся экранные x- и y-координаты курсора мыши. Поле hwnd содержит идентификатор окна, в функцию которого будет направлено сообщение. В поле wHitTestCode находится код тестирования, определяющий область окна, соответствующую расположению курсора мыши на момент генерации сообщения. Поле dwExtraInfo содержит дополнительную информацию, которую можно получить с помощью функции GetMessageExtraInfo :

LPARAM WINAPI GetMessageExtraInfo(void);

Назначение отдельных бит возвращаемого этой функцией значения зависит от аппаратного обеспечения.

Фильтр WH_MSGFILTER

Фильтр WH_MSGFILTER получает управление, когда диалоговая панель или меню выбирает сообщение. Функции фильтра разрешается изменить или обработать перехваченное сообщение. Фильтр WH_MSGFILTER может находиться в приложении или в DLL-библиотеке, его можно определить как для отдельной задачи, так и для всей системы в целом.

Приведем прототип функции фильтра типа WH_MSGFILTER:

LRESULT CALLBACK MessageProc(
  int code,       // код действия
  WPARAM wParam,  // не определено
  LPARAM lParam); // указатель на структуру MSG

Параметр code может принимать значения MSGF_DIALOGBOX (ввод в диалоговой панели), MSGF_SCROLLBAR (ввод в области полосы просмотра), MSGF_MENU (ввод в меню) или MSGF_NEXTWINDOW (пользователь активизирует следующее окно, нажимая комбинацию клавиш <Alt + Tab> или <Alt + Esc>).

Если фильтр обрабатывает сообщение, функция фильтра должна вернуть ненулевое значение, если нет - нулевое.

Фильтр WH_SYSMSGFILTER

Фильтр WH_SYSMSGFILTER получает управление, когда диалоговая панель или меню выбирает сообщение. Функции фильтра разрешается изменить или обработать перехваченное сообщение. Фильтр WH_SYSMSGFILTER может находиться только DLL-библиотеке. Назначение этого фильтра аналогично назначению фильтра WH_MSGFILTER, но он может быть установлен только для всей системы в целом.

Приведем прототип функции фильтра типа WH_SYSMSGFILTER:

LRESULT CALLBACK SysMsgProc(
  int code,       // код действия
  WPARAM wParam,  // не определено
  LPARAM lParam); // указатель на структуру MSG

Если фильтр обрабатывает сообщение, функция фильтра должна вернуть ненулевое значение, если нет - нулевое.

Приложение может установить одновременно фильтры WH_SYSMSGFILTER и WH_MSGFILTER, в этом случае вначале вызывается фильтр WH_SYSMSGFILTER, а затем - фильтр WH_MSGFILTER. Если же функция фильтра WH_SYSMSGFILTER возвращает ненулевое значение, фильтр WH_MSGFILTER не вызывается.

Фильтр WH_SHELL

Фильтр WH_SHELL предназначен для приложений-оболочек (shell application) и позволяет получать необходимые извещения от операционной системы Windows.

Приведем прототип функции фильтра типа WH_SHELL:

LRESULT CALLBACK ShellProc(
  int code,       // код действия
  WPARAM wParam,  // флаг текущей задачи
  LPARAM lParam); // не определено

Параметр code может принимать одно из следующих значений:

Значение параметра code Описание
HSHELL_ACTIVATESHELLWINDOW Оболочка должна активизировать свое главное окно
HSHELL_WINDOWCREATED Создано окно верхнего уровня, которое не принадлежит ни одному приложению. Это окно будет существовать во время работы функции фильтра. Идентификатор созданного окна передается через параметр wParam
HSHELL_WINDOWDESTROYED Описанное выше окно верхнего уровня будет уничтожено после завершения работы функции фильтра. Идентификатор уничтожаемого окна передается через параметр wParam

Функция фильтра должна вернуть нулевое значение.

[Назад] [Содеожание] [Дальше]