Почему WM_CLIPBOARDUPDATE не обрабатывается TApplicationEvents.OnMessage в крупных проектах Delphi на Windows 10
При работе с компонентом TApplicationEvents в среде разработки Delphi для отслеживания изменений в буфере обмена операционной системы Windows 10 используется следующий подход:
procedure TFormMain.AppEventsMainMessage(var Msg: tagMSG; var Handled: Boolean);
begin
case Msg.message of
Winapi.Messages.WM_CLIPBOARDUPDATE:
begin
// Обработка сообщения о изменении содержимого буфера обмена
CodeSite.Send('TFormMain.AppEventsMainMessage: WM_CLIPBOARDUPDATE');
end;
end;
end;
Этот метод обычно работает корректно, однако в крупных проектах сообщение WM_CLIPBOARDUPDATE может не обрабатываться в обработчике событий TApplicationEvents.OnMessage. В чем причина?
Оказывается, операционная система Windows не рассылает сообщение WM_CLIPBOARDUPDATE всем окнам при изменении содержимого буфера обмена. Для получения уведомлений о таких изменениях необходимо зарегистрировать окно, используя функцию AddClipboardFormatListener. Согласно документации этой функции:
Помещает указанное окно в список слушателей форматов clipboard, поддерживаемых системой.
Когда окно добавлено в список слушателей форматов clipboard, ему будет отправлено сообщение WM_CLIPBOARDUPDATE каждый раз, когда содержимое clipboard изменяется.
После вызова функции AddClipboardFormatListener(Handle) окно с идентификатором Handle будет получать сообщения WM_CLIPBOARDUPDATE при изменении clipboard. Если в методе FormCreate формы TFormMain вызвать AddClipboardFormatListener(Handle), где Handle означает Self.Handle, то окно, ассоциированное с TFormMain, начнет получать эти сообщения, которые могут быть обработаны методом TFormMain.WMClipboardUpdate.
Однако, если есть вторая форма TFormSecond, она не будет получать такие сообщения, так как регистрация была произведена только для TFormMain.
Также стоит отметить, что любое сообщение, отправленное в окно вашего приложения, пройдет через TApplicationEvents. Это означает, что если вы зарегистрировали любое окно в вашем приложении с помощью AddClipboardFormatListener, то TApplicationEvents в вашем приложении будут видеть это сообщение.
Важно: вызов AddClipboardFormatListener() следует выполнять не в событии OnCreate формы, а в переопределенном методе CreateWnd или CreateWindowHandle(), чтобы обеспечить корректную работу в случае, если HWND формы создается повторно во время выполнения программы.
В контексте обсуждения было предложено добавить событие OnClipboardChanged в класс TApplicationEvents, что позволило бы избежать необходимости вручную добавлять и удалять ClipboardFormatListener. Это предложение было направлено в Embarcadero, и оно получило идентификатор в системе отслеживания ошибок: RSP-38670.
В заключение, для корректной обработки сообщения WM_CLIPBOARDUPDATE в Delphi-проектах на Windows 10 необходимо зарегистрировать окно с помощью функции AddClipboardFormatListener, после чего сообщение будет доставляться в обработчик, определенный для этого окна.
В крупных проектах Delphi на Windows 10 сообщение `WM_CLIPBOARDUPDATE` не обрабатывается в `TApplicationEvents.OnMessage` из-за необходимости явной регистрации окон для получения уведомлений об изменениях буфера обмена, что не выполняется автоматически.
Комментарии и вопросы
Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS
Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.