Когда я выполняю событие OnDblClick (Form1), чтобы открыть Form2, оно запускает событие OnCellClick Form2, не щелкая по сетке form2 - PullRequest
0 голосов
/ 28 января 2019

Форма события 1:

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

Форма события 2:

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

Что я должен сделать, чтобы избежать события onCellClick в fom2

Ответы [ 3 ]

0 голосов
/ 30 января 2019

@ 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;

The FDownфлаг просто указывает, что MouseUp должен выполняться только после сообщения MouseDown.
Из моего быстрого теста я не заметил никаких последствий.но может быть.

0 голосов
/ 31 января 2019

Вы пытались сделать Application.ProcessMessages() в обработчике DblClick?

procedure TForm1.Panel1DblClick(Sender: TObject);
begin
  Application.ProcessMessages;
  TForm2.Create(Self).ShowModal;
end;
0 голосов
/ 30 января 2019

ОС выводит WM_LBUTTONDBLCLK на второй нажатие левой кнопки мыши.Когда вы выполняете вызов ShowModal здесь, приложение не получает возможности обработать, еще не опубликованное, сообщение WM_LBUTTONUP до тех пор, пока не отобразится ваше диалоговое окно.Так как TDBGrid запускает событие OnCellClick, пока элемент управления обрабатывает сообщение WM_LBUTTONUP, и сообщение оказывается отправленным в сетку, поскольку модальная форма является активным окном, вы столкнулись с проблемой.

Поведение сетки имеет вид задокументировано ;

Происходит, когда пользователь отпускает мышь в одной из ячеек сетки.

хотя можно утверждать, что следовало бы упомянуть, что вам даже не нужно нажимать кнопку мыши ...

Это неудачное дизайнерское решение, это не то, как работает щелчок.Подумайте о том, чтобы нажать кнопку на одной ячейке и отпустить на другой.Нет OnCellClick должен быть уволен.Текущее поведение довольно запутанно, событие запускается для ячейки, на которой вы нажали кнопку - при условии, что вы отпустите кнопку в действительной ячейке, а не в пустом месте.

Как вы узнали, вы даже можете запустить событие, нажав кнопку в другой форме и отпустив ее в ячейке сетки этой формы.В этом случае событие запускается для выбранной в данный момент ячейки, и положение мыши не играет в этом никакой роли.Мое мнение таково, что OnCellClick - полный беспорядок.

Вы можете использовать ответ Кобика для решения.Приведенное ниже решение не может быть выполнено, если по какой-то причине кнопка мыши удерживается при втором нажатии в течение какого-либо периода времени.

Публикация сообщения, полученного пользователем, для задержки показа диалогового окна, как предлагается в комментариях к вопросу, не работает, поскольку отправленные сообщения имеют более высокий приоритет, чем входные сообщения.См. документацию для GetMessage для более подробной информации.

Если вы перейдете по ссылке, вы заметите, что таймерный подход, также предложенный в комментариях к вопросу, будет работать.В отличие от комментария предполагается, что временной интервал не имеет значения, поскольку сообщение 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;
...