StringGrid i zaznaczanie klikniętego wiersza

0

Witam
Chcę by po kliknięciu w dowolne pole w wierszu StringGrid , wiersz ten był zaznaczony.
Korzystam z :

 
procedure TForm1.StringGrid1Click(Sender: TObject);
var
grid: TStringgrid;
gridcli:integer;

begin
   grid:= Sender As TStringgrid;
   gridcli:=grid.Row;

   stringgrid1.Selection:=TGridRect(Rect(0,gridcli,2,gridcli));
end;  

i owszem zaznacza (komórki wiersza zmieniają się na swój negatyw) ale tylko te komórki "nie kliknięte", komórka którą klikałem jest nadal w oryginalnym kolorze.
Jeżeli StringGrid ma tylko jedną kolumnę to po prostu nic nie jest zaznaczone.
Próbowałem użyć zdarzenia OnMouseUp ale efekt ten sam :/

0

Spróbowałem użyć procedury MStringGrid_SelectRow - niestety to nie działa - wywala błąd :

scr1.jpg

0

Więc źle spróbowałeś.
Pokaż jak spróbowałeś lub przekopiuj ten post do forum wróżbitów.

0

Użyłem procedury :

procedure MStringGrid_SelectRow(const aStGDs: TStringGrid; const aRowWybSr: Integer);
var
  _myRect: TGridRect;    // do zaznaczania
  _RowWyb: Integer;
begin
  if aRowWybSr>-1
  then _RowWyb := aRowWybSr+1
  else _RowWyb := aStGDs.RowCount-1;
 
    with aStGDs do
    begin
      Row     := _RowWyb;
      with _myRect do
      begin
        Top := _RowWyb;
        Bottom := _RowWyb;
        Left := 0;
        Right := 2;
      end;
      Selection := _myRect;
      SetFocus;
    end;
 
end;

Musiałem podać Left i Right na sztywno - w oryginalnej wersji kompilator nie chciał tego skompilować

i zmodyfikowałem swoją procedurę :

procedure TForm1.StringGrid1Click(Sender: TObject);
var
grid: TStringgrid;
gridcli:integer;
 
begin
   grid:= Sender As TStringgrid;
   gridcli:=grid.Row;
 
   MStringGrid_SelectRow(StringGrid1, gridcli);
end; 

Program się skompilował , uruchomił i po kliknięciu w StringGrid1 wyskakuje pokazany wcześniej błąd.

1

rysowanie grida możesz zmodyfikować przez oprogramowanie obsługi zdarzenia 'StringGrid1.ondrawcell'

procedure TForm5.StringGrid1Click(Sender: TObject);
var
  sgrid: TStringGrid;
begin
  sgrid := TStringGrid(Sender);
  self.s_row := sgrid.Row;
  sgrid.Refresh;
end;

procedure TForm5.StringGrid1DrawCell(Sender: TObject; ACol, ARow: Integer; Rect: TRect; State: TGridDrawState);
var
  sgrid: TStringGrid;
begin
  sgrid := TStringGrid(Sender);
  if ARow = self.s_row then
    sgrid.Canvas.Brush.Color := clblue
  else
    sgrid.Canvas.Brush.Color := clwhite;
  sgrid.Canvas.FillRect(Rect);
  sgrid.Canvas.TextOut(Rect.Left + 3, Rect.Top + 3, sgrid.Cells[ACol, ARow]);
end;

0

Kod można nieco uprościć, raz że przez Absolute, dwa - za pomocą IfThen:

procedure TForm5.StringGrid1Click(Sender: TObject);
var
  Grid: TStringGrid absolute Sender;
begin
  Self.s_row := Grid.Row;
  Grid.Refresh();
end;
 
procedure TForm5.StringGrid1DrawCell(Sender: TObject; ACol, ARow: Integer; Rect: TRect; State: TGridDrawState);
var
  Grid: TStringGrid absolute Sender;
begin
  Grid.Canvas.Brush.Color := IfThen(Self.s_row = ARow, clBlue, clWhite);
  Grid.Canvas.FillRect(Rect);
  Grid.Canvas.TextOut(Rect.Left + 3, Rect.Top + 3, Grid.Cells[ACol, ARow]);
end;

Przy czym w zdarzeniu StringGrid1DrawCell w ogóle nie potrzeba zmiennej, bo odwołania do zawartości skonkretyzowanego komponentu można wykonać za pomocą instrukcji wiążącej.

0

nie wiem jak w Lazarusie ale w Delphi coś takiego nie przejdzie :

  ifthen(ARow = self.s_row, clblue, clwhite); 

bo drugi i trzeci parametr muszą być typu string

0

Wątek widzę po tagu dotyczy Lazarusa, a w module Math znajdują się przeładowane wersje tej funkcji:

// Source position: math.pp line 587

function ifthen(
  val: Boolean;
  const iftrue: Integer;
  const iffalse: Integer = 0
):Integer; overload;

function ifthen(
  val: Boolean;
  const iftrue: Int64;
  const iffalse: Int64 = 0
):Int64; overload;

function ifthen(
  val: Boolean;
  const iftrue: Double;
  const iffalse: Double = 0.0
):Double; overload;

Widać Delphi w wersji jaką posiadasz nie dorobiło się wersji funkcji dla innych typów, ale bardzo łatwo samemu je napisać, nawet dla dedykowanych typów.

0

Witam ponownie - dziękuje za zainteresowanie, wszystkie te rady sprawdzę w poniedziałek - teraz nie mam "przy sobie" tego kodu.
Zastanawia mnie tylko brak prostego rozwiązania nie związanego z "przerysowywaniem" StringGrida :/
Niby

stringgrid1.Selection:=TGridRect(Rect(0,gridcli,2,gridcli)); 

działa, ale dlaczego nie zmienia się komórka "kliknięta" ?
To by uprościło całość.

0

Ok - zadziałała lekko zmodyfikowana wersja grzegorz_so :


procedure TForm1.StringGrid1Click(Sender: TObject);
var
grid: TStringgrid absolute Sender;
begin
   grid:= Sender As TStringgrid;
   IDstrgr1:=grid.Row;
end;

procedure TForm1.StringGrid1DrawCell(Sender: TObject; ACol, ARow: Integer; aRect: TRect; aState: TGridDrawState);
var
  sgrid: TStringGrid;
begin
  sgrid := TStringGrid(Sender);
  if ARow = IDstrgr1 then
   begin
    sgrid.Canvas.Brush.Color := clblue;
    sgrid.Font.Color := clwhite;
   end
  else
  begin
    sgrid.Canvas.Brush.Color := clwhite;
    sgrid.Font.Color := clblue;
  end;
  sgrid.Canvas.FillRect(aRect);
  sgrid.Canvas.TextOut(aRect.Left + 3, aRect.Top + 3, sgrid.Cells[ACol, ARow]);
end;                    

Gdzie IDstrgr1 to zmienna globalna - Self.s_row uniemożliwiało kompilację - nie znam się za bardzo na p.obiektowym ale s_row nie powinno być jakoś dodane (zainicjowane) do obiektu stringgrid1 ?

1

's_row' powinno być w definicji klasy Tform1.
do zapamiętania numeru zaznaczanego wiersza można też użyć pola Tag z klasy Tstringrid

procedure TForm1.StringGrid1Click(Sender: TObject);
var
grid: TStringgrid absolute Sender;
begin
     grid.tag =grid.Row;
end;
0

Dzięki teraz działa idealnie :)

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