Search code examples
delphidelphi-xe7

Why the EN_PROTECT notification message is not sent to the RichEdit?


Using a runtime created TRichEdit descendant, I need to be notified when the EN_PROTECTED notification message is sent to the RichEdit.

As far as I know, it should be sent to the RichEdit wrapping any notification message who could edit a protected part of the text (for example: WM_PASTE) and the original notification message code should be available in TWMNotifyRE.ENProtected.msg.

Unfortunately, it seems that my RichEdit never receives the EN_PROTECTED notification message.

Code sample:

unit Unit1;

interface

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

type
  TMyRichEdit = class(Vcl.ComCtrls.TRichEdit)
  private
    procedure CNNotify(var AMessage: TWMNotifyRE); message CN_NOTIFY;
  end;

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

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TMyRichEdit.CNNotify(var AMessage: TWMNotifyRE);
begin
  if (AMessage.NMHdr.code = EN_PROTECTED) then
  begin
    //this code is never executed
    DoSometing();
  end else
  begin
    inherited;
  end;
end;

procedure TForm1.FormCreate(Sender: TObject);
var
  RichEdit : TMyRichEdit;
begin
  RichEdit := TMyRichEdit.Create(Self);
  RichEdit.Align := alClient;
  RichEdit.Parent := Self;
  RichEdit.ScrollBars := ssVertical;
  RichEdit.DefAttributes.Protected := True;
end;

end.

I've read that the DefAttributes.Protected must be set to True in order to get the EN_PROTECTED notification but it doesn't solved the problem


Solution

  • The problem is in DefAttributes implementation. It ignores any changes to it, if its TRichEdit control window handle hasn't been allocated yet.

    To fix that you can force allocating the handle before changing the DefAttributes:

    RichEdit.HandleNeeded;
    RichEdit.DefAttributes.Protected := True;
    

    When you put TRichEdit on the form in design-time, the designer initializes its Lines property to 'RichEdit1' or whatever, which will cause implicit handle allocation when loading the control from DFM. That would explain the difference between designer-created and manually-created control behavior.