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;