为什么数据集的状态在抑制 WM_PASTE 后变为 dsEdit?
Why dataset's state changes to dsEdit after suppressing WM_PASTE?
我正在拦截和压制 WM_PASTE
message for a TDBEdit
by assigning its WindowProc
property, as described in 。
按下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.
在雷米对你的链接问题的回答中使用插入器 class 解决方案,如果你为你的数据集创建一个 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;
因此,由于 KeyPress()
看到 ^V
字符,调用 FDataLink.Edit()
将数据集置于 dsEdit
状态。
您还可以通过覆盖插入器 class 中的 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;
我正在拦截和压制 WM_PASTE
message for a TDBEdit
by assigning its WindowProc
property, as described in
按下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.
在雷米对你的链接问题的回答中使用插入器 class 解决方案,如果你为你的数据集创建一个 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;
因此,由于 KeyPress()
看到 ^V
字符,调用 FDataLink.Edit()
将数据集置于 dsEdit
状态。
您还可以通过覆盖插入器 class 中的 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;