Search code examples
delphipastedelphi-2007windows-messages

How to intercept and suppress a message for a TFrame's subcomponent?


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)


Solution

  • 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;