Immer wieder kommt hier die Frage auf, wie man überwachen kann, ob und wann sich der Inhalt der Zwischenablage ändert. Und da ich heute genau das brauchte, nahm ich mir die Freiheit dieses mal als Delphi-App für die Code-Library aufzubereiten.
Theorie:
Das Fenster, welches sich in die Liste derere einreihen möchte, die das Clipboard beobachten, muss sich mittels
SetClipboardViewer registrieren. Als Ergebnis erhalten wir das
Handle des nächsten Beobachterfensters. Gibt es keines, so ist das Ergebnis 0. Schlägt der Aufruf fehl, so ist das Ergebnis auch 0
Also mit
GetLastError testen, ob es nicht doch korrekt ist.
Wenn das Fenster nicht mehr beobachten will bzw. (ganz wichtig), wenn das Fenster geschlossen wird, so muss
ChangeClipboardChain aufgerufen werden.
Des Weiteren müssen noch 2 Windows-Botschaften abgearbeitet werden, welche nur dann aufgerufen werden, wenn wir uns auch im ersten Schritt als Beobachter angemeldet haben:
WM_CHANGECBCHAIN und
WM_DRAWCLIPBOARD
Hier mal die wichtigsten Teile des Codes, das komplette Beispiel findet Ihr als Download im Anhang.
Delphi-Quellcode:
procedure TfrmClpBrdVw.WMChangeCBChain(
var Msg: TWMChangeCBChain);
begin
if Msg.Remove = FNextViewer
then
begin
FNextViewer := Msg.Next;
Msg.Result := 0;
end
else
begin
if (FNextViewer <> 0)
and (FNextViewer <> INVALID_HANDLE_VALUE)
then
Msg.Result := SendMessage(FNextViewer, WM_CHANGECBCHAIN, TMessage(Msg).WParam, TMessage(Msg).LParam);
end;
end;
procedure TfrmClpBrdVw.WMDrawClipboard(
var Msg: TWMDrawClipboard);
begin
lblDateTime.Caption := DateTimeToStr(Now);
if ClpBrd.HasFormat(CF_TEXT)
then
begin
mmoClipbrdContents.Text := ClpBrd.AsText;
end
else
begin
mmoClipbrdContents.Text := '
';
end;
if (FNextViewer <> 0)
and (FNextViewer <> INVALID_HANDLE_VALUE)
then
Msg.Result := SendMessage(FNextViewer, WM_DRAWCLIPBOARD, TMessage(Msg).WParam, TMessage(Msg).LParam);
end;
procedure TfrmClpBrdVw.AttachToClipboard;
begin
if FNextViewer = INVALID_HANDLE_VALUE
then
begin
FNextViewer := SetClipboardViewer(
Handle);
if FNextViewer = 0
then
if GetLastError <> 0
then
ShowMessage(LastErrorMsgStr);
end;
end;
procedure TfrmClpBrdVw.DetachFromClipboard;
begin
if FNextViewer <> INVALID_HANDLE_VALUE
then
begin
ChangeClipboardChain(
Handle, FNextViewer);
FNextViewer := INVALID_HANDLE_VALUE;
end;
end;
Danke an unseren Nutzer
Benedikt für Hinweise zu 0 und INVALID_HANDLE_VALUE
...
...