TStringGrid - OnMouseUp is not called!

前端 未结 2 1990
孤街浪徒
孤街浪徒 2021-01-23 00:12

I have a weird behavior with TStringGrid in Delphi 7. Delphi does not call the OnMouseUp event if a pop-up menu is associated to the grid. Basically, when the RMB is pressed, th

2条回答
  •  不知归路
    2021-01-23 00:21

    The automatic popping up of a context menu is a response to a right click of the mouse. The same click also fires the OnMouseUp event. The VCL developers could either choose to fire the 'OnMouseUp' event before the popup is shown, or after. Apparently the latter is in effect, that is, the event is fired when the popup is closed (either by mouse or by the keyboard like pressing 'Esc').

    There's no doubling of the event, when you press the left button to close the popup, you're firing the 'OnMouseUp' event again by releasing the left button.


    You have several alternatives. One is to derive a new class and override the MouseDown method to fire your own event. An example;

    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;
    


    Another alternative can be to handle VM_RBUTTONUP message. This can either be done by deriving a new class as above, or replacing the WindowProc of the grid. There's an example of replacing the WindowProc here in this question.


    Another alternative can be to leave the mouse-up event alone and do your processing in the OnPopup event of the popup menu. This event is fired before the popup is shown. You can get the mouse coordinates with Mouse.CursorPos.


    Still, another alternative can be to set the AutoPopup property of the popup menu to False, and in the OnMouseUp event (or better yet in the OnContextMenu event) first do some processing and then show the popup. An example;

    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;
    

提交回复
热议问题