Решил разобраться с устройством Windows, в частности с сообщениями. Народ в сети массово отправляет к Рихтеру и Русиновичу. Книги приобрел – начал читать. Что хочу сказать – первое впечатление – информация ценнейшая для разработки под Windows. Ещё и на русском языке. Но поскольку практика это лучший инструмент познания, решил сделать несколько простых примеров до основательного чтения этих книг. После чтения сделаю ещё несколько примеров, чтобы сравнить насколько лучше понимаю предмет.
Как отправить сообщение из приложения?
Рассмотрим на примере закрытия окна. Сообщение будет WM_CLOSE. Список всех сообщений для Windows можно посмотреть здесь.
Итак, из того, что я понял на данный момент, чтобы отправить сообщения определенному окну, часто используются функции
1 2 3 |
SendMessage(Form2.Handle,WM_CLOSE,0,0); //а также функция PostMessage(Form2.Handle,WM_CLOSE,0,0); |
Оба сообщения закроют окно c Handle равным Form2.Handle Первый параметр – Handle окна, второй параметр – собственно сообщения, а третий и четвертый – дополнительные параметры, которые задействуются или нет от случая к случаю, например координаты курсора. В приведенном примере оба параметра занулены. Если поместить эти инструкции, скажем в обработчик кнопки окна, то после нажатия в ядро Windows будет направлено сообщение о закрытии окна, а Windows, соответственно просто закроет окно.
Где найти полный список сообщений?
В принципе таких ресурсов много. Вот один из них.
Слушает ли Delphi программа сообщения?
Определенно да. Вот простой пример. Поймаем сообщение нажатия правой кнопкой мыши на любом из компонентов приложения.
1 2 3 4 |
procedure TForm2.FormCreate(Sender: TObject); begin Application.OnMessage:=AppMessage; end; |
1 2 3 4 |
procedure TForm2.AppMessage(var Msg: TMsg; var Handled: Boolean); begin if Msg.message=WM_RBUTTONDOWN then showmessage('Сообщение поймано'); end; |
Если нажмем правой клавишей мыши на любом компоненте приложения, то увидим
Здесь мы отлавливали сообщение о нажатии правой кнопки мыши. Таким же образом можно отлавливать любые другие сообщения из списка.
Как отправить “кастомное” сообщение?
Под кастомным сообщением я подразумеваю сообщение не из списка, а какое-то свое сообщение, например WM_USER+2001. Вот как можно отправить такое кастомное сообщение. Пример основан на официальной документации
Объявляем глобальную константу
1 2 |
const WM_CUSTOM = WM_USER + 2001; |
Далее создаем и присваиваем обработчик
1 2 3 4 5 6 7 8 9 10 11 12 13 |
procedure TForm.FormCreate(Sender: TObject); begin Application.OnMessage:=AppMessage; // Присваиваем обработчик end; //Создаем обработчик procedure TForm.AppMessage(var Msg: TMsg; var Handled: Boolean); begin if (Msg.hwnd = Form.Handle) and (Msg.message=WM_CUSTOM) then Showmessage('Кастомное сообщение поймано'); end; |
И последний штрих – отправляем сообщения
1 2 3 4 |
procedure TForm2.bSendMessageClick(Sender: TObject); begin PostMessage(Form2.Handle,WM_CUSTOM,0,0); end; |
Ещё вариант отправки кастомного сообщения
Определяем свою константу (она должна быть прописана выше, чем метод, который её использует, то есть, например, до описания типов)
1 2 |
const WM_CUSTOM = WM_USER + 2001; |
Далее определяем обработчик сообщения в методах класса формы, например, таким образом
1 |
procedure MyMessageHandler(var Msg:TMessage); message WM_CUSTOM; |
Далее прописываем его
1 2 3 4 |
procedure TForm2.MyMessageHandler(var Msg: TMessage); begin showmessage('Кастомное сообщение поймано'); end; |
Далее отправляем PostMessage, скажем, по нажатию кнопки
1 2 3 4 |
procedure TForm2.bSendMessageClick(Sender: TObject); begin PostMessage(Form2.Handle,WM_CUSTOM,0,0); end; |
Результат
Аpplication.ProcessMessages
Наконец, чтобы окончательно налепить всего в кучу про сообщения рассмотрим пример с сайта delphi-manual.ru, который очень хорошо демонстрирует работу Application.ProcessMessages.
Насколько я понял, сообщения в Windows выстраиваются в очередь. Отправка через PostMessage это постановка сообщения в конец очереди, отправка через SendMessage это отправка сообщения мимо очереди – оно будет выполнено одним из первых, не смотря на других ожидающих. Аналогичное действие у Application.ProcessMessages
Этот код с сайта delphi-manual.ru очень хорошо демонстрирует действие Application.ProcessMessages
В данном случае мы пытаемся добиться моргания текста в Edit1.Text, если не пользоваться Application.ProcessMessages, то этого моргания не будет, потому что сообщения в конце очереди, а если раскомментировать Application.ProcessMessages, то сообщения будут в начале очереди
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
procedure TForm.ButtonClick(Sender: TObject); var i: Integer; begin if Edit.Text='' then begin for i:=1 to 10 do begin Edit.Text:='Введите данные'; // Application.ProcessMessages; // Раскомментируйте и будет моргать sleep(300); Edit.Text:=''; // Application.ProcessMessages; // Раскомментируйте и будет моргать sleep(300); end; Edit.SetFocus; end; end; |
Результат