Delphi 为什么是数据集';在取消WM_粘贴后,s状态更改为dsEdit?

Delphi 为什么是数据集';在取消WM_粘贴后,s状态更改为dsEdit?,delphi,paste,delphi-2007,Delphi,Paste,Delphi 2007,我通过分配其属性来拦截和抑制TDBEdit的消息,如中所述 按下Ctrl+V键后,尽管截获了WM_-PASTE,但数据集的状态从dsBrowse变为dsEdit 为什么会发生这种情况?我如何避免这种情况 unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, ExtCtrls, DBCtrls, StdCtrls, Ma

我通过分配其属性来拦截和抑制
TDBEdit
的消息,如中所述

按下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对链接问题的回答中的interposer类解决方案,如果为数据集创建
BeforeEdit
处理程序并在其中放置断点,则会发现断点在输入interposer的
WMPaste()
方法之前移动

如果随后在编辑之前跟踪
处理程序,最终将到达
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;

你没有正确地遵循你给出的例子。WM_粘贴消息在这里被截获,但它也被传递到其他控件,如Edt。要真正解决这个问题,您需要对Edt进行子类化,这样才能防止WM_粘贴消息对该特定控件产生影响。非主题:无论如何,在Firefox中,为什么q在q的浏览列表中几乎显示为白色?@MartynA我不知道您想说什么。它在我的FireFox中看起来很好。@Martyn-您的忽略列表中可能有一个标记。“关注/忽略标记”列表位于浏览列表的右侧。我的意思是,在我的FF中,此q与所有其他q不同,它显示的文本比其他消息轻得多,几乎看不见。我每隔几天就注意到这一点。在
WMPaste()
中检查
Message.Msg
是不必要的,因为
Message
调度程序保证
WMPaste()
只会为
WM\u PASTE
消息调用。因此根本不需要在
WMPaste()
中调用
inherited
过程TDBEdit.WMPaste(var消息:TMessage);开始和结束
此外,当检测到
^V
时,无需在
KeyPress()
中调用
继承的
过程TDBEdit.KeyPress(变量键:Char);如果开始键=^V,则开始键:=#0;出口结束;继承;结束@Remy:谢谢,但是WMPaste处理程序在你的代码中,OP说他用过,所以我把它放在那里了。我想我要做的是保留原来的窗口过程替换,但用wm_char的一个替换wm_paste处理程序<代码>如果(AMessage.Msg=WM_CHAR)和(TWmChar(AMessage.CharCode=Ord(^V)),则退出
则不会生成wm_粘贴。@MartynA“WMPaste处理程序在您的代码中”-是的,但它没有检查
消息.Msg
,因为它不需要检查。“OP说他使用了”-不,OP使用了我的
WindowProc
示例,而不是我的插入器示例。在
WindowProc
中,确实需要检查
消息.Msg
。在这两个示例中,
SomeCondition
并不意味着“检查
消息。Msg
”我累了,而且wm_粘贴处理程序仍然是必需的,vcl在按键时起作用,但操作系统也有上下文菜单!。。
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;