当我执行OnDblClick事件(Form1)以打开Form2时,它将触发Form2的OnCellClick事件,而无需单击form2网格

时间:2019-01-28 11:43:08

标签: delphi delphi-10.2-tokyo

事件表格1:

procedure TForm1.Panel1DblClick(Sender: TObject);
begin
  TForm2.Create(Self).ShowModal;
end;

事件表格2:

procedure TForm2.DBGrid1CellClick(Column: TColumn);
begin
  ShowMessage('Test');
end;

如何避免fom2的onCellClick事件?

3 个答案:

答案 0 :(得分:4)

操作系统在鼠标左键的第二下位置显示一个WM_LBUTTONDBLCLK。当您在此处执行ShowModal调用时,直到显示对话框之后,应用程序才有机会处理尚未发布的WM_LBUTTONUP消息。由于TDBGrid会在控件处理OnCellClick消息时触发WM_LBUTTONUP事件,并且由于模态窗体现在是活动窗口,因此消息恰好发布到了网格中,因此您遇到了问题

网格的行为是documented;

  

当用户释放鼠标在其中一个单元格中时发生   网格。

尽管可以说它应该提到您甚至不必按下鼠标按钮...

这是一个不幸的设计决定,而不是单击的工作原理。想想按一个单元格上的按钮,然后释放另一个单元格上的按钮。不得解雇OnCellClick。当前行为相当令人困惑,如果您在有效单元格而不是空白空间上释放按钮,则事件将针对您按下按钮的单元格触发。

您已经发现,您甚至可以通过按其他表单上的按钮并将其释放到此表单上的网格单元中来触发事件。在这种情况下,该事件将触发当前选定的单元格,而鼠标位置根本不起作用。我认为OnCellClick真是一团糟。



您可以使用kobik's answer作为解决方案。如果由于某种原因在任何时间段内第二次按下鼠标键都无法按以下解决方案操作。


如问题注释中所建议的那样,张贴自己收到的消息以延迟对话框的显示是行不通的,因为张贴的消息比输入的消息具有更高的优先级。有关更多详细信息,请参见GetMessage的{​​{3}}。

如果您点击链接,您会注意到计时器方法也可以使用,如问题注释中所建议。与注释不同的是,由于WM_TIMER消息的优先级最低,因此时间间隔无关紧要。这是一件好事,这使其成为一种故障保护方法。

我想将计时器放在模式对话框中,因为它拥有问题控件。

procedure TForm2.FormCreate(Sender: TObject);
begin
  DBGrid1.Enabled := False;
  Timer1.Interval := 1;
  Timer1.Enabled := True;
end;

procedure TForm2.Timer1Timer(Sender: TObject);
begin
  DBGrid1.Enabled := True;
  Timer1.Enabled := False;
end;

答案 1 :(得分:3)

@Sertac对行为做了很好的解释。

我将尝试通过为TDBGrid创建一个插入程序类来提供另一种解决方法:

type
  TDBGrid = class(DBGrids.TDBGrid)
  protected
    FDown: Boolean;
    procedure MouseDown(Button: TMouseButton; Shift: TShiftState;
      X, Y: Integer); override;
    procedure MouseUp(Button: TMouseButton; Shift: TShiftState;
      X, Y: Integer); override;
  end;

  TForm2 = class(TForm)
    ...
    DBGrid1: TDBGrid;
    ...
  end;

implementation

procedure TDBGrid.MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
  FDown := True;
  try
    inherited;
  except
    FDown := False;
    raise;
  end;
end;

procedure TDBGrid.MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
  if FDown then
  try
    inherited;
  finally
    FDown := False;
  end;
end;

FDown标志仅表示MouseUp消息之后必须紧跟MouseDown
从我的快速测试中,我没有发现任何影响。但有可能

答案 2 :(得分:0)

您是否尝试过在DblClick处理程序中执行Application.ProcessMessages()

procedure TForm1.Panel1DblClick(Sender: TObject);
begin
  Application.ProcessMessages;
  TForm2.Create(Self).ShowModal;
end;