1

Following the example here http://www.tek-tips.com/faqs.cfm?fid=6272 I have amended the component in order to detect the OnPaste event in a TRichEdit. The following is the source code:

type
  TStringEvent = procedure(Sender: TObject; var s: String) of object;
  TRichEditEx = class(TRichEdit)
  private
    FOnBeforePaste: TStringEvent;
    FOnAfterPaste: TNotifyEvent;
    procedure WMPaste(var Message: TMessage); message WM_PASTE;
  protected
  public
  published
    property OnBeforePaste: TStringEvent read FOnBeforePaste write FOnBeforePaste;
    property OnAfterPaste: TNotifyEvent read FOnAfterPaste write FOnAfterPaste;
  end;

procedure Register;

implementation

procedure Register;
begin
  RegisterComponents('.....', [TRichEditEx]);
end;

{ TRichEditEx }

procedure TRichEditEx.WMPaste(var Message: TMessage);
var
  strClpText: String;
begin
  // Check if the OnBeforePaste event is assigned and check if the clipboard contains plain text.
  if Assigned(FOnBeforePaste) and Clipboard.HasFormat(CF_TEXT) then
  begin
    // Save the clipboard text into a local variable
    strClpText := ClipBoard.AsText;
    // Fire the OnBeforePaste event
    FOnBeforePaste(self, strClpText);

    // Clear the clipboard and replace it with the new text
    Clipboard.Clear;
    Clipboard.AsText := strClpText;
  end;

  // Perform the actual paste
  inherited;

  // if the OnAfterPaste event is assigned, fire it.
  if Assigned(FOnAfterPaste) then
    FOnAfterPaste(self);
end;

end.

I registered the component succesfully but the two events are not fired.

What am I doing wrong here ?

EDIT

Inspired by TLama's solution I used another approach and overridden WM_KeyDown. The following is the code:

  TRichEditBeforePasteEvent = procedure(Sender: TObject; var Content: string; var CanPaste: Boolean) of object;
  TRichEditEx = class(Vcl.ComCtrls.TRichEdit)
  private
    FOnAfterPaste: TNotifyEvent;
    FOnBeforePaste: TRichEditBeforePasteEvent;
  protected
    procedure WM_KeyDown(var Msg: TWMKeyDown); message WM_KEYDOWN;
  public
    constructor Create(AOwner: TComponent); override;
  published
    property OnAfterPaste: TNotifyEvent read FOnAfterPaste write FOnAfterPaste;
    property OnBeforePaste: TRichEditBeforePasteEvent read FOnBeforePaste write FOnBeforePaste;
  end;
constructor TRichEditEx.Create(AOwner: TComponent);
begin
  inherited;
  Self.DefAttributes.Protected := True;
end;

procedure TRichEditEx.WM_KeyDown(var Msg: TWMKeyDown);
var
  ShiftState: TShiftState;
  Content: string;
  CanPaste: Boolean;
begin
  if PlainText then begin
    ShiftState := KeyDataToShiftState(Msg.KeyData);
    if (ssCtrl in ShiftState) and
       (Msg.CharCode = Ord('V')) then
    begin
      CanPaste:=True;
      if Assigned(FOnBeforePaste) then
      begin
        Content := Clipboard.AsText;
        FOnBeforePaste(Self, Content, CanPaste);
        Clipboard.AsText:=Content;
      end;
      if CanPaste then begin
        self.PasteFromClipboard;
        if Assigned(FOnAfterPaste) then
          FOnAfterPaste(Self);
      end
    end
    else
      inherited;
  end
    else
      inherited;
end;

and so far it works for me.

pio pio
  • 732
  • 1
  • 7
  • 29
  • 1
    Based on [`this suggestion`](http://stackoverflow.com/questions/6038998/richedit-not-respecting-plaintext-with-pasted-content#comment6991943_6040817) I made up [`this code`](http://pastebin.com/JPH8r8x1) which is missing the working `OnAfterPaste` event, since I don't know how to process the current message from the handler itself (shame on me, I never did that :) [@anyone, feel free to continue on this, I must leave for now] – TLama Mar 23 '15 at 15:58
  • Don't forget that you can paste by Shift + Insert as well (and what's worse, the user can have some sort keyboard mapper, which opens up other ways). And by context menu (if there's one). What's wrong with the `EN_PROTECTED` notification, anyway ? – TLama Mar 24 '15 at 10:17

0 Answers0