CYFROWY BARON • PROGRAMOWANIE • Zobacz wątek - Stałe tło w ListBox

Stałe tło w ListBox

dział ogólny

Stałe tło w ListBox

Nowy postprzez mate006 » piątek, 30 listopada 2012, 20:08

Witam

Potrzebuję zrobić aby do komponentu ListBox wczytało tło z grafiki, i by ta grafika była statyczna tzn nie przemieszczała się, znalazłem w serwisie Cyfrowego Barona przykład Grafika jako tło w ListBox. jednak on powiela grafikę, a ja potrzebuję by była cały czas taka sama, najlepiej skopiowała tło pod sobą i załadowała do ListBox.

Próbowałem już różnych sposobów z tym przykładem jednak bez jakiegokolwiek efektu.

Bardzo bym prosił o jakąś poradę
Avatar użytkownika
mate006
Intelektryk
Intelektryk
 
Posty: 145
Dołączył(a): wtorek, 2 marca 2010, 14:12
Podziękował : 7
Otrzymał podziękowań: 0
System operacyjny: Windows 7 Premium 64
Kompilator: Embarcadero® C++Builder® XE
Gadu Gadu: 0
    Windows 7Firefox

Re: Stałe tło w ListBox

Nowy postprzez Cyfrowy Baron » sobota, 1 grudnia 2012, 01:14

Jedyna zdarzenie do rysowania jakie oferuje ListBox to OnDrawItem, które służy do wstawiania grafiki do każdej linii tego obiektu, a nie do całego obiektu. Mój kod rysuje grafikę linia po linii i powtarza ją we wszystkich liniach. Z braku zdarzenia, które dawałoby dostęp do rysowania po całym obiekcie, nie da się zrobić tego co chcesz.
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: Stałe tło w ListBox

Nowy postprzez Mironas » środa, 5 grudnia 2012, 11:12

Teoretycznie można by to zrobić uwzględniając przy rysowaniu item-u wartość ListBox1->TopIndex. Jednak tu jest problem, ponieważ po każdym scroll-u należy przerysować wszystkie item-y. Nie można tego zrobić bezpośrednio w ListBox1DrawItem bo się zapętli. Można użyć Timera (działający kod poniżej) ale to powoduje nieprzyjemny efekt migotania.

Podaję kod (na podstawie CyfrowegoBarona) - może ktoś wymyśli co zrobić aby nie migotało.
Zwróć uwagę na zmienną segment.
Ustawienia Timer-a:
Timer1->Enabled = false;
Timer1->Interval = 1;

Unit1.h:
KOD cpp:     UKRYJ  
private:
  Graphics::TBitmap *ListBmp;
  Graphics::TBitmap *FillBmp;
  int iLastTopIndex;
  void FillBitmap(Graphics::TBitmap *FillBmp, Graphics::TBitmap *ListBmp, TListBox *ListBox);
 


Unit1.cpp:
KOD cpp:     UKRYJ  
void __fastcall TForm1::FormCreate(TObject *Sender)
{
  ListBmp = new Graphics::TBitmap;
  ListBmp->LoadFromFile(ExtractFilePath(ParamStr(0)) + "fantasy.bmp");
  FillBmp = new Graphics::TBitmap;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::ListBox1DrawItem(TWinControl *Control, int Index, TRect &Rect, TOwnerDrawState State)

{
  String tekst = ListBox1->Items->Strings[Index];
  unsigned short x = (ListBox1->ItemHeight - ListBox1->Canvas->TextHeight(tekst))/2 - 1;

  int segment = Index - ListBox1->TopIndex;

  if(State.Contains(odSelected))
  {
    ListBox1->Canvas->Brush->Color = clYellow;
    ListBox1->Canvas->Font->Color = clBlue;
    ListBox1->Canvas->Brush->Style = bsSolid;
    Frame3D(ListBox1->Canvas, Rect, (TColor)0x00C6E7FF, (TColor)0x000086FF, x/2);
  }
  else
    ListBox1->Canvas->Brush->Style = bsClear;

  FillBitmap(FillBmp, ListBmp, ListBox1);

  TRect ARect;
  ARect.left   = Rect.left;
  ARect.top    = segment * ListBox1->ItemHeight;
  ARect.right  = Rect.right;
  ARect.bottom = (segment * ListBox1->ItemHeight) + ListBox1->ItemHeight;

  ListBox1->Canvas->CopyRect(Rect, FillBmp->Canvas, ARect);
  ListBox1->Canvas->FillRect(Rect);
  ListBox1->Canvas->TextOut(Rect.Left + x, Rect.Top + x, ListBox1->Items->Strings[Index]);

  Timer1->Enabled = false;
  Timer1->Enabled = true;
}
//---------------------------------------------------------------------------
void TForm1::FillBitmap(Graphics::TBitmap *FillBmp, Graphics::TBitmap *ListBmp, TListBox *ListBox)
{
  FillBmp->Width  = ListBox->Width;
  FillBmp->Height = ListBox->Items->Count * ListBox->ItemHeight;
  FillBmp->Canvas->Brush->Bitmap = ListBmp;
  FillBmp->Canvas->FillRect(Rect(0, 0, FillBmp->Width, FillBmp->Height));
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Timer1Timer(TObject *Sender)
{
  Timer1->Enabled = false;
  if ( iLastTopIndex != ListBox1->TopIndex )
  {
    ListBox1->Repaint();
    iLastTopIndex = ListBox1->TopIndex;
  }
}
//---------------------------------------------------------------------------
 
Avatar użytkownika
Mironas
Programista I
Programista I
 
Posty: 427
Dołączył(a): poniedziałek, 2 stycznia 2012, 19:02
Podziękował : 17
Otrzymał podziękowań: 61
System operacyjny: Windows 10
Kompilator: C++Builder 10.3 Rio
TMS Components Pack
Gadu Gadu: 0
    Windows XPChrome

Re: Stałe tło w ListBox

Nowy postprzez Cyfrowy Baron » środa, 5 grudnia 2012, 17:38

To co zaproponowałeś można zrobić bez Timer'a, ale nie wyeliminuje to skoków tła:

KOD cpp:     UKRYJ  
Graphics::TBitmap *ListBmp; /* w pliku nagłówkowym sekcja private */

__fastcall TForm1::TForm1(TComponent* Owner)
        : TForm(Owner)
{
 ListBmp = new Graphics::TBitmap;
 ListBmp->LoadFromFile(ExtractFilePath(ParamStr(0)) + "grafika.bmp");
}
//---------------------------------------------------------------------------
void __fastcall TForm1::ListBox1DrawItem(TWinControl *Control, int Index, TRect &Rect,
          TOwnerDrawState State)
{
 String tekst = ListBox1->Items->Strings[Index];
 unsigned short x = (ListBox1->ItemHeight - ListBox1->Canvas->TextHeight(tekst))/2 - 1;

 if(State.Contains(odSelected))
 {
  ListBox1->Canvas->Brush->Color = clYellow;
  ListBox1->Canvas->Font->Color = clHighlightText;
  ListBox1->Canvas->Brush->Style = bsSolid;
 }
 else
  ListBox1->Canvas->Brush->Style = bsClear;

  int tIndex = ListBox1->TopIndex;

 TRect ARect;
 ARect.left   = Rect.left;
 ARect.top    = (Index - tIndex) * ListBox1->ItemHeight;
 ARect.right  = Rect.right;
 ARect.bottom = ( (Index - tIndex) * ListBox1->ItemHeight) + ListBox1->ItemHeight;



 ListBox1->Canvas->CopyRect(Rect, ListBmp->Canvas, ARect);
 ListBox1->Canvas->FillRect(Rect);
 ListBox1->Canvas->TextOut(Rect.Left, Rect.Top, ListBox1->Items->Strings[Index]);
}
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 3 gości