Сообщения Windows - введение
Кто-нибудь может со мной поделиться информацией о работе в 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 позволяют тонко управлять вашими приложениями, выполняя именно те задачи, которые вам необходимо решить (метод "точечной наводки"). Вам необходимо лишь выбрать цель и передать свою просьбу понравившемуся элементу управления (или самому ловить такие сообщения). [000288]