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_CLIPBOARDUPDATE
message 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.