- Gdy kikniemy lewym przyciskiem raz myszką na komórkę to zaznaczenie zostaje, a gdy kikniemy dwa razy do zaznaczenie ginie innymi słowy
Tzn. chodzi o to, że jak raz klikniemy LPM, to komórka staje się zablokowana (czyli nie można jej podświetlić, tak jak w moim przykładzie są komórki czerwone i żółte), a drugi raz ją odblokowuje? Opisz mi nieco dokładniej, np. krok po kroku, dlatego że późno już i myślenie mam nieco spowolnione;
Notabene Gratuluję znajomości Delphi ja bym nigdy nie wpadł na taki sposób oprogramowania.
Mój przykładowy kod wygląda tak a nie inaczej, dlatego że mało miałem czasu; To nie jest dobra praktyka, dlatego że komponent do własnych działań korzysta z zewnętrznych danych, które zadeklarowane są gdzie indziej, niż w klasie samego komponentu; W ten sposób oczywiście można rozbudowywać komponenty, ale tylko w przypadku, gdy w programie mamy jedną instancję; Przy wielu egzemplarzach trzeba by wiele razy deklarować to samo, a to już mija się z celem;
Dlatego napisałem Ci, że lepszym wyjsciem było by stworzenie nowej klasy komponentu, dziedziczącej po TStringGrid
; W takiej klasie można zadeklarować "wewnętrznie" nowe dane, oraz upublicznić je za pomocą właściwości, dodać nowe metody itd.; Dzięki temu aby skorzystać z nowych możliwości, wystarczy położyć komponent na formularzu i tyle; A dodatkowo, takich komponentów będzie można użyć w programie wiele, dlatego że dodatkowe możliwości zaimplementowane są wewnątrz komponentu, więc nie trzeba będzie ich pakować np. do klasy formularza;
No dobra, postaram się strzelić;
Zmodyfikowałem kod tak, że po dwukrotnym kliknięciu na komórkę, zostaje ona zablokowana i przemalowana na odpowiedni kolor, a po ponownym dwukrotnym kliknięciu zostaje odblokowana, a jej kolor i styl powraca;
Zmieniłem deklarację rekordu, przechowującego informacje o pojedynczej komórce, obecnie wygląda tak:
type
{ single cell information record }
TStringGridCellInfo = record
{ for standard cells }
Standard: record
FontColor: TColor;
BackColor: TColor;
end;
{ for highlighted cells }
Highlighted: record
FontColor: TColor;
BackColor: TColor;
end;
{ for blocked cells }
Blocked: record
FontColor: TColor;
BackColor: TColor;
end;
{ "can highlight" state }
CanHighlight: Boolean;
end;
Zmodyfikowałem także kod zdarzenia OnDrawCell
, aby dostosować rysowanie wszystkich czterech typów komórek; Poniżej nowy jego kod:
procedure TMainForm.sgPreviewDrawCell(Sender: TObject; ACol, ARow: Integer; Rect: TRect; State: TGridDrawState);
var
Grid: TStringGrid;
intX, intY: Integer;
strCell: AnsiString;
begin
Grid := Sender as TStringGrid;
with Grid.Canvas do
begin
{ fixed cell }
if (ACol < Grid.FixedCols) or (ARow < Grid.FixedRows) then
begin
{ font and background colors }
Font.Color := clGray;
Brush.Color := $00D8E9EC;
{ font style }
Font.Style := [];
end
else
{ can highlight the cell }
if CellsInfoArr[ACol, ARow].CanHighlight then
begin
{ highlighted cell }
if gdSelected in State then
begin
{ font and background colors }
Font.Color := CellsInfoArr[ACol, ARow].Highlighted.FontColor;
Brush.Color := CellsInfoArr[ACol, ARow].Highlighted.BackColor;
{ font style }
Font.Style := [fsBold];
end
else
{ standard cell }
begin
{ font and background colors }
Font.Color := CellsInfoArr[ACol, ARow].Standard.FontColor;
Brush.Color := CellsInfoArr[ACol, ARow].Standard.BackColor;
{ font style }
Font.Style := [];
end;
end
else
{ blocked cell }
begin
{ font and background color }
Font.Color := CellsInfoArr[ACol, ARow].Blocked.FontColor;
Brush.Color := CellsInfoArr[ACol, ARow].Blocked.BackColor;
{ font style }
Font.Style := [fsBold];
end;
{ cell background }
FillRect(Rect);
{ cell content }
strCell := Grid.Cells[ACol, ARow];
intX := Rect.Left + ((Rect.Right - Rect.Left) - TextWidth(strCell)) div 2;
intY := Rect.Top + ((Rect.Bottom - Rect.Top) - TextHeight(strCell)) div 2;
TextOut(intX, intY, strCell);
end;
end;
No i samo zdarzenie podwójnego kliknięcia; W nim pobierana jest pozycja kursora na ekranie (bądź pulpicie), następnie koordynaty przeliczane są na współrzędne względem komponentu; Następnie odpowiednią metodą tłumaczone są współrzędne kursora myszy na koordynaty komórki, nad którą znajduje się kursor; Następnie sprawdzane jest, czy komórka, nad którą jest kursor jest "fixed" czy nie; Jeśli nie, to pole CanHighlight
jest negowane, a cały komponent przemalowywany (niestety nie mam innego pomysłu na to, jak przemalować tylko jedną komórkę - testuję pod Delphi7);
Kod zdarzenia jest krótki i prosty w zrozumieniu:
procedure TMainForm.sgPreviewDblClick(Sender: TObject);
var
Grid: TStringGrid;
ptHover: TPoint;
gcHover: TGridCoord;
begin
Grid := Sender as TStringGrid;
{ get the cursor coordinates }
GetCursorPos(ptHover);
ptHover := ScreenToClient(ptHover);
{ get the cell coordinates }
gcHover := Grid.MouseCoord(ptHover.X, ptHover.Y);
{ check the cell type (standard or fixed }
if (gcHover.X >= Grid.FixedRows) and (gcHover.Y >= Grid.FixedCols) then
begin
{ update the cell info }
with CellsInfoArr[gcHover.X, gcHover.Y] do
CanHighlight := not CanHighlight;
{ repaint grid }
Grid.Repaint();
end;
end;
Dzięki temu, możliwe jest blokowanie dwukrotnie klikniętych komórek oraz ich odblokowywanie po ponownym dwukliku; Oczywiście kolory zostawiłem takie, jakie przedstawiłem w poprzednim przykładzie, jednak nic nie stoi na przeszkodzie, aby w tej metodzie oprócz zmiany stanu CanHighlight
, zmienić także kolor i styl zablokowanej komórki - należy to zrobić także w zdarzeniu OnDblClick
;
Efekt nowego kodu poniżej, dla losowo poblokowanych komórek:
Komórki koloru białego to komórki odblokowane i nie zaznaczone, niebieskie są także odblokowane, ale zaznaczone, a czerwone to komórki zablokowane; Czyli zaznaczone są komórki od [4,4] do [9,7];
Myślę, że teraz naświetliłem bardziej sposób dynamicznego kolorowania komórek; W razie pytań - pisz; A program oraz poprawione jego źródła w załączniku.