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

时间:2019-08-28 13:55:31

标签: delphi paste delphi-2007

我正在通过分配WM_PASTE属性来拦截和抑制TDBEdit的{​​{3}}消息,如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.

1 个答案:

答案 0 :(得分:1)

在雷米对链接问题的回答中使用插入器类解决方案,如果为数据集创建BeforeEdit处理程序并在其中放置一个断点,则会发现断点在插入器的{{1}之前跳闸}方法输入。

如果您随后跟踪WMPaste()处理程序,最终将到达BeforeEdit,其中(在D7中)包含以下代码:

TDBEdit.KeyPress()

因此,由于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()的调用使DataSet进入KeyPress()状态。

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

^V