Click here to Skip to main content
15,867,308 members
Please Sign up or sign in to vote.
1.00/5 (1 vote)
See more:
I need to temporarily prevent other programs from being able to monitor changes made to Clipboard interrupting the Clipboard messages chain. How could this be done in Delphi?

I found this code which was supposed to do the trick but it doesn't (in Win 10 Ent x64). Is there any mistake in this code that can be corrected?

The PAS file follows:

(* ---------------------------------------------------------------
 { TAntiClipboardLogging }
Generates OnClipboardChange event when contents of clipboard
changes. Property PreventClipboardLogging to toggle ClipboardLogging
on or off.

Sample code usage:
==================

  private
    { Private declarations }
    FBlocker: TAntiClipboardLogging; // for anti-Clipboard logging

procedure TFormMain.StartAntiClipboardLoggingProc;
begin
  // start anti-Clipboard logging
  FBlocker := TAntiClipboardLogging.Create;
  FBlocker.PreventClipboardLogging := True;
  Application.ProcessMessages;
end;

procedure TFormMain.StopAntiClipboardLoggingProc;
begin
  // stop anti-Clipboard logging
  FBlocker.PreventClipboardLogging := False;
  FBlocker.Free;
  Application.ProcessMessages;
  Sleep(100); // e.g. if clearing Clipboard afterwards
end;
---------------------------------------------------------------- *)
unit AntiClipboardLogging;

interface

uses
  Windows, Messages, Classes;

type
  TClipboardChangeEvent = TNotifyEvent;

  { TClipboardActivityMonitor }
  TClipboardActivityMonitor = class(TPersistent)
  private
    FMonitorWindow: THandle;
    FNextWindow: THandle;
    FPreventClipboardLogging: Boolean;
    FOnClipboardChange: TClipboardChangeEvent;
    procedure PassMessage(Message: TMessage);
    procedure SetPreventClipboardLogging(const Value: Boolean);
  protected
    procedure DoClipboardChange; virtual;
    procedure WndProc(var Message: TMessage); virtual;
    property OnClipboardChange: TClipboardChangeEvent
      read FOnClipboardChange write FOnClipboardChange;
  public
    constructor Create; virtual;
    destructor Destroy; override;
    property PreventClipboardLogging: Boolean
      read FPreventClipboardLogging write
      SetPreventClipboardLogging;
  end;

  TAntiClipboardLogging = class(TClipboardActivityMonitor)
  published
    property OnClipboardChange;
    property PreventClipboardLogging;
  end;

implementation

uses
  Forms;

{ TClipboardActivityMonitor }

constructor TClipboardActivityMonitor.Create;
begin
  FPreventClipboardLogging := False;
end;

destructor TClipboardActivityMonitor.Destroy;
begin
  SetPreventClipboardLogging(False);
  inherited;
end;

procedure TClipboardActivityMonitor.DoClipboardChange;
begin
  if Assigned(FOnClipboardChange) then
    FOnClipboardChange(Self);
end;

procedure TClipboardActivityMonitor.PassMessage(Message: TMessage);
begin
  SendMessage(FNextWindow, Message.Msg, Message.WParam,
    Message.LParam);
end;

procedure TClipboardActivityMonitor.SetPreventClipboardLogging(const
  Value: Boolean);
begin
  if FPreventClipboardLogging = Value then
    Exit;
  if Value then
    begin
      FMonitorWindow := AllocateHWnd(WndProc);
      FNextWindow := SetClipBoardViewer(FMonitorWindow);
    end
  else
    begin
      ChangeClipboardChain(FMonitorWindow, FNextWindow);
      DeallocateHWnd(FMonitorWindow);
    end;
  FPreventClipboardLogging := Value;
end;

procedure TClipboardActivityMonitor.WndProc(var Message: TMessage);
begin
  if Message.Msg = WM_DRAWCLIPBOARD then
    begin
      // This Message is also triggered when starting
      // or stopping to monitor
      // In these cases Clipboard.FormatCount will always
      // return 0 (??)
      try
        DoClipboardChange;
      finally
      // PassMessage(Message); // Remove this line to break chain
      end;
    end;

  //wParam = HWNDRemove
  //lParam = HWNDNext
  if Message.Msg = WM_CHANGECBCHAIN then
    begin
      // If next window is the one to be removed, LParam is
      // the new NextWindow.
      // Else pass the message to our NextWindow
      if FNextWindow = Cardinal(Message.WParam) then
        FNextWindow := Cardinal(Message.LParam)
      else
        PassMessage(Message);
    end;

  with Message do
    Result := DefWindowProc(FMonitorWindow, Msg, wParam, lParam);
end;

end.


What I have tried:

The above code but it doesn't work.
Posted
Updated 29-May-18 22:14pm
v2

As far as I know, you can't prevent any application - let alone all of them - from accessing the clipboard at any time. That's kind of the point - the clipboard is a data exchange area for the user, not for applications.

If you are using the clipboard as an inter-process communications channel, you will annoy the heck out of "normal users" who want what they copied on there. You should probably redesign to use Sockets instead of the clipboard - it'll be more robust, more secure, and it won't annoy your users!
 
Share this answer
 
Comments
Selukwe 30-May-18 13:53pm    
Thanks. I do not want to block the clipboard. It is not about preventing applications accessing clipboard. I am aware that this is not possible. But if I get it correct, changed clipboard sends message to other apps informing them about the change. What I'm after is temporarily interrupting this message chain so that other apps will not notice the changed clipboard contents. But this contents will still be there and accessible on paste action - both by menu right-click as well as keyboard shortcut.

The code I presented worked well in Win XP and I think also in Win 7, but fails to work in Win 10. So I'm seeking a skilled Delphi expert to advise on possible workaround in the latest Windows environment. Any workable sample of using Sockets for this purpose?
Your code uses the clipboard viewer chain to get notified about clipboard change events and misuses that to prevent other applications that have registered themself to the chain from being notified.

But that solution has three drawbacks:
  1. The clipboard can be accessed by any application at any time
  2. Applications that are in the chain before your application are still getting notified
  3. Most applications did not even use the clipboard chain

So using such code is rather useless. It will not work reliable even when you only want to avoid the notifications being send to other applications from the chain because some will still get them.
 
Share this answer
 
Comments
Selukwe 30-May-18 13:59pm    
Thanks Jochen. You seem to get my point and seem knowledgable about clipboard mechanism. So to sum it up - is there a workaround to make this work? I am after pasting from clipboard some text that for a few seconds should not be retrievable from clipboard by other apps. Can this be done?
Jochen Arndt 30-May-18 14:58pm    
There is no real solution. Once something has been put on the clipboard it is available for all other aplications.

What you could do is getting all data from the clipboard into local storage, clear the clipboard, and put the data back after some time.

But that is an advanced task requiring very good knowledge about the clipboard. You have to handle all the clipboard storage formats, it will not work for some data (those not using the default release method), it might use additional memory (for data using delay rendering), and may have unwanted side effects (e.g. with delete on paste operations used by the Explorer when cutting files).
Jochen Arndt 30-May-18 15:49pm    
Such is called IPC (Inter Process Communication). There are multiple methods to implement such like sockets on localhost or shared memory but both sides must use the same method and know how to handle the data (use the same protocol).
Selukwe 31-May-18 5:52am    
This is not useful to me. I am after ability to transfer strings into ordinary third party programs that I have no control about.

How safe from logging is drag-and-drop? I haven't heard of drag-and-drop loggers while any clipboard manager is essentially a functional clipboard logger...
Jochen Arndt 31-May-18 6:00am    
Any window that has registered itself as drop target will be notified when the mouse cursor enters, moves over, or leaves the window while dragging. With the notifications such windows have full access to the data being dragged.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900