Reputation: 8043
I'm intercepting and suppressing the WM_PASTE
message for a TDBEdit
by assigning its WindowProc
property, as described in this answer.
After pressing Ctrl+V, despite the WM_PASTE
is intercepted, the dataset's state changes from dsBrowse
to dsEdit
.
Why is this happening and how could I avoid that?
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.
Upvotes: 2
Views: 277
Reputation: 30715
Using the interposer class solution in Remy's answer to your linked question, if you create a BeforeEdit
handler for your DataSet and put a breakpoint in it, you will find that the breakpoint trips before the interposer's WMPaste()
method is entered.
If you then trace out of the BeforeEdit
handler, you will eventually arrive in TDBEdit.KeyPress()
which (in D7) contains the code below:
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;
So, the DataSet is put into dsEdit
state by the call to FDataLink.Edit()
as a result of KeyPress()
seeing the ^V
character.
You could achieve the behavior you want by also overriding KeyPress()
in the interposer class. The following will prevent pressing ^V
from having any effect:
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;
Upvotes: 1