如何捕获编辑控件文本选中/取消选中事件实现内容实时同步
TMemo选中内容实时同步到TEdit无定时器实现方案
不需要依赖定时器,也不用局限于OnMouseUp/OnKeyUp这类操作结束才触发的事件,直接响应Windows原生编辑控件的EN_SELCHANGE通知即可,该通知会在所有选中状态发生变化的瞬间触发,包括鼠标拖动选中文本的过程、键盘按Shift+方向键选文本、全选、取消选中、代码修改选中范围等全部场景,完全满足实时同步要求。
实现逻辑
EN_SELCHANGE是编辑类控件(TMemo、TEdit等均属于原生Windows Edit控件封装)发送给父窗体的通知消息,VCL没有将其封装为公开事件,直接在窗体层拦截WM_COMMAND消息即可处理,无需自定义控件。- 默认状态下TMemo不会主动发送选中变化通知,需要先通过消息开启对应通知权限。
- 拦截到对应通知后,直接将TMemo的选中文本赋值给TEdit即可完成同步。
完整代码示例
首先在窗体类中声明消息处理方法:
type TMainForm = class(TForm) Memo1: TMemo; Edit1: TEdit; procedure FormCreate(Sender: TObject); private procedure WMCommand(var Msg: TWMCommand); message WM_COMMAND; end;
添加窗体创建时的初始化代码,开启选中通知:
procedure TMainForm.FormCreate(Sender: TObject); var EventMask: DWORD; begin // 获取控件原有事件掩码,追加选中变化通知权限 EventMask := SendMessage(Memo1.Handle, EM_GETEVENTMASK, 0, 0); SendMessage(Memo1.Handle, EM_SETEVENTMASK, 0, EventMask or ENM_SELCHANGE); end;
实现WM_COMMAND消息处理,实时同步选中文本:
procedure TMainForm.WMCommand(var Msg: TWMCommand); begin inherited; // 校验消息来源为目标Memo的选中变化通知 if (Msg.NotifyCode = EN_SELCHANGE) and (Msg.Ctl = Memo1.Handle) then begin Edit1.Text := Memo1.SelText; end; end;
方案优势
- 无定时器轮询,无额外性能开销
- 实时性强:拖动选择过程中每一次选中范围变动都会立刻触发更新,不需要等鼠标/按键抬起
- 场景覆盖全:鼠标选、键盘选、全选、取消选中、代码修改选中范围等所有导致选中内容变化的操作都能被捕获
- 兼容性好:所有Windows系统版本、所有Delphi版本均可正常使用,依赖的是Win32原生控件标准消息,无版本兼容问题
内容的提问来源于stack exchange,提问作者yonni
相关产品推荐
相关产品推荐

