Przezroczystość w StringGrid

0

Cześć,
od paru dni walczę z dostosowanie StringGrida do swoich oczekiwań :) Idzie mi to strasznie ciężko ale zrobiłem małe postępy.

Chciałbym aby po kliknięciu w wybraną komórkę cały wiersz został zaznaczony przezroczystym kolorem. Udało mi się to osiągnąć poprzez wczytanie obrazka z przezroczystością i wypełnieniem nim komórki.

Najbardziej zależy mi na tle StringGrida. Udało mi się wczytać do tła obrazek:

procedure TForm1.StringGrid1DrawCell(Sender: TObject; aCol, aRow: Integer;
  aRect: TRect; aState: TGridDrawState);
begin

  StringGrid1.Canvas.Draw(0,0, Image1.Picture.Graphic);

end;

I jest ok ale nie do końca wygląda to tak jak chciałem.
Chciałbym aby ten wybrany obrazek wypełnił całą powierzchnię StringGrida a nie tylko miejsce gdzie są komórki.
Oprócz tego pojawił się u mnie pomysł aby całkowicie zlikwidować tło StringGrida.

Czy jest możliwe aby StringGrid nie miał żadnego tła (pomijając celowo pokolorowane komórki) i widoczne przez niego były elementy/kolory/tła komponentów, formy leżącej pod nim? Jak można osiągnąć taki efekt? Jest w ogóle to możliwe?

Dodatkowo pojawił się problem z opóźnieniem przy 'kolorowaniu' całego wiersza obrazem z przezroczystością. Kliknięta komórka koloruje się od razu jednak reszta dopiero po chwili.

Kolorowanie w ten sposób całego wiersza rozwiązałem poprzez zapisanie w zmiennej numeru klikniętego wiersza a potem w procedurze DrawCell sprawdzeniu czy aktualnie rysowana komórka leży w zaznaczonym wierszu.

procedure TForm1.StringGrid1Click(Sender: TObject);
begin
     PRow:=StringGrid1.Row;
end;


procedure TForm1.StringGrid1DrawCell(Sender: TObject; aCol, aRow: Integer;
  aRect: TRect; aState: TGridDrawState);
begin

  stringgrid1.Canvas.Draw(0,0, Image1.Picture.Graphic);

      if (aCol = 0) or (aRow = 0) then
    begin
      stringgrid1.Canvas.Pen.Color := $00DCE8ED;
      stringgrid1.Canvas.Brush.Color := $00DCE8ED;
      stringgrid1.Canvas.Font.Style := [fsBold];
      stringgrid1.Canvas.Rectangle(aRect);
    end;

    if ((gdSelected in aState) or (PRow=aRow))  then
      begin
        stringgrid1.canvas.StretchDraw(aRect, img.Picture.Graphic);
      end;

end;

Może trochę chaotycznie ale proszę o pomoc:)

1

Jak chcesz, aby wszystkie komórki w poziomie były zaznaczane po kliknięciu to ustaw wartość goRowSelect na True we właściwości Options; Dzięki temu, po kliknięciu w daną komórkę, wszystkie w danym wierszu zostaną przemalowane, co możesz oprogramować w zdarzeniu OnDrawCell;

Natomiast żadne zdarzenie nie umożliwia oprogramowania malowania pustej przestrzeni kontrolki.

0

Dzięki!

Czyli nie da się po prostu tego oprogramować?
Dalej powalcze jednak troche z przezroczystością tła całego komponentu. Niby jest opcja ParentColor ale wtedy StringGrid przybiera tylko jednolity kolor, jeżeli wrzuce na Canvas formy jakiś obraz to oczywiście StringGrid tego nie widzi.

1

Czyli nie da się po prostu tego oprogramować?

Da się, ale nie będzie to takie proste; Trzeba będzie ręcznie obsłużyć odpowiednie komunikaty i metody odpowiedzialne za wypełnianie tła komponentu; Oczywiście w taki sposób, aby nie zepsuć pozostałych mechanizmów; Z reguły jest to trudne zadanie i aby uzyskać zawsze działający prawidłowo kod, trzeba mieć dużą wiedzę i postępować z głową;

Niby jest opcja ParentColor ale wtedy StringGrid przybiera tylko jednolity kolor [...]

Efekt prawie taki, jaki Cię interesuje; Ustaw sobie ParentColor na True (dzięki temu kolor tła będzie z automatu taki sam jak rodzica), a następnie oprogramuj zdarzenie OnDrawCell, w którym zdefiniuj malowanie komórek;

Dzięki temu podczas działania programu, wszystkie komórki będą malowane dokładnie tak jak tego chcesz; A wyglądem komponentu w designerze się nie przejmuj - w tym czasie kod własnego zdarzenia nie działa, więc nie ma wtedy podglądu;

Przykładowy kod testowy (komponent nie posiada komórek tytułowych):

procedure TForm1.StringGrid1DrawCell(Sender: TObject; ACol, ARow: Integer; ARect: TRect; AState: TGridDrawState);
var
  LGrid: TStringGrid absolute Sender;
begin
  LGrid.Canvas.Brush.Color := clWhite;
  LGrid.Canvas.FillRect(ARect);
end;

Efekt podczas działania programu:

grid.png

Aby poprawnie rozróżnić tym komórki i jej styl, musisz skorzystać z dostarczonych w zdarzeniu argumentów; Typ komórki (tytułowa lub zwykła) określa się na podstawie współrzędnych malowanej komórki, czyli argumentów ACol i ARow; Aby sprawdzić, czy komórka jest tytułową, wartości tych parametrów należy porównać z wartościami właściwości FixedCols i FixedRows;

var
  LFixed: Boolean;
begin
  LFixed := (ACol < LGrid.FixedCols) or (ARow < LGrid.FixedRows);

Do sprawdzenia stanu podświetlenia komórki, należy sprawdzić, czy w argumencie AState znajduje się enum gdSelected; Analogicznie z fokusem - jeśli malowana komórka trzyma fokusa to parametr AState zawiera wartość gdFocused; Sprawdzenie istnienia wartości wyliczeniowej w zbiorze dokonuje się za pomocą operatora In:

var
  LSelected: Boolean;
  LFocused: Boolean;
begin
  LSelected := gdSelected in AState;
  LFocused := gdFocused in AState;
0

Dzieki Panowie za pomoc,
poniosła mnie trochę fantazja i chciałem osiągnąć efekt jak na załączonym screenie ale widzę, że za krótki na razie jestem na takie bajery więc pokombinuje inaczej:)

Chciałem pokombinować z parent color wrzucając w tło formy jakiś obrazek (docelowo jakiś wzorek etc) tylko, że to i tak nie traktowane będzie przez formę jako 'color' a co za tym idzie StringGrid nie wyświetli tego jako ParentColor.

1

poniosła mnie trochę fantazja i chciałem osiągnąć efekt jak na załączonym screenie ale widzę, że za krótki na razie jestem na takie bajery więc pokombinuje inaczej:)

Nie zauważyłem, że w pierwszym poście jest załącznik... :]

Nie widzę problemu, aby taki efekt osiągnąć; O ile nie przeszkadza Ci brak kontroli pustego obszaru to te cuda z komórkami jak najbardziej można uzyskać, i to w dość prosty sposób; Trzeba jednak pamiętać, że jeśli komponent będzie posiadał więcej kolumn/wierszy niż na raz pomieści, to trzeba będzie do obliczeń wziąć pod uwagę indeks pierwszej wyświetlonej kolumny/wiersza; Dzięki temu bez względu na widok (przewinięcie), obraz w komórkach będzie sprawiał wrażenie statycznego (stojącego w miejscu);

Czyli rozwiązanie - malować najpierw obliczony fragment obrazu, a następnie malować półprzezroczysty prostokąt (jeśli komórka jest zaznaczona).

0

No właśnie troche mi nie pasuje brak kontroli nad tłem komponentu ale na razie zostawie ten temat. Zajmę się tym trochę później.

Załącznik w pierwszym poście to jest moje dzieło i efekt tego co udało mi się osiągnąć :)
Załącznik w poście nad Twoim ostatnim to efekt jaki chciałbym ostatecznie osiągnąć.

Dzięki za rady, postaram się powalczyć jeszcze z tematem i dam znać jak wyszło.

1

Powalczyłem trochę z tematem i udało mi się osiągnąć efekt, który w miarę mnie zadowala :)

grid.png

Jak widać mam jeszcze 2 problemy.

Pierwszy pewnie jest banalny ale nie wiem jak sobie z nim poradzić.
Chodzi o to żeby zlikwidować czerwoną ramkę przy zaznaczonym wierszu. Albo jestem już zmęczony albo StringGrid serio nie posiada nic takiego jak FocusRect=false?

Drugim problemem są ScrollBary. Specjalnie dodałem na screenie jeden żeby pokazać jak pięknie się wyróżnia.
Jest możliwe zmienienie koloru takiego scrollbara?

Cały czas googluje ale nie moge znaleźć nic konkretnego:)

0

Chodzi o to żeby zlikwidować czerwoną ramkę przy zaznaczonym wierszu. Albo jestem już zmęczony albo StringGrid serio nie posiada nic takiego jak FocusRect=false?

Ustaw DefaultDrawing na False - będziesz mógł w pełni kontrolować malowanie komórek;

Drugim problemem są ScrollBary. Specjalnie dodałem na screenie jeden żeby pokazać jak pięknie się wyróżnia. Jest możliwe zmienienie koloru takiego scrollbara?

I tak, i nie - domyślnie nie ma takiej możliwości, więc trzeba by pokombinować z WinAPI, łapać odpowiednie komunikaty i oprogramować własne malowanie jego elementów; Albo skorzystać z jakiegoś mechanizmu skinowania (w tej paczce nie ma kontrolki StringGrid).

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