2010-07-19 5 views
2

델파이 7에서 TStringGrid와 관련된 이상한 동작이 있습니다. 팝업 메뉴가 그리드와 연결되어 있으면 델파이는 OnMouseUp 이벤트를 호출하지 않습니다. 기본적으로 RMB을 누르면 메뉴 팝업이 OnMouseUp을 취소/지연합니다. 사실 100 % 정확하도록 다음 번에 마우스 버튼을 누르면 OnMouseUp이 두 번 호출됩니다. 한 번은 현재 이벤트에, 한 번은 손실/지연 이벤트에 대해 호출됩니다.TStringGrid - OnMouseUp이 호출되지 않았습니다!

다음에 사용자가 마우스 버튼을 누르면 불필요한 코드가 호출되므로 프로그램의 전체 논리가 엉망이됩니다.

답변

0

는 이미 어떻게 든 Sertac에 의해 설명 된 것과 유사한 접근을했다 : 난 그냥 그리드에 팝업 메뉴를 할당 더 이상 PopupMenu로 속성을 사용하지 않습니다. 대신, 내 눈금 내 눈금 (내 눈금 TStringGrid 파생 된 무겁게 수정 된 문자열 표입니다) 마우스 아래로 이벤트를 처리하고 원하는 방식으로 팝업 표시 및 메뉴 팝 전에 수행 할 추가 처리 할.

4

컨텍스트 메뉴의 자동 팝업은 마우스 오른쪽 버튼 클릭에 대한 응답입니다. 같은 클릭으로 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을 대체하여이 작업을 수행 할 수 있습니다. 이 question에 WindowProc here을 바꾸는 예가 있습니다.


또 다른 방법으로 마우스 업 이벤트 만 남겨두고 팝업 메뉴의 OnPopup 이벤트에서 처리 할 수도 있습니다. 이 이벤트는 팝업이 표시되기 전에 시작됩니다. Mouse.CursorPos으로 마우스 좌표를 가져올 수 있습니다.


또 다른 대안은 False에 팝업 메뉴의 AutoPopup 속성을 설정할 수 있으며, (더 나은 아직 OnContextMenu 이벤트 나)에 OnMouseUp 이벤트에 우선 몇 가지 처리를 수행 한 후 팝업을 보여줍니다. 보기;

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; 
+0

"분명히 후자가 효과가 있습니다." 이것은 OnMouseUp 이벤트가 마우스 업 이벤트가 아니기 때문에 직관적 인 카운터입니다. 실제로, 그것은 "마우스 다운"이벤트입니다 !!! 당신의 완전한 답을 +1하십시오. – Ampere

+0

@Altar> "... counter intuitive ..."- 나는 팝업 메뉴가 실제로 WM_RBUTTONUP뿐만 아니라 WM_NCRBUTTONUP과 함께 생성 된 'WM_CONTEXTMENU'에 대한 응답이라는 점을 고려하면 ' Shift + F10 '과 VK_APPS가 있으며, 예를 들어 VK_APPS를 사용하면 팝업이 표시되기 전에 OnKeyUp이 시작됩니다. –

관련 문제