|
Вирус детям не игрушка, не товарищ и не друг!
|
Кто-нибудь может со мной поделиться информацией о работе в
Delphi с Windows Messages (системные сообщения)? Все эти сообщения типа WM_***
вызывают у меня нервный тик, поскольку это я не могу понять как это
работает.
Список всех системных сообщений Windows доступен в файлах электронной справки
Delphi. (Я использую D5, но думаю в будущих версиях все останется на своих
местах).
Сообщения WM_ (и другие) играют существенную роль в работе Windows. Все вы
хорошо знаете, что Delphi первоначально строится на принципе *управления
событиями*; наверняка не один раз вы создавали обработчики событий OnKeyPress,
OnThis, OnThat и других. Если у вас есть исходный код VCL, вы легко обнаружите,
что механизм работы событий в Delphi основан на обработке конкретных системных
соощенияй, посылаемых вашему элементу управления (как раз здесь и заложено
главное достоинство объектно-ориентированного программирования, когда вы можете
создать новый компонент на основе существующего и "научить" его обрабатывать
другие необходимые вам системные сообщения). Windows постоянно посылает
сообщения в ответ на действия пользователя и ждет соответствующей реакции от
приложений Delphi (и всех остальных приложений Windows), заключающейся в их
"приеме" и соответствующей обработке. Delphi имеет оболочки для большинства
системных сообщений, создав "механизм оповещения элемента управления о приеме
сообщения на его адрес" - события для компонентов, как было описано выше.
Кроме приема сообщений, у вас также существует возможность их отправления.
Это возможно двумя способами: SendMessage и PostMessage (обе являются Win API
функциями), а также метод Delphi Perform. Первые два требуют в качестве
параметра Handle указывать дескриптор компонента, которому вы шлете сообщение,
тогда как Perform является методом, принадлежащим самому компоненту. Сообщения
передаются в стандартную очередь системных сообщений и обрабатываются подобно
другим сообщениям.
Вот тривиальный пример: я хочу (по некоторой причудливой причине) вставлять в
TMemo символ 'y' каждый раз после набора цифры '4'. (Обдумайте способ
автоматической вставки блока begin-end или заключительной скобки.) Я, конечно,
мог бы поработать с Memo-свойством Lines, но это было бы не так красиво и
достаточно громоздко. Вот как выглядит наш пример с использованием
сообщений:
procedure TForm1.Memo1KeyPress(Sender: TObject; var Key: Char);
begin
if Key = '4' then
SendMessage(Memo1.Handle, WM_CHAR, Word('y'), 0);
end;
|
Другой пример демонстрирует работу с компонентом ComboBox. Мы хотим, чтобы он
автоматически выпадал при нажатии пользователем какой-либо клавиши. Это
поведение, к сожалению, нестандартно. Вот что мы делаем:
procedure TFormEffortRates.ComboBoxMaterialKeyDown(Sender: TObject; var
Key: Word; Shift: TShiftState);
var
iShowing: integer;
{ какой-то код, затем... }
begin
{ С помощью сообщения узнаем состояние ("раскрытость") ComboBox'а }
iShowing := SendMessage((Sender as TComboBox).Handle, CB_GETDROPPEDSTATE, 0, 0);
if iShowing = 0 then
{ раскрываем ComboBox }
SendMessage((Sender as TComboBox).Handle, CB_SHOWDROPDOWN, 1,0);
end;
|
Другой хороший пример демонстрирует способ получения строки и колонки TMemo.
Для такого трюка мы воспользуемся API. Вот реализация этого метода (это может не
самый эффективный метод, но он приведен ради демонстрации работы сообщений):
function TMDIChild.GetMemoColumn(const TheMemo : TMemo) : integer;
begin
Result := TheMemo.SelStart -
(SendMessage(TheMemo.Handle, EM_LINEINDEX,
GetMemoLine(TheMemo), 0));
end;
function TMDIChild.GetMemoLine(const TheMemo : TMemo) : integer;
begin
Result := SendMessage(TheMemo.Handle, EM_LINEFROMCHAR,
TheMemo.SelStart, 0);
end;
|
Повторю снова: список и описание всех сообщений приведены в электронной
справке по API. Инструкция по их использованию получилась у меня несколько
скупой, но я надеюсь что хотя-бы несколько прояснил ситуацию и вы сможете
задавать более конкретные вопросы.
Короче говоря, сообщения API позволяют тонко управлять вашими приложениями,
выполняя именно те задачи, которые вам необходимо решить (метод "точечной
наводки"). Вам необходимо лишь выбрать цель и передать свою просьбу
понравившемуся элементу управления (или самому ловить такие сообщения).
|