Search code examples
delphiclipboardpaste

How to modify the text being pasted?


I'm trying to modify the text being pasted inside a TEdit descendant.

When the user paste some text, I want to replace all 'X' chars with an 'Y', without modifying the actual clipboard text content.

I've intercepted the WM_PASTE message, but I'm not aware about any "clean" way to change the text that's being pasted into the control.

unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;

type
  TMyEdit = class(Vcl.StdCtrls.TEdit)
  private
    procedure WMPaste(var Msg: TWMPaste); message WM_PASTE;
  end;

  TForm1 = class(TForm)
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

uses
  Clipbrd;

procedure TMyEdit.WMPaste(var Msg: TWMPaste);
begin
  inherited;
end;

procedure TForm1.FormCreate(Sender: TObject);
var
  Edt : TMyEdit;
begin
  Edt := TMyEdit.Create(Self);
  Edt.Top := 10;
  Edt.Left := 10;
  Edt.Parent := Self;
end;

end.

The only working way I've found is to temporarly replace the clipboard content, but I'm looking for a cleaner solution (if there's one...).

procedure TMyEdit.WMPaste(var Msg: TWMPaste);
var
  PrevClipboardText : string;
begin
  if(IsClipboardFormatAvailable(CF_TEXT)) then
  begin
    PrevClipboardText := Clipboard.AsText;
    try
      Clipboard.AsText := StringReplace(Clipboard.AsText, 'X', 'Y', [rfReplaceAll]);
      inherited;
    finally
      Clipboard.AsText := PrevClipboardText;
    end;
  end else
  begin
    inherited;
  end;
end;

Solution

  • Why not do the obvious thing?

    procedure TEdit.WMPaste(var Msg: TWMPaste);
    begin
      SelText := F(Clipboard.AsText);
    end;
    

    where F is your string-transforming function.