当用户按下 CTRL+X 并仍然保持 TMemo 的默认 CTRL+X 行为时如何进行干预?

How to interfere when user presses CTRL+X and still keep TMemo's default CTRL+X behavior?

我在表单上有一个 TMemo,我已经为它设置了一个 OnChange 事件。我希望当用户在备忘录中按下 Ctrl+X 时不会触发 OnChange 事件。但是 Ctrl+X 只是切断了文本选择,这肯定会触发 OnChange 事件。我怎样才能防止这种情况发生?

我尝试在 KeyUp 事件中检测 Ctrl+X,如果用户按下 Ctrl+X 我取消绑定备忘录的 OnChange 事件并以编程方式再次剪切文本。但这不起作用,我不知道如何以编程方式发送 Ctrl+X.

procedure TForm1.Memo1KeyUp(Sender: TObject; var Key: Word; Shift: TShiftState);
begin
  if (Key = Ord('X')) and (Shift = [ssCtrl]) then
  begin
    Memo1.OnChange := nil;
    // programmatically cut the text here, which I don't know how to do
    Memo1.OnChange := Memo1Change;
  end;
end;

不要依赖键盘事件(例如,当您使用弹出菜单剪切某些内容时,它们不会执行),而是依赖 windows 消息。

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

type
  TForm1 = class(TForm)
    Memo1: TMemo;
    procedure Memo1Change(Sender: TObject);
    procedure FormCreate(Sender: TObject);
  private
    FPrevMemoWindowProc : TWndMethod;
    procedure MemoWindowProc(var AMessage: TMessage);
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

uses
  Clipbrd;

procedure TForm1.MemoWindowProc(var AMessage: TMessage);
begin
  if(AMessage.Msg = WM_CUT) then
  begin
    if(Memo1.SelLength > 0) then
    begin
      Memo1.OnChange := nil;
      try
        Clipboard.AsText := Memo1.SelText;
        Memo1.ClearSelection();
        Exit;
      finally
        Memo1.OnChange := Memo1Change;
      end;
    end;
  end;

  FPrevMemoWindowProc(AMessage);
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  FPrevMemoWindowProc := Memo1.WindowProc;
  Memo1.WindowProc := MemoWindowProc;
end;

procedure TForm1.Memo1Change(Sender: TObject);
begin
  ShowMessage('Change');
end;