Kolorowanie wybranych komórek StringGrida.

0

Witam. Siedze i kombinuje, ale nie moge sobie poradzić z jedną rzeczą. Mam na formatce standardowego StringGrida
nazwanego SG1 i taki kod jak poniżej (fragmenty). I problem polega na tym, że gdy klikne dwukrotnie w komórke SG1
to zmienia ona kolor wypełnienia oraz czcionki na żądany. Wierszy do klikania jest 13. I załóżmy, że klikne na pierwszy
oraz drugi. Jednak kiedy przyciskiem ustawię AktualnyGraczNr := 2; i kliknę w kolumnie o indeksie 2. To w poprzedniej
z kolumn kolorowe zaznaczenie zostanie tylko przy pierwszym klikniętym elemencie. Kolor z ostatniej pokolorowanej
komórki znika. To samo stanie się na przykład z pierwszą komórką jeżeli najpierw kliknę dwukrotnie na nią, a później
na przykłąd na drugą komórkę - po czym znowu na pierwszą komórkę i zmienie przyciskiem AktualnyGraczNr := 2; to
kolorowanie z pierwszej komórki zniknie. Jak temu zaradzić aby pozostawały wszystkie zawarte w zbiorze komórki
pokolorowane poprawnie? Co ciekawe jeżeli klikne na niewłaściwą kolumnę (inna niż w zmiennej AktualnyGraczNr)
i pokaże mi się komunikat z ShowMessage, to po jego zamknięciu i zmianie AktualnyGraczNr - oznaczenia zostają w
sposób prawidłowy. Kombinowałem już ze zmianą Focusa na jakiś inny element formatki, ale to nie pomogło. Może
ktoś z Was wie jak zrobić aby StringGrid zachowywał się poprawnie. Ewentualnie jakiś inny pomysł na zmiane dla
dwukrotnie klikniętej komórki koloru na stałe. Dodam, że próbowałem chyba różnych opcji StringGrida, a także je w
całości wyłączałem. Teraz mam tylko takie [goFixedVertLine, goFixedHorzLine, goVertLine, goHorzLine]. Może coś
trzeba jeszcze poprawić czy przestawić, ale nie wiem. Dodam, że wolę raczej używać standardowy StringGrid..

// ... ciach...
const
  Min_Graczy = 1;
  Max_Graczy = 2;
// ... ciach ...
  public
    KoloroweTab : array[1..Max_Graczy] of set of Byte;
    AktualnyGraczNr, AktualnaKolumna, AktualnyWiersz : Byte;
//... ciach ...
procedure TMainForm.SG1DrawCell(Sender: TObject; ACol, ARow: Integer;
  Rect: TRect; State: TGridDrawState);
var
  I : Byte;
  S : string;
  DrawRect : TRect;
begin
  S := SG1.Cells[ACol, ARow];
  DrawRect := Rect;
  DrawRect.Left := DrawRect.Left + 2;
  DrawRect.Top := Drawrect.Top + 4;
  Drawrect.Right := Rect.Right;
  SG1.Canvas.FillRect(DrawRect);
  DrawText(SG1.Canvas.Handle, Pchar(S), Length(S), DrawRect, dt_Center);

  if (ACol = AktualnyGraczNr) and (ARow in KoloroweTab[AktualnyGraczNr]) then
    begin
    SG1.Canvas.Brush.Color := RGB(255, 165, 0);
    SG1.Canvas.Font.Color := clWhite;
    SG1.Canvas.FillRect(Rect);
    DrawText(SG1.Canvas.Handle, Pchar(S), Length(S), DrawRect, dt_Center);
    end;
end;
// ... ciach ...
procedure TMainForm.SG1DblClick(Sender: TObject);
begin
  if AktualnaKolumna <> AktualnyGraczNr then
    begin
    ShowMessage(Format(
       'Jesteś graczem numer: %d, a próbujesz wpisać punkty za kombinacje dla gracza numer: %d',
          [AktualnyGraczNr, AktualnaKolumna]));
    Exit;
    end;
  PlayerClicks[AktualnyGraczNr][AktualnyWiersz] := True;
  KoloroweTab[AktualnyGraczNr] := KoloroweTab[AktualnyGraczNr] + [AktualnyWiersz];
end;
0

Nie da się zmienić koloru komórki "na stałe". A tak w ogóle to najlepiej jakbyś napisał krótko i zwięźle co chcesz osiągnąć a nie taki tasiemcowy-wstęp. No więc, w OnDrawCell musisz albo dynamicznie kolor wyliczać, albo trzymać sobie te kolor gdzieś na boku. Z istotnych ustawień jest jeszcze DefaultDrawing. Nie analizowałem kodu. Aha przy malowankach dobrze jest się upewnić że Brush.Style jest na bsSolid, ale jak tego nigdzie nie zmieniasz to powinno być OK. Ewentualnie jeśli to jest coś związanego z przenoszeniem zaznaczenia, wykorzystać zdarzenie OnSelectCell, i wywołać jakiegoś Invalidate.

b

0
b0bik napisał(a)

Nie da się zmienić koloru komórki "na stałe".

Co się nie da? :)
Kilka miesięcy temu pisałem komponent oparty na DrawGridzie(a więc jeszcze niżej niż stringGrid). Komponent to po prostu kalendarz, na którym można zaznaczać różne dni na różne kolory.

I generalnie musisz zrobić coś, żeby pamiętać jaka komórka jest na jaki kolor. Najprościej to będzie zrobić za pomocą dwuwymiarowej tablicy:

tab[x, y]:=kolor, gdzie x i y to współrzędne komórki.

Ja potrzebowałem czegoś więcej, więc stworzyłem sobie obiekty, które nazwałem TDayItem. I teraz kalendarz może mieć jakieś dayItemy, ale nie musi. Oczywiście jeden dayItem odpowiada jednemu dniu w kalendarzu i przechowuje kolor komórki, jakiś dodatkowy tekst, datę(dzięki której wiem, do której komórki należy) i kilka innych potrzebnych mi rzeczy.

Tak więc podejrzewam, że w Twoim przypadku wystarczy stworzyć tablicę, jak wyżej podałem.

0

@Juhas: czytaj, czytaj, czytaj i ... odpowiadaj. Przecież napisałem czarno na białym, że albo musi sobie dynamicznie to liczyć albo gdzieś trzymać. I Ty właśnie zrobiłeś to drugie.

0

Dziękuję za porady. Teraz wszystko działa jak należy. Aby rozwiązać mój problem trzeba najlepiej stworzyć
dwuwymiarową tablicę i to w niej przechowywać kolory. A jeszcze lepiej stworzyć tablicę Canvasów, bo jak
się użyje same kolory w takiej tablicy jak poniżej to przy odświeżeniu formatki na przykład poprzez chwilowe
zminimalizowanie wszystkie czcionki będą mały kolor biały (a nie czarny), czyli taki, jaki dla ów klikniętych dwukrotnie komórek (z innym tłem) przewidziałem. To najwazniejszy kod, jakby ktoś miał podobny problem

type
  TClickArray = array[1..Kategorie_Ilosc] of boolean;
// ciach ....
  public
    OznaczajKolorami : boolean;
    ColorArray : array[0..Max_Graczy, 0..Kategorie_Ilosc] of TCanvas;
    AktualnyGraczNr, AktualnaKolumna, AktualnyWiersz : Byte;
    PlayerClicks : array[1..Max_Graczy] of TClickArray;
// ciach ...
procedure TMainForm.SG1DrawCell(Sender: TObject; ACol, ARow: Integer;
Rect: TRect; State: TGridDrawState);
var
  S : string;
  DrawRect : TRect;
begin
  S := SG1.Cells[ACol, ARow];
  DrawRect := Rect;
  DrawRect.Left := DrawRect.Left + 2;
  DrawRect.Top := Drawrect.Top + 4;
  Drawrect.Right := Rect.Right;
  SG1.Canvas.Font.Color := clBlack;
  SG1.Canvas.FillRect(DrawRect);
  DrawText(SG1.Canvas.Handle, Pchar(S), Length(S), DrawRect, dt_Center);
  if (OznaczajKolorami = True) then
  begin
    SG1.Canvas.Brush.Color := ColorArray[ACol, ARow].Brush.Color;
    SG1.Canvas.Font.Color :=  ColorArray[ACol, ARow].Font.Color;
    SG1.Canvas.FillRect(Rect);
    DrawText(SG1.Canvas.Handle, Pchar(S), Length(S), DrawRect, dt_Center);
  end;
end;

procedure TMainForm.SG1SelectCell(Sender: TObject; ACol, ARow: Integer;
var CanSelect: Boolean);
var
  I : Byte;
begin
  AktualnaKolumna := ACol;
  AktualnyWiersz := ARow;

  if AktualnaKolumna = AktualnyGraczNr then
  begin
    for I := 1 to Kategorie_Ilosc do
    begin
      if PlayerClicks[AktualnyGraczNr][I] = False then
        SG1.Cells[AktualnyGraczNr, I] := '';
    end;
    if PlayerClicks[AktualnyGraczNr][AktualnyWiersz] = False then
    begin
      SG1.Cells[AktualnyGraczNr, ARow] := IntToStr(Random(58) + 1);
    end;
  end;
end;

procedure TMainForm.SG1DblClick(Sender: TObject);
begin
  if AktualnaKolumna <> AktualnyGraczNr then
  begin
    ShowMessage(Format(
    'Jesteś graczem numer: %d, a próbujesz wpisać punkty za kombinacje dla gracza numer: %d',
    [AktualnyGraczNr, AktualnaKolumna]));
    Exit;
  end;
  PlayerClicks[AktualnyGraczNr][AktualnyWiersz] := True;
  OznaczajKolorami := True;
  ColorArray[AktualnyGraczNr, AktualnyWiersz].Font.Color := clWhite;
  ColorArray[AktualnyGraczNr, AktualnyWiersz].Brush.Color := clBlue;
end;

procedure TMainForm.TworzTabliceKolorow;
var
  I, J : Byte;
begin
  for I := 0 to High(ColorArray) do
    for J := 0 to SG1.RowCount - 1 do
    begin
      ColorArray[I][J] := TCanvas.Create;
    end;

    for I := 0 to SG1.RowCount - 1 do
    begin
      ColorArray[0][I].Brush.Color := clBtnFace;
      ColorArray[0][I].Font.Color := SG1.Font.Color;
    end;

    for I := 0 to SG1.ColCount - 1 do
    begin
      ColorArray[I][0].Brush.Color := clBtnFace;
      ColorArray[I][0].Font.Color := SG1.Font.Color;
    end;

    for I := 1 to High(ColorArray) do
      for J := 1 to SG1.RowCount - 1 do
      begin
        ColorArray[I][J].Brush.Color := SG1.Color;
        ColorArray[I][J].Font.Color := SG1.Font.Color;
      end;
    end;
// ciach ...

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