When I copy something onto the clipboard, it shows up in the Clipboard history (Win+V). And with Windows 10 and Windows 11, it also syncs the clipboard with the cloud and other devices.
When I copy sensitive data onto the clipboard (like a password), I don't want it to show up in the history, and I don't want Windows to sync it to other devices.
How can I manage to do that?
You can not only put Text on the clipboard, but all kind of different types of data. It's like a Multi-Part-Message in an EMail, where you can have the mail in plain text and in HTML format.
There are many default Clipboard types that are known to Delphi. And on Windows 10 and later, the Cloud Clipboard has 3 new Clipboard types that are not represented by ID but per Name, such as "ExcludeClipboardContentFromMonitorProcessing"
:
https://learn.microsoft.com/en-us/windows/win32/dataxchg/clipboard-formats
You have to declare these 3 new types yourself and set them if you copy sensitive data.
I wrote a TClipboard
helper so it is easier to handle. It adds a SetTextWithoutHistory()
method.
Here is the helper:
unit vcl.Clipbrd.sec;
interface
uses
Windows, Clipbrd, SysUtils;
type
TClipboardSec = class helper for TClipboard
public
procedure SetTextWithoutHistory(const Value: string);
property AsTextWithoutHistory : string write SetTextWithoutHistory;
end;
implementation
var
dwNo : DWORD;
dwYes: DWORD;
CF_ExcludeClipboardContentFromMonitorProcessing : UINT;
CF_CanIncludeInClipboardHistory: UINT;
CF_CanUploadToCloudClipboard: UINT;
procedure TClipboardSec.SetTextWithoutHistory(const Value: string);
begin
Open;
try
Adding;
SetBuffer(CF_ExcludeClipboardContentFromMonitorProcessing, dwYes, sizeOf(DWORD) );
SetBuffer(CF_CanIncludeInClipboardHistory, dwNo, sizeOf(DWORD) );
SetBuffer(CF_CanUploadToCloudClipboard, dwNo, sizeOf(DWORD));
SetBuffer(CF_UNICODETEXT, PChar(Value)^, ByteLength(Value) + SizeOf(Char));
finally
Close;
end;
end;
initialization
dwNo := 0;
dwYes := 1;
CF_ExcludeClipboardContentFromMonitorProcessing := RegisterClipboardFormat('ExcludeClipboardContentFromMonitorProcessing');
if CF_ExcludeClipboardContentFromMonitorProcessing = 0
then RaiseLastOSError;
CF_CanIncludeInClipboardHistory := RegisterClipboardFormat('CanIncludeInClipboardHistory');
if CF_CanIncludeInClipboardHistory = 0
then RaiseLastOSError;
CF_CanUploadToCloudClipboard := RegisterClipboardFormat('CanUploadToCloudClipboard');
if CF_CanUploadToCloudClipboard = 0
then RaiseLastOSError;
finalization
end.
I hope it helps someone.
I needed a long time to figure it out.