Witam społeczność.
Pytanie jak w temacie. Jak zrobić, aby wiersz pod kursorem (aktywna komórka) podświetlił się? No i żeby to podświetlenie wędrowało, jak będę przeskakiwał strzałkami w górę i w dół.
- Rejestracja:ponad 22 lata
- Ostatnio:minuta
- Postów:296

- Rejestracja:ponad 13 lat
- Ostatnio:około 4 godziny
- Lokalizacja:Tuchów
- Postów:12164
Można wymusić aktywację konkretnej komórki w zdarzeniu OnMouseMove
. Wersja dla Delphi:
procedure TForm1.StringGrid1MouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
var
Grid: TStringGrid absolute Sender;
Col, Row: Integer;
begin
Grid.MouseToCell(X, Y, Col, Row);
Grid.Col := Col;
Grid.Row := Row;
end;
Wersja dla Lazarusa:
procedure TForm1.StringGrid1MouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
var
Grid: TStringGrid absolute Sender;
Cell: TPoint;
begin
Cell := Grid.MouseToCell(Point(X, Y));
Grid.Col := Cell.X;
Grid.Row := Cell.Y;
end;
W połączeniu z opcją goRowSelect
wygląda dość dobrze – i da się zaznaczenie przesuwać klawiaturą.
Ale będą z tym problemy, jeśli zechcesz zezwolić użytkownikowi na zaznaczanie zakresów lub edycję zawartości. W takim przypadku być może lepszą opcją będzie ręczne malowanie komórek, czyli obsługę zdarzenia OnDrawCell
.
- Rejestracja:ponad 14 lat
- Ostatnio:około 8 godzin
@furious programming: , @kAzek, @autor
Malowanie komórek stringgrida
za pomocą własnego kodu może być najlepszym rozwiązaniem, czyli obsługa zdarzenia OnDrawCell
.
Może to trudniejsze od ustawienia takich czy innych opcji stringgrida
, ale za to są niemal nieograniczone możliwości wizualizacji

- Rejestracja:ponad 22 lata
- Ostatnio:minuta
- Postów:296
Ok. Staram się to wdrożyć. Niestety. Jest problem. Na początek kod.
procedure TMyStringGrid.DrawCell(ACol, ARow: Integer; ARect: TRect;
AState: TGridDrawState);
begin
if (Length(Cells[7, ARow]) > 80) then
begin
Canvas.Brush.Color := RGB(255, 210, 210);
if (ARow = Row) then Canvas.Brush.Color := RGB(0, 255, 0)
else Canvas.Brush.Color := clWhite;
end
else
begin
Canvas.Brush.Color := clWhite;
if (ARow = Row) then Canvas.Brush.Color := RGB(0, 255, 0)
else Canvas.Brush.Color := clWhite;
end;
inherited DrawCell(ACol, ARow, ARect, AState);
end;
Nie wiem jak to ugryźć. Przede wszystkim procedura ma pokolorować wiersz, na czerwono, jeśli w danej kolumnie ilość znaków przekroczy 80. Po drugie, na zielono ma się zaznaczyć aktywny wiersz. Jednocześnie ma przy dwukliku na daną komórkę ma się pobierać jej zawartość. Ktoś pomoże?
- Rejestracja:ponad 22 lata
- Ostatnio:minuta
- Postów:296
Czy ktoś pomoże?



- Rejestracja:ponad 13 lat
- Ostatnio:około 4 godziny
- Lokalizacja:Tuchów
- Postów:12164
@Buster: nie wiem na ile to będzie pomocne, ale pod Lazarusem udało mi się to wykonać:
procedure TForm1.StringGrid1DrawCell(ASender: TObject; ACol, ARow: Integer; ARect: TRect; AState: TGridDrawState);
var
Grid: TStringGrid absolute ASender;
begin
if gdFixed in AState then Exit;
if gdRowHighlight in AState then
Grid.Canvas.Brush.Color := clGreen
else
if Grid.Cells[5, ARow].Length = 0 then
Grid.Canvas.Brush.Color := clRed;
Grid.DefaultDrawCell(ACol, ARow, ARect, AState);
end;
Jak to wygląda – kontrolka ma ustawiony DefaultDrawing
na True
, aby sama malowała odpowiednio komórki. We właściwości Options
mam zaznaczoną opcję goRowHighligh
, aby móc obsłużyć funkcję zaznaczania wierszami. Jest też zaznaczona opcja goEditing
, aby móc edytować zawartość komponentu. Po zmianie danych, komponent prawidłowo odmalowywuje cały wiersz – to zasługa podświetlania bieżącego wiersza.
Aktywny wiersz ma wyższy priorytet od tego z nieprawidłowymi danymi. Oznacza to, że jeśli dany wiersz jest jednocześnie zaznaczony oraz posiada błędne dane w określonej kolumnie, wiersz zostanie pomalowany na zielono, a nie na czerwono.
Pod Delphi trzeba będzie zapisać to nieco inaczej, dlatego że z tego co widzę w dokumentacji, TStringGrid
nie ma opcji goRowHighlight
, więc trzeba będzie skorzystać z goRowSelect
i zmienić warunek na taki:
if gdSelected in AState then
Grid.Canvas.Brush.Color := clGreen
Zmienić trzeba też warunek, dlatego że u siebie (dla testu) sprawdzam czy w szóstej kolumnie coś jest i jeśli nie ma, to wiersz malowany jest na czerwono. Ty chcesz sprawdzać, czy tekst jest dłuższy niż 80 znaków, więc to sobie zmień. No i metody TStringGrid.DefaultDrawCell
może pod Delphi nie być, więc zmień sobie na inherited
(o ile faktycznie tak powinno się wołać bazową metodę komponentu).
Spróbuj przeportować ten kod i sprawdź, czy działa właściwie. W razie czego coś się jeszcze pomyśli.
- grid.png (14 KB) - ściągnięć: 184
- Rejestracja:ponad 22 lata
- Ostatnio:minuta
- Postów:296
Przeportowałem i śmiga. Ale..... Po dwukliku do edycji otwiera się zawsze komórka z pierwszej kolumny. Nieważne, którą komórkę się kliknie.
Kod po przeportowaniu:
//if gdFixed in AState then Exit; - ten wiersz niepotrzebny; jak jest, to wtedy nie widać nazw kolumn po załadowaniu pliku.
if gdSelected in AState then Canvas.Brush.Color := clGreen
else if Cells[7, ARow].Length > 80 then Canvas.Brush.Color := clRed;
inherited DrawCell(ACol, ARow, ARect, AState);
- Rejestracja:ponad 14 lat
- Ostatnio:około 8 godzin
kod rysujący "stringgrida" nie ma żadnego związku z kodem obsługującym "dwuclick" ....
pokaż kod obsługujący "DblClick"
- Rejestracja:ponad 22 lata
- Ostatnio:minuta
- Postów:296
Proszę:
procedure TForm1.StringGrid1Click(Sender: TObject);
begin
Form3.Col := (Sender as TStringGrid).Col;
Form3.Row := (Sender as TStringGrid).Row;
Form3.Memo1.Text := (Sender as TStringGrid).Cells[(Sender as TStringGrid).Col, (Sender as TStringGrid).Row];
Form3.Label1.Caption := IntToStr(Length(Form3.Memo1.Text));
Form3.ShowModal;
end;
- Rejestracja:ponad 14 lat
- Ostatnio:około 8 godzin
i tu masz problem ...
myślę że masz poplątane zarządzanie formami
- Rejestracja:ponad 22 lata
- Ostatnio:minuta
- Postów:296
No jak? Akurat ta część aplikacji jest prosta jak konstrukcja cepa. Przy dwukliku na danej komórce, pobierają się: współrzędne komórki i podstawiają do zmiennych na Form3 oraz zawartość komórki, która jest wstawiana do TMemo na Form3. Następnie Form3 się pokazuje modalnie. Użytkownik edytuje TMemo i klika przycisk OK. Wtedy do komórki ze współrzędnych pobranych wcześniej wstawia się zawartość TMemo i Form3 się zamyka. I co jest nie tak?

- Rejestracja:ponad 13 lat
- Ostatnio:około 4 godziny
- Lokalizacja:Tuchów
- Postów:12164
- Rejestracja:ponad 22 lata
- Ostatnio:minuta
- Postów:296
Wygląda, że "winna" jest opcja goRowSelect. Jak jest na false, to wtedy pobiera prawidłowe współrzędne. Jak jest na true, to pobiera współrzędne pierwszej komórki w klikniętym wierszu, np. :klikam w komórkę c = 7, r = 8, a pobierają się c = 0, r = 8.

- Rejestracja:ponad 13 lat
- Ostatnio:około 4 godziny
- Lokalizacja:Tuchów
- Postów:12164
Tu jest bubel:
procedure TForm1.StringGrid1Click(Sender: TObject);
begin
Form3.Col := (Sender as TStringGrid).Col;
Form3.Row := (Sender as TStringGrid).Row;
Zmień zdarzenie OnClick
na OnMouseDown/Up
, a w nim przetłumacz współrzędne z parametrów X
i Y
na współrzędne komórki, za pomocą metody MouseToCell
. Tak przygotowane współrzędne nie będą wskazywały na pierwszą komórkę wiersza, a na tę, którą faktycznie kliknięto.
Przy okazji – w tym jednym zdarzeniu aż pięć razy rzutujesz Sender
na konkretną klasę. Tego typu nadmiarowość wyklucza się za pomocą poniższego zabiegu:
var
Grid: TStringGrid absolute Sender;
Dodatkowa zmienna nie zostaje zadeklarowana (to alias parametru – istnieje pod tym samym adresem co Sender
) i daje bezpośredni dostęp do zawartości grida, bez konieczności jakiegokolwiek rzutowania:
procedure TForm1.StringGrid1Click(Sender: TObject);
var
Grid: TStringGrid absolute Sender;
begin
Form3.Col := Grid.Col;
Form3.Row := Grid.Row;
Form3.Memo1.Text := Grid.Cells[Grid.Col, Grid.Row];
Jest to w pełni bezpieczne, pod warunkiem, że Sender
faktycznie zawiera wskazanie na obiekt klasy TStringGrid
.
- Rejestracja:prawie 20 lat
- Ostatnio:minuta
- Lokalizacja:Gorlice
To sobie pobierz właściwe komórki metodą MouseToCell
var
pt: TPoint;
row, col: Integer;
begin
GetCursorPos(pt);
pt:= StringGrid1.ScreenToClient(pt);
StringGrid1.MouseToCell(pt.X, pt.Y, col, row);
//reszta kodu
end;