You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何EN_PROTECTED通知消息未发送至TRichEdit派生控件?

解决TRichEdit派生类收不到EN_PROTECTED通知的问题

问题根源分析

你的代码存在两个关键问题:

  1. 未给RichEdit控件启用ENM_PROTECTED通知掩码,系统不会主动发送该类型通知。
  2. 仅设置DefAttributes.Protected只能让新输入文本默认带保护属性,但空控件下的粘贴操作不会触发保护检查;同时缺少启用控件保护通知的核心设置。

修正后的代码示例

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;
    procedure CreateWnd; override;
  end;

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

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TMyRichEdit.CreateWnd;
begin
  inherited;
  // 启用EN_PROTECTED通知掩码
  SendMessage(Handle, EM_SETEVENTMASK, 0, ENM_PROTECTED or GetEventMask);
  // 设置控件为全局保护模式,任何编辑操作都会触发EN_PROTECTED
  SendMessage(Handle, EM_SETPROTECTED, WPARAM(True), 0);
end;

procedure TMyRichEdit.CNNotify(var AMessage: TWMNotifyRE);
begin
  inherited; // 必须先调用inherited,保证系统正常处理其他通知
  if (AMessage.NMHdr.code = EN_PROTECTED) then
  begin
    // 根据原始消息类型判断操作
    case AMessage.ENProtected.msg of
      WM_PASTE: ShowMessage('尝试粘贴到受保护区域');
      WM_CUT: ShowMessage('尝试剪切受保护内容');
      WM_DELETE: ShowMessage('尝试删除受保护内容');
    end;
    // 若要阻止编辑操作,设置AMessage.Result := 1;
    // AMessage.Result := 1;
  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;
  // 添加测试用的受保护文本,方便快速验证效果
  RichEdit.Text := '这是受保护的文本';
end;

end.

关键修正点说明

  • 启用通知掩码:在CreateWnd中通过EM_SETEVENTMASK消息添加ENM_PROTECTED标志,告知系统需要发送该类型通知。
  • 全局保护模式:通过EM_SETPROTECTED消息设置控件为全局保护状态,此时任何编辑操作都会触发EN_PROTECTED;如果只想保护特定文本段,可去掉这条消息,转而给指定文本范围单独设置PROTECTED属性。
  • 正确调用inherited:在CNNotify中先执行inherited,确保系统正常处理其他通知逻辑,避免破坏控件原有功能。
  • 添加测试文本:空控件下的粘贴操作可能不会触发保护检查,提前添加受保护文本可快速验证通知是否生效。

内容的提问来源于stack exchange,提问作者Fabrizio

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 09:07:41