delphi - 为什么抑制WM_PASTE后数据集的状态变为dsEdit?

标签 delphi paste delphi-2007

我通过分配WM_PASTE属性来拦截和禁止TDBEdit消息,如WindowProc中所述。

在按Ctrl + V后,尽管截取了WM_PASTE,但数据集的状态仍从dsBrowse变为dsEdit

为什么会发生这种情况,我该如何避免呢?

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, ExtCtrls, DBCtrls, StdCtrls, Mask, DB, DBClient;

type
  TForm1 = class(TForm)
    procedure FormCreate(Sender: TObject);
  private
    FPrevWindowProc : TWndMethod;
    procedure   MyWindowProc(var AMessage: TMessage);
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
var
  Dst : TClientDataSet;
  Dsc : TDataSource;
  Fld : TField;
  Nav : TDBNavigator;
  Edt : TDBEdit;
begin
  //dataset
  Dst := TClientDataSet.Create(Self);
  Dst.FieldDefs.Add('TEST', ftString, 20);
  Dst.CreateDataSet();
  Dst.Active := True;
  Fld := Dst.Fields[0];
  Dst.Append();
  Fld.AsString := 'test';
  Dst.Post();

  //datasource
  Dsc := TDataSource.Create(Self);
  Dsc.DataSet := Dst;

  //navigator
  Nav := TDBNavigator.Create(Self);
  Nav.DataSource := Dsc;
  Nav.Top := 3;  
  Nav.Left := 3;
  Nav.Parent := Self;

  //editor
  Edt := TDBEdit.Create(Self);
  Edt.DataSource := Dsc;
  Edt.DataField := Fld.FieldName;
  Edt.Top := 31;
  Edt.Left := 3;
  Edt.Parent := Self;
  FPrevWindowProc := Edt.WindowProc;
  Edt.WindowProc := MyWindowProc;
end;

procedure   TForm1.MyWindowProc(var AMessage: TMessage);
begin
  if(AMessage.Msg = WM_PASTE) then
  begin
    ShowMessage('WM_PASTE, exit!');
    Exit;
  end;

  FPrevWindowProc(AMessage);
end;

end.

最佳答案

使用Remy对链接的问题的答案中的插入器类解决方案,如果您为DataSet创建一个BeforeEdit处理程序并在其中放置一个断点,则您会发现断点在输入插入器的WMPaste()方法之前跳闸了。

如果随后从BeforeEdit处理程序中进行跟踪,则最终将到达TDBEdit.KeyPress(),其中(在D7中)包含以下代码:

procedure TDBEdit.KeyPress(var Key: Char);
begin
  inherited KeyPress(Key);
  if (Key in [#32..#255]) and (FDataLink.Field <> nil) and
    not FDataLink.Field.IsValidChar(Key) then
  begin
    MessageBeep(0);
    Key := #0;
  end;
  case Key of
    ^H, ^V, ^X, #32..#255:
      FDataLink.Edit;
    #27:
      begin
        FDataLink.Reset;
        SelectAll;
        Key := #0;
      end;
  end;
end;


因此,由于dsEdit看到FDataLink.Edit()字符,因此通过调用KeyPress()将DataSet置于^V状态。

您还可以通过覆盖插入器类中的KeyPress()来实现所需的行为。以下内容将防止按^V产生任何效果:

type  // This can be in your Form's unit but must go before your Form's type declaration
  TDBEdit = class(DBCtrls.TDBEdit)
    procedure WMPaste(var Message: TMessage); message WM_PASTE;
    procedure KeyPress(var Key: Char); override;
  end;
[...]

procedure TDBEdit.WMPaste(var Message: TMessage);
begin
  if not (Message.Msg = WM_PASTE) then
    inherited;
end;

procedure TDBEdit.KeyPress(var Key: Char);
begin
  case Key of
    ^V : Key := #0;
  end;  { case }
  inherited;
end;

关于delphi - 为什么抑制WM_PASTE后数据集的状态变为dsEdit?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57694135/

相关文章:

delphi - 如何禁用/隐藏表单中的图标?

delphi - 如何使用 RTTI 将事件处理程序分配给事件属性?

php - 使用 Delphi 2010 和 php4Delphi 编写 PHP 扩展

r - 在 R 中粘贴字符串最有效的方法是什么?

delphi - Delphi 2009 中的 dfm 中添加的 DoubleBuffered 属性在 Delphi 2007 中不存在

delphi - 跨进程单例对象

xml - NativeXml和线程

r - 连接列中的特定字符串

clipboard - 从剪贴板粘贴到 vim 脚本中

delphi - 如何在调用Web服务期间防止对话框(基本身份验证提示)