TStringGrid - OnMouseUp не вызывается!

У меня странное поведение с TStringGrid в Delphi 7. Delphi не вызывает событие OnMouseUp, если всплывающее меню связано с сеткой. В основном, когда нажимается RMB, всплывающее меню как-то отменяет / задерживает OnMouseUp. На самом деле, чтобы быть точным на 100%, при следующем нажатии кнопки мыши OnMouseUp вызывается дважды - один раз для текущего события и один раз для потерянного / отложенного события.

Это испортит всю логику программы, так как нежелательный код будет вызван в следующий раз, когда пользователь нажмет кнопку мыши.

2 ответа

Решение

Я уже использовал подход, похожий на описанный Sertac: я просто больше не использую свойство PopupMenu, чтобы назначить всплывающее меню для сетки. Вместо этого внутри моей сетки (моя сетка представляет собой сильно измененную строковую сетку, полученную из TStringGrid), я обрабатываю событие мыши и отображаю всплывающее окно так, как я хочу, и выполняю дополнительную обработку, которую я хотел выполнить, ДО появления меню.

Автоматическое отображение контекстного меню - ответ на щелчок правой кнопкой мыши. Тот же щелчок также запускает OnMouseUp событие. Разработчики VCL могут либо выбрать событие OnMouseUp до отображения всплывающего окна, либо после. По-видимому, последнее действует, то есть событие запускается, когда всплывающее окно закрывается (либо с помощью мыши, либо с помощью клавиатуры, например, при нажатии клавиши "Esc").

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


У вас есть несколько альтернатив. Одним из них является создание нового класса и переопределение MouseDown способ запустить ваше собственное событие. Пример;

type
  TMyStringGrid = class(TStringGrid)
  private
    FOnRButtonUp: TMouseEvent;
  protected
    procedure MouseDown(Button: TMouseButton; Shift: TShiftState;
      X, Y: Integer); override;
  published
    property OnRButtonUp: TMouseEvent read FOnRButtonUp write FOnRButtonUp;
  end;
[...]

procedure TStringGrid.MouseDown(Button: TMouseButton; Shift: TShiftState; X,
  Y: Integer);
begin
  if (Button = mbRight) and Assigned(FOnRButtonUp) then
    FOnRButtonUp(Self, Button, Shift, X, Y);
  inherited;
end;


Другой альтернативой может быть обработка VM_RBUTTONUP сообщение. Это можно сделать путем получения нового класса, как указано выше, или замены WindowProc сетки. В этом вопросе есть пример замены WindowProc.


Другой альтернативой может быть то, что вы можете оставить событие мышки в покое и выполнить обработку в OnPopup событие всплывающего меню. Это событие вызывается перед показом всплывающего окна. Вы можете получить координаты мыши с Mouse.CursorPos,


Тем не менее, другой альтернативой может быть установить AutoPopup свойство всплывающего меню False и в OnMouseUp событие (или еще лучше в OnContextMenu событие) сначала выполнить некоторую обработку, а затем показать всплывающее окно. Пример;

procedure TForm1.StringGrid1MouseUp(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
var
  Pt: TPoint;
begin
  // Do processing

  if Button = mbRight then begin
    Pt := (Sender as TStringGrid).ClientToScreen(Point(X, Y));
    PopupMenu1.Popup(Pt.X, Pt.Y);
  end;
end;
Другие вопросы по тегам