To be notified when the clipboard content changes in Windows 10, I usually use a TApplicationEvents component with this code:
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;
And usually, it works. So I used this code also in an existing large project. But there, the WM_CLIPBOARDUPDATE message is not fired in the TApplicationEvents.OnMessage event handler!
What could prevent this message from being captured in the TApplicationEvents.OnMessage event handler?
EDIT: ONLY when using the AddClipboardFormatListener function, that DOES work in my project:
procedure TformMain.FormCreate(Sender: TObject);
begin
Winapi.Windows.AddClipboardFormatListener(Handle);
procedure TformMain.FormDestroy(Sender: TObject);
begin
Winapi.Windows.RemoveClipboardFormatListener(Handle);
Private
procedure WMClipboardUpdate(var Msg: TMessage); message WM_CLIPBOARDUPDATE;
implementation
procedure TformMain.WMClipboardUpdate(var Msg: TMessage);
begin
CodeSite.Send('TformMain.WMClipboardUpdate: WM_CLIPBOARDUPDATE');
end;
But this does not answer the question "What could prevent this message from being captured in the TApplicationEvents.OnMessage event handler?"
CodePudding user response:
Windows doesn't broadcast WM_CLIPBOARDUPDATE to all windows when the clipboard is updated. Instead, you have to register your window if you want to be notified. From the documentation of AddClipboardFormatListener:
Places the given window in the system-maintained clipboard format listener list.
When a window has been added to the clipboard format listener list, it is posted a
WM_CLIPBOARDUPDATEmessage whenever the contents of the clipboard have changed.
So after you have called
AddClipboardFormatListener(Handle)
the window with HWND Handle will be posted WM_CLIPBOARDUPDATE messages when the clipboard is changed. If you write
AddClipboardFormatListener(Handle)
in your TformMain.FormCreate, then Handle means Self.Handle, that is, the window associated with TformMain will be posted the messages. So they can be detected by your TformMain's
procedure WMClipboardUpdate(var Msg: TMessage); message WM_CLIPBOARDUPDATE;
But if you have a second form, TformSecond, it will not receive any such messages, because you did only register your TformMain.
Also, any message posted to a window in your application will pass through your TApplicationEvents. This means that if you have registered any window in your app using AddClipboardFormatListener, then any TApplicationEvents in your app will see this message.
