Событие OnMessage, перехватчики сообщений, перехваты Windows


Использование события OnMessage
Для обработки сообщений в приложении можно использовать событие Application.OnMessage. Как уже говорилось ранее, цикл обработки сообщений периодически просматривает содержимое поля FOnMessage. Фактически проверяется наличие обработчика у события OnMessage. С помощью этого обработчика можно перехватить или изменить обработку любых сообщений, кроме сообщений оперативной подсказки и (напомним, что сообщения, посланные функцией SendMessage, не попадают в цикл сообщений и также не могут быть перехвачены этим обработчиком этого события).

Поле FOnMessage и событие OnMessage имеют тип указателя на метод TMessageEvent. Он объявлен следующим образом

Procedure(Var Msg: TMsg; Var Handled: Boolean) Of Object;

Таким образом, обработчик этого события должен возвращать True через параметр Handled, если сообщение обработано, иначе обработка сообщения будет продолжена.

Тогда: положить компонент Application и в OnMessage написать эту функцию:

procedure TForm1.ApplicationEvents1Message(var Msg: tagMSG;
var Handled: Boolean);
var ch:char;
begin
if CheckBox2.Checked then
if Msg.message= WM_CHAR then begin
ch:=char(msg.WParam);
case ch of
‘r’,’R’: Panel1.Color:=clred;
‘b’,’B’: Panel1.Color:=clblue;
‘g’,’G’: Panel1.Color:=clgreen;
end;
end
end;

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

Использование перехватчиков сообщений
а) Перехваты Delphi
Можно осуществить перехват сообщения, предназначенного для окна объекта Application, с помощью метода, имеющего следующий тип:

Туре TWindowHook=Function(Var Message: TMessage): Boolean Of Object;

Такой метод следует зарегистрировать в качестве перехватчика сообщений приложения с помощью следующего метода класса TApplication:
HookMainWindow(Hook: TWindowHook);

Этот метод — перехватчик сообщения добавляется перед методом WndProc. Подобных методов можно зарегистрировать несколько.

Если один из перехватчиков сообщения типа TWindowHook в цепочке методов обрабатывающих сообщение вернет True, то это будет означать, что это сообщение обработано. Когда надобность в перехвате сообщений отпадет, зарегистрированный перехватчик сообщения можно исключить из списка действующих с помощью метода класса TApplication:

UnhookMainWindow(Hook: TWindowHook);
Type TForm 1 =Class(TForm)
// Все иные необходимые объявления
Public
Function AppHook(Var Msg: TMessage): Boolean; // Объявление метода
End;
Function TForml.AppHookfVar Msg: TMessage): Boolean; Begin
Editl.Text:=’3ro Hook!’; // Вывод сообщения
Result:=True;
End;
Procedure TForml.ButtonlClick(Sender: TObject);
Begin
Application.HookMainWindow(AppHook); // Регистрация метода
End;
Procedure TForml.Button2Click(Sender: TObject);
Begin
Application.UnhookMainWindow(AppHook); // Отключение метода
End;
Procedure TForml.Button3Click(Sender: TObject);
Begin
SendMessage(Application.Handle,WM_NULL,0,0); // Посылка сообщения
End;

б) Перехваты Windows
В Windows предусмотрена функция SetWindowsHookEx, позволяющая установить функцию перехвата для доступа к сообщениям до того, как их получат другие приложения. Для этой функции определены перехваты Windows, приведенные ниже
WH_CALLWNDPROC — Позволяет контролировать сообщение до посылки сообщения конкретному окну функцией SendMessage

WH_CALLWNDPROCRET — Позволяет контролировать сообщение после того, как оно обработано процедурой окна.

WHGETMESSAGE — Позволяет контролировать сообщения, зарегистрированные в очереди сообщений

Перехватчики подобных системных сообщений должны располагаться в библиотеках Dll. Примеры подобных сообщений относительно большие и имеются в литературе.

Нестандартные сообщения

Помимо стандартных и системных сообщений Windows имеется еще три обширные категории сообщений.
а) Собственные сообщения компонентов
Целый ряд стандартных для Windows компонентов имеют набор собственных сообщений, идентификаторы которых начинаются на соответствующие буквы (ListBox — LB_**, Edit, Memo — MEM_**, ComboBox — CB_**, Button — BM_**, Scroll Bar — SBM_**).

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

SendMessage(Button1.Handle, BM_CLICK, 0,0); // Нажатие кнопки

б) Извещающие сообщения (notification message)
Представляют собой сообщения, посылаемые родительскому окну, когда в одном из его дочерних компонентов происходят действия, для которых предусмотрены эти сообщения. Эти сообщения генерируется только стандартными управляющими элементами Windows, такими как кнопки (BN_**), поля ввода (EN__**), списки (LBN_**) и т.п.

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

в) Сообщения устройств и компонентов Windows
В Windows предусмотрено еще около 40 групп сообщений, которые не поддерживаются Delphi. К ним можно сообщения от TrackBar (TBM_**), Tree View (TVM_**), UpDown (UDM_**), ряда других компонентов, различных элементов управления, устройств Windows, таких как видеодрайверов, панели управления и т.п. С подобными сообщениями можно познакомиться в справочной системе.

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

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

Выделяют два основных варианта организации фоновых работ.
а) Использование события Onldle
Когда приложение не занято обработкой сообщений, то оно находится в режиме ожидания. В этот момент приложение, как уже говорилось ранее, проверяет содержимое поля FOnldle. Фактически проверяется наличие обработчика у события Onldle. Если обработчик есть, то он выполняется. Как и положено, поле FOnldle и событие Onldle имеют тип указателя на метод TIdleEvent. Он объявлен следующим образом.

Procedure(Sender: TObject; Var Done: Boolean) Of Object;

Обработчик получает логический параметр Done, по умолчанию равный True. Если установить его равным False, то обработчик будет запускаться во время ожидания сообщений. Для запуска фонового режима с определенной задержкой можно использовать компонент Timer 1, установив его свойство Enabled в True.

Положить компонент ApplicationEvents1 и сделать обработчик события для OnIdle

procedure TForm1.ApplicationEvents1Idle(Sender: TObject;
var Done: Boolean);
begin
If edit3.Text<>edit2.Text then edit3.Text:=edit2.Text;
Done:=false;
end;

Поскольку во время работы обработчика приложение не обрабатывает поступающие сообщения, следует делать его коротким. В долго работающие обработчики необходимо включать метод ProcessMessages, который запускает механизм обработки поступающих сообщений. Например, так:
Application.ProcessMessages;

б) Использование функции PostMessage
Менее распространенный способ реализации фоновых вычислений заключается в том, что приложение посылает самому себе пользовательское сообщение по окончании каждого шага фонового процесса:

PostMessage(Handle, WM_USER, 0,0);

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


Комментарии запрещены.




Статистика