Mega Code Archive

 
Categories / Delphi / Examples
 

How to watch the clipboard

Title: How to watch the clipboard Question: Is there a way to react when something is pasted to the clipboard ? Answer: Your application needs to be registered as a "Clipboard Viewer". It will then receive a WM_DRAWCLIPBOARD message whenever the contents of the Clipboard have changed: var NextViewer: THandle; ... NextViewer := SetClipboardViewer(Handle); The following two message-handling methods need to be declared: procedure WMDrawClipboard(var Message : TMessage); message WM_DRAWCLIPBOARD ; procedure WMChangeCBChain(var Message : TWMChangeCBChain); message WM_CHANGECBCHAIN; As mentioned above, the WM_DRAWCLIPBOARD message will be received whenever the contents of the Clipboard changes. The WM_CHANGECBCHAIN message occurs whenever an application is registered or unregistered as a Clipboard viewer. This is because all Clipboard viewers are "chained" together, and if that chain is broken, one or more of the applications will not properly receive the WM_DRAWCLIPBOARD message. The logic in your WMDrawClipboard method can react to the Clipboard change however you deem necessary. For example, the following is taken from the accompanying demo: procedure TForm1.WMDrawClipboard(var Message : TMessage) ; begin if Clipboard.HasFormat(CF_TEXT) then Memo1.Text := Clipboard.AsText ; if NextViewer 0 then SendMessage(NextViewer,Message.Msg, Message.WParam,Message.LParam) ; end; First, we check to see whether there is text in the Clipboard. If so, we stuff it into a memo on our form. We then verify that there is another application in the Clipboard viewer chain (NextViewer), and shuttle the WM_DRAWCLIPBOARD message along to it. It is vital that you do this in your own WMDrawClipboard method! If your leanings run more toward the sadistic side, here is a piece of code that will strip out any vowels from the Clipboard. It's guaranteed to drive the user nuts! var s : string ; x : integer ; begin s := '' ; for x := 1 to Length(Clipboard.AsText) do if not (Clipboard.AsText[x] in ['a','A','e','E','i','I','o','O','u','U']) then s := s + Clipboard.AsText[x] ; Clipboard.AsText := s ; The logic in your WMChangeCBChain method should match the following: procedure TForm1.WMChangeCBChain(var Message : TWMChangeCBChain) ; begin if Message.Remove = NextViewer then NextViewer := Message.Next else if NextViewer 0 then SendMessage(NextViewer, Message.Msg, TMessage(Message).WParam, TMessage(Message).LParam) ; end ; The WM_CHANGECBCHAIN will include information as to whether the other application is being added to, or removed from, the Clipboard viewing chain. If the app is being removed, we need to see if it is the next application in the chain. Otherwise, we pass the message along to NextViewer, as we did in our WMDrawClipboard method. The final step is to remove our application from the Clipboard viewing chain. I recommend putting this logic in your main form's OnDestroy event. procedure TForm1.FormDestroy(Sender: TObject); begin ChangeClipboardChain(Handle, NextViewer) ; end;