2

I need to intercept the WM_PASTE message for a TEdit component which is placed inside a TFrame's descendant class.

If a condition is not satisfied, I want to iniby the paste operation.

Is there a way to do this at the frame level? (I mean, without declaring a TEdit's descendant)

Fabrizio
  • 7,603
  • 6
  • 44
  • 104

1 Answers1

5

Is there a way to do this at the frame level? (I mean, without declaring a TEdit's descendant)

WM_PASTE is sent directly to the TEdit window, the TFrame never sees it, so you must subclass the TEdit directly in order to intercept the message. You can either:

  • have the TFrame assign a handler to the TEdit's WindowProc property. This is a simple approach if you have only a few TEdits to subclass, but it gets more complicated the more TEdits you want to subclass:

    type
      TMyFrame = class(TFrame)
        Edit1: TEdit;
        ...
        procedure FrameCreate(Sender: TObject);
        ...
      private
        PrevWndProc: TWndMethod;
        procedure EditWndProc(var Message: TMessage);
        ...
      end;
    
    procedure TMyFrame.FrameCreate(Sender: TObject);
    begin
      PrevWndProc := Edit1.WindowProc;
      Edit1.WindowProc := EditWndProc;
      ...
    end;
    
    procedure TMyFrame.EditWndProc(var Message: TMessage);
    begin
      if Message.Msg = WM_PASTE then
      begin
        if SomeCondition then
          Exit;
      end;
      PrevWndProc(Message);
    end;
    
  • write and install a new component that is derived from TEdit, similar to the TMemo example you presented.

  • define an interposer class that is local to just the TFrame's unit, above the TFrame class declaration, which will intercept WM_PASTE for every TEdit on the Frame:

    type
      TEdit = class(Vcl.StdCtrls.TEdit)
        procedure WMPaste(var Message: TMessage); message WM_PASTE;
      end;
    
      TMyFrame = class(TFrame)
        Edit1: TEdit;
        Edit2: TEdit;
        ...
      end;
    
    procedure TEdit.WMPaste(var Message: TMessage);
    begin
      if not SomeCondition then
        inherited;
    end;
    
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • Great answer! The first way fits better for me in my case, because my frame contains other `TEdit` controls. Tested and working, thank you! – Fabrizio Mar 16 '18 at 12:50