StringGrid obsługujący dwa różne TPopupMenu dla komórek

0

Witam.

Czy da się zrobić coś takiego.

Chodzi i o coś takiego, jedne popMenu1 działa tylko i wyłącznie dla Cells[0,0] a drugie popMenu2 dla reszty całego komponentu położonego na formie.

Pozdrawiam
Janusz

2

Ogólnie chodzi o to, aby:

  • stworzyć dwa różne TPopupMenu i nigdzie ich nie podłączać,
  • w zdarzeniu Grid.OnMouseDown należy:
    • pobrać współrzędne komórki na podstawie pozycji kliknięcia z parametrów X i Y,
    • jeśli współrzędne są równe 0:
      • przypisać do Grid.PopupMenu pierwsze menu,
    • jeśli koordynaty wskazują na inną komórkę:
      • przypisać do Grid.PopupMenu drugie menu.

W Lazarusie wygląda to tak:

procedure TForm1.StringGrid1MouseDown(ASender: TObject; AButton: TMouseButton; AShift: TShiftState; AX, AY: Integer);
var
  Grid: TStringGrid absolute ASender;
  Cell: TPoint;
begin
  if AButton = mbRight then
  begin
    Cell := Grid.MouseToCell(Point(AX, AY));

    if Cell = Point(0, 0) then
      Grid.PopupMenu := PopupMenu1
    else
      Grid.PopupMenu := PopupMenu2;
  end;
end;

Spróbuj czegoś podobnego.

3

Pod Delphi trochę inaczej:

procedure TForm2.StringGrid1ContextPopup(Sender: TObject; MousePos: TPoint;
  var Handled: Boolean);
var
  CX, CY: Integer;
begin
  TStringGrid(Sender).MouseToCell(MousePos.X, MousePos.Y, CX, CY);
  if (CX = 0) and (CY = 0) then
    TStringGrid(Sender).PopupMenu:= PopupMenu1
  else
    TStringGrid(Sender).PopupMenu:= PopupMenu2
end;
1

W ogóle to zdarzenie OnContextPopup jest lepsze do tego celu, niż OnMouseDown. Można też zamiast przypisywać menu do właściwości kontrolki, wywołać je samemu za pomocą metody TPopupMenu.Popup oraz ustawić Handled na True.

No i pod Lazarusem, metoda MouseToCell nie odróżnia kliknięcia w komórkę od kliknięcia w puste miejsce komponentu. W Delphi też tak jest, czy po kliknięciu w wolną przestrzeń zwraca -1 dla współrzędnych?

0

Działa tylko musiałem ją trochę zmodyfikować. Mam inne parametry wejściowe.

procedure TForm22.gGrid1MouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
var  Grid: TgGrid absolute Sender;
     ACol, ARow : integer;
begin
     if Button = mbRight then
          begin
             Grid.MouseToCell(X, Y, ACol, ARow);
             if (ACol=0) and (ARow=0) then Grid.PopupMenu := popC00
                                      else Grid.PopupMenu := popCxx;
          end;

end;

procedure TForm22.StringGrid1MouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
     // oryginalna siatka ma te same parametry
end;

Dziękuje.
Pozdrawiam
Janusz

0

Menu kontekstowe komponentu TStringGrid można wywołać dwojako:

  • prawym przyciskiem myszy,
  • specjalnym klawiszem klawiatury.

Obie te akcje spowodują wywołanie zdarzenia OnContextPopup, więc to @kAzek podał poprawne i bezpieczne rozwiązanie. Moje również działa, ale nie obsługuje sposobu z klawiaturą.

0

Może i metoda @kAzek jest i bardziej prawidłowa. Tylko jak tą metodą z klawiatury
obsłuży Cells[0,0] przy FixedCols=1 , FixedRows=1.

Wniosek jest prosty ten myk jest tylko i wyłącznie dla "myszy".

Ale Obaj macie rację. Jeszcze raz dziękuje za pomoc.
Pozdrawiam
Janusz.

1

Skrótem klawiatury zawsze wyświetla się nad komórką 0,0 ale można to zmienić aby wyświetlało się tam gdzie rzeczywiście jest kursor o ile ten znajduje się nad kontrolką a jeżeli nie to nie wyświetlać popup wcale.

procedure TForm2.StringGrid1ContextPopup(Sender: TObject; MousePos: TPoint;
  var Handled: Boolean);
var
  CX, CY: Integer;
begin
   Handled:= True; //sami w koncu wywolujemy popup
   if (MousePos.X = -1) and (MousePos.Y = -1) then //wywolane z klawiatury
   begin
     GetCursorPos(MousePos);
     MousePos:= TStringGrid(Sender).ScreenToClient(MousePos); //pozycja kursora
   end;

  TStringGrid(Sender).MouseToCell(MousePos.X, MousePos.Y, CX, CY);
  if (CX = 0) and (CY = 0) then
    TStringGrid(Sender).PopupMenu:= PopupMenu1
  else if (CX = -1) or (CY = -1)  then exit   //na pustym obsarze
  else
    TStringGrid(Sender).PopupMenu:= PopupMenu2;

  MousePos:= TStringGrid(Sender).ClientToScreen(MousePos);
  TStringGrid(Sender).PopupMenu.Popup(MousePos.X, MousePos.Y);
end;

1 użytkowników online, w tym zalogowanych: 0, gości: 1