CYFROWY BARON • PROGRAMOWANIE • Zobacz wątek - TListView - kolorowanie komórek raz jeszcze

TListView - kolorowanie komórek raz jeszcze

dział ogólny

TListView - kolorowanie komórek raz jeszcze

Nowy postprzez Mioss » poniedziałek, 27 czerwca 2011, 02:35

Witam,
1) Chcę pokolorować wiersz TListView na zielono. Nic prostszego, ustalam Brush->Color na mój kolor w OnCustomDrawItem. A jeżeli opróćz tego, jeden z SubItemów chcę pokolorować na czerwono? Jak to zrobić tak, aby w OnCustomDrawSubItem nie dbać o kolor całego itemu (tego zielonego)? Domyślnie, jak pokoloruję w ten sposób jakiś SubItem, to wszystkie na prawo od niego będą w tym kolorze co on.
2) Jak pokolorować CZĘŚĆ SubItemu? Np. połowę na zielono, połowę na standardowy kolor -> w efekcie chcę uzyskać coś w stylu ProgressBara, ale zwyklym malowaniem na canvasie, po co cały obiekt. Moje próby albo zamalowują cały SubItem, albo dają zamierzony efekt tylko przy podświetleniu wybranego elementu. Przy okazji, jak coś zmienię w którejś z tych funkcji malujących, to po najechaniu na Item, teksty mi się malują jako czarne prostokąty... Ma ktoś coś takiego?
Z góry dzięki za pomoc
Avatar użytkownika
Mioss
Bladawiec
Bladawiec
 
Posty: 2
Dołączył(a): poniedziałek, 27 czerwca 2011, 02:13
Podziękował : 0
Otrzymał podziękowań: 0
System operacyjny: Windows
Kompilator: C++ Builder 2010
Gadu Gadu: 0
    Windows 7Opera

Re: TListView - kolorowanie komórek raz jeszcze

Nowy postprzez Cyfrowy Baron » poniedziałek, 27 czerwca 2011, 09:35

Musisz stworzyć warunek dokładnie określający, które komórki są kolorowane, czyli np: jeżeli to kolumna 2 to ustaw kolor na żółty, a jeżeli nie to na biały

KOD cpp:     UKRYJ  
void __fastcall TForm1::ListView1CustomDrawSubItem(TCustomListView *Sender,
        TListItem *Item, int SubItem, TCustomDrawState State, bool &DefaultDraw)
{
 if(SubItem == 2)
 {
   ListView1->Canvas->Brush->Color = clYellow;
 }
 else
 {
   ListView1->Canvas->Brush->Color = clWhite;
 }
}


Musisz dodać warunek else. By jednak nie określać zawsze warunku, szczególnie, gdy tych kolorowanych kolumn jest wiele, lepiej posłużyć się blokiem switch:

KOD cpp:     UKRYJ  
void __fastcall TForm1::ListView1CustomDrawSubItem(TCustomListView *Sender, TListItem *Item,
                  int SubItem, TCustomDrawState State, bool &DefaultDraw)
{
 switch(SubItem)
 {
  case 2: ListView1->Canvas->Brush->Color = clYellow; break;
  default:  ListView1->Canvas->Brush->Color = clWhite; break;
 }
}


Jeżeli nie chcemy kolorować całej kolumny, a jedynie wybraną komórkę, to należy jeszcze określić numer wiersza w którym ta komórka ma być kolorowana:

KOD cpp:     UKRYJ  
void __fastcall TForm1::ListView1CustomDrawSubItem(TCustomListView *Sender, TListItem *Item,
                  int SubItem, TCustomDrawState State, bool &DefaultDraw)
{
 if(Item->Index == 1)
 {
  switch(SubItem)
  {
   case 2: ListView1->Canvas->Brush->Color = clYellow; break;
   default:  ListView1->Canvas->Brush->Color = clWhite; break;
  }
 }
}


Tutaj również możemy użyć switch:

KOD cpp:     UKRYJ  
void __fastcall TForm1::ListView1CustomDrawSubItem(TCustomListView *Sender, TListItem *Item,
                  int SubItem, TCustomDrawState State, bool &DefaultDraw)
{
 switch(Item->Index)
 {
  case 1:
  {
        switch(SubItem)
        {
         case 2:  ListView1->Canvas->Brush->Color = clYellow; break;
         default: ListView1->Canvas->Brush->Color = clWhite;  break;
        } break;
  }
 }
}


No i na koniec bardziej złożony przykład:

KOD cpp:     UKRYJ  
void __fastcall TForm1::ListView1CustomDrawSubItem(TCustomListView *Sender, TListItem *Item,
                  int SubItem, TCustomDrawState State, bool &DefaultDraw)
{
 switch(Item->Index)
 {
  case 1:
  {
        switch(SubItem)
        {
         case 1:  ListView1->Canvas->Brush->Color = clGreen; break;
         case 2:  ListView1->Canvas->Brush->Color = clYellow; break;

         default: ListView1->Canvas->Brush->Color = clWhite;  break;
        }
  } break; /* WAŻNE!!! } break; */

  case 2:
  {
        switch(SubItem)
        {
         case 1:  ListView1->Canvas->Brush->Color = clRed; break;
         case 2:  ListView1->Canvas->Brush->Color = clMaroon; break;

         default: ListView1->Canvas->Brush->Color = clWhite;  break;
        }
  } break; /* WAŻNE!!! } break; */

 }
}


Co się tyczy drugiego problemu to nie widzę na to sposobu, gdyż zdarzenie OnCustomDrawSubItem nie zwraca żadnego uchwytu do obszaru komórki, więc nie da się tam nic narysować.
Jedyne rozsądne wyjście to zabawa z ikonkami, czyli można w ImageList umieścić ikony reprezentujące paski postępu i zmieniać indeksy ikon dla wybranego SubItem. To oczywiście pociąga za sobą kolejne problemy, gdyż w komórce z takim progressbarem nie może być tekstu, a i tekst w kolumnie głównej zostanie przesunięty względem długości ikony.

Przypuszczam, że chcesz zrobić to co można czasami spotkać w różnych programach, tyle, że tam na ogół nie jest wykorzystywany komponent TListView, lecz SysListView32.

Takie progressbary ma już wbudowane np. komponent TAdvListView z komercyjnej paczki TMS Component Pack.
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    Windows XPFirefox

Re: TListView - kolorowanie komórek raz jeszcze

Nowy postprzez Mioss » poniedziałek, 27 czerwca 2011, 21:23

Uchwyt do obszaru komórki to jeszcze pikuś - wystarcza makro WinAPI ListView_GetSubItemRect.
Gorzej jest z tym, że malowanie FillRect albo czymś podobnym, w którejś z tych funkcji ListView powoduje dosyć niezdefiniowane zachowanie, jak np. właśnie te czarne prostokąty po najechaniu, dlatego pytam jaka jest tego przyczyna / co robię źle.

A czy standardowy Borland dostarcz jakiegoś komponentu bardziej zaawansowanego? Skąd wziąć to SysListView32?
Avatar użytkownika
Mioss
Bladawiec
Bladawiec
 
Posty: 2
Dołączył(a): poniedziałek, 27 czerwca 2011, 02:13
Podziękował : 0
Otrzymał podziękowań: 0
System operacyjny: Windows
Kompilator: C++ Builder 2010
Gadu Gadu: 0
    Windows 7Opera

Re: TListView - kolorowanie komórek raz jeszcze

Nowy postprzez Cyfrowy Baron » wtorek, 28 czerwca 2011, 09:47

Próbowałem już z tym FillRect, ale to nie zadziała. W komórce to Brush musi być wypełniony.

Mioss napisał(a):A czy standardowy Borland dostarcz jakiegoś komponentu bardziej zaawansowanego? Skąd wziąć to SysListView32?


Komponent SysListView32 nie rozwiąże Twojego problemu. Podałem go jako przykład, gdyż większość uważa, że listy widoczne w różnych programach to właśnie klasa TListView, a tymczasem to zupełnie inne biblioteki. SysListView32 to biblioteka Exploratora Windows i jest dostarczana wraz ze środowiskiem C++Builder 2010, ale nie jako komponent lecz biblioteka i to ukryta. Bibliotekę można znaleźć w katalogu: c:\Documents and Settings\All Users\Dokumenty\RAD Studio\7.0\Demos\CPP\Apps\ShellControls\. Ja dodałem go do paczki i zainstalowałem jako komponent.
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    Windows XPFirefox

Re: TListView - kolorowanie komórek raz jeszcze

Nowy postprzez polymorphism » wtorek, 28 czerwca 2011, 10:07

SysListView32 to nie biblioteka, tylko klasa okna (WC_LISTVIEW), czyli zwykły systemowy listview. Z tego co pamiętam, VCL korzystał z systemowej kontrolki, no ale może coś się pozmieniało...
C++ Reference - opis wszystkich klas STL-a i funkcji C.
Avatar użytkownika
polymorphism
Doświadczony Programista ● Moderator
Doświadczony Programista ● Moderator
 
Posty: 2156
Dołączył(a): piątek, 19 grudnia 2008, 13:04
Podziękował : 0
Otrzymał podziękowań: 200
System operacyjny: Windows 8.1
Windows 10
Linux Mint 21.1
Kompilator: Visual Studio
Visual Studio Code
MSYS2 (MinGW, clang)
g++
clang
Gadu Gadu: 0
    Windows XPFirefox

Re: TListView - kolorowanie komórek raz jeszcze

Nowy postprzez Cyfrowy Baron » wtorek, 28 czerwca 2011, 10:11

Masz rację to WC_LISTVIEW.
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    Windows XPFirefox

Re: TListView - kolorowanie komórek raz jeszcze

Nowy postprzez Cyfrowy Baron » piątek, 1 lipca 2011, 12:55

Póki co, jedyne co udało mi się osiągnąć to wstawienie do komórki prawdziwego TProgressBar:

KOD cpp:     UKRYJ  
__fastcall TForm1::TForm1(TComponent* Owner)
        : TForm(Owner)
{
 ProgressBar1->Parent = ListView1;
 ProgressBar1->Visible = false;
}
//---------------------------------------------------------------------------

BOOL bProgress = false;

int x = 1;

void __fastcall TForm1::ListView1CustomDrawSubItem(TCustomListView *Sender, TListItem *Item,
                  int SubItem, TCustomDrawState State, bool &DefaultDraw)
{
 if(Item->Index == 2 && SubItem == x)
 {

  TRect cRect = Item->DisplayRect(drBounds);

  for(int i = 0; i < SubItem; i++)
                          cRect.Left  = cRect.Left + Sender->Column[i]->Width;

  cRect.Right = cRect.Left + Sender->Column[SubItem]->Width;

  ProgressBar1->BoundsRect = cRect;
 }
}
//---------------------------------------------------------------------------
/* TEST */
void __fastcall TForm1::Button3Click(TObject *Sender)
{
 if(bProgress)
 {
  bProgress = false;
  Button3->Caption = "Run ProgressBar";
  Timer1->Enabled = false;
  ProgressBar1->Visible = false;
  ProgressBar1->Position = 0;
 }
 else
 {
  bProgress = true;
  Button3->Caption = "Stop ProgressBar";
  Timer1->Enabled = true;
  ProgressBar1->Visible = true;
  x++;
  if(x > ListView1->Columns->Count - 1) x = 1;
 }
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Timer1Timer(TObject *Sender)
{
 if(ProgressBar1->Position < 100) ProgressBar1->Position += 1;
 else ProgressBar1->Position = 0;
}



Nie masz wystarczających uprawnień, aby zobaczyć pliki załączone do tego postu.
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    Windows XPFirefox


  • Podobne tematy
    Odpowiedzi
    Wyświetlone
    Ostatni post

Powrót do Ogólne problemy z programowaniem

Kto przegląda forum

Użytkownicy przeglądający ten dział: Brak zalogowanych użytkowników i 1 gość

cron