CYFROWY BARON • PROGRAMOWANIE • Zobacz wątek - DropDownStyle dla ComboBox

DropDownStyle dla ComboBox

problemy z tworzeniem aplikacji graficznych oraz audio i wideo

DropDownStyle dla ComboBox

Nowy postprzez Slynx » sobota, 2 kwietnia 2011, 23:47

Piszę poprawiony komponent ComboBox z możliwością dodawania obrazków dla każdego elementu (16x16) i natrafiłem na pewien problem, a raczej pytanie.
Tak wygląda efekt, który chcę osiągnąć:

Obrazek

A tak który mam:
Obrazek

Problem w tym, że nie wiem jak to zrobić, tj. nie wiem co jest w DrawMode.Normal kontrolowanym przez system.
Może ktoś się orientuje co trzeba dodać by w osiągnąć ten efekt ? Jak opcja, właściwość jest ustawiana ? Bo source Code do komponentów NET raczej nie udostępniają, żebym sobie podejrzał ;)
--
Powinienem tam pokazać jakiś obrazek żeby było widać, że działa, ale już mniejsza o to ;p
Avatar użytkownika
Slynx
Mądrosław
Mądrosław
 
Posty: 350
Dołączył(a): piątek, 17 grudnia 2010, 21:59
Podziękował : 11
Otrzymał podziękowań: 0
System operacyjny: Windows 7 32
Kompilator: Visual C++ 2005; Visual C++ 2008; Visual C++ 2010; Visual C# 2010;
Gadu Gadu: 0
    Windows 7Chrome

Re: DropDownStyle dla ComboBox

Nowy postprzez Corvis » niedziela, 3 kwietnia 2011, 00:45

Nic nie kumam !!

W Builderze, żeby tak zrobić wystarczy zrobić Style -> csDropDownList
"Sukcesy trwają, dopóki ich ktoś nie spieprzy. Porażki są wieczne"

Dr Gregory House
Avatar użytkownika
Corvis
Programista I
Programista I
 
Posty: 880
Dołączył(a): sobota, 26 lipca 2008, 00:31
Podziękował : 80
Otrzymał podziękowań: 30
System operacyjny: WINDOWS 7 64-bity
Kompilator: Praca - C++ Builder XE2 ENTERPRISE - Update 4, Dom - C++ Builder XE4 - Uddate 1
Gadu Gadu: 0
    Windows VistaChrome

Re: DropDownStyle dla ComboBox

Nowy postprzez Cyfrowy Baron » niedziela, 3 kwietnia 2011, 10:12

Ja również nie rozumiem. :roll: Czy chodzi o sam wygląd komponentu? :oops:

Slynx napisał(a):Piszę poprawiony komponent ComboBox z możliwością dodawania obrazków dla każdego elementu (16x16)


Może chodzi o możliwość wstawiania grafiki do komponentu typu TComboBox?! Jeżeli tak to należy posłużyć się zdarzeniem OnDrawItem oraz ustawić właściwość Style komponentu na csOwnerDrawFixed.

Z wykorzystaniem komponentu TImageList do przechowywania ikon ładowanych do ComboBox1. By ikony wyglądały na liście ładnie i bez tła należy w ImageList1 ustawić właściwość ColorDepth na cd32Bit. Jeżeli komponent nie posiada takiej właściwości to trzeba pokombinować, ale o tym nie będzie teraz.

KOD cpp:     UKRYJ  
__fastcall TForm1::TForm1(TComponent* Owner)
        : TForm(Owner)
{
  ComboBox1->ItemHeight = ImageList1->Height + 2; /* dopasowanie wysokości elementów listy do wysokości ikon */
}
void __fastcall TForm1::ComboBox1DrawItem(TWinControl *Control, int Index,
        TRect &Rect, TOwnerDrawState State)
{
 TCanvas *tCanvas = ComboBox1->Canvas;
 String cText = ComboBox1->Items->Strings[Index];

 /* zmienna x pomaga w wyśrodkowaniu tekstu w pionie względem ikony */
 int x = ( ComboBox1->ItemHeight - tCanvas->TextHeight(cText) ) / 2 - 1;

 /* zmienna Index określa numer elementu listy, tutaj dodatkowo określa
    numer ikony pobieranej z ImageList1 */

 ImageList1->Draw(tCanvas, Rect.Left + 1, Rect.Top + 1, Index, true);

 tCanvas->TextOut( Rect.Left + ImageList1->Width + 2, Rect.Top + x, cText );
}


uzyskamy taki efekt:

combo1.png


Ja użyłem w ImageList1 grafiki o wymiarach 20x20, a nie 16x16 bo akurat takie miałem pod ręką.

Lepszy efekt uzyskasz jednak nieco rozbudowując ten kod:

KOD cpp:     UKRYJ  
void __fastcall TForm1::ComboBox1DrawItem(TWinControl *Control, int Index,
        TRect &Rect, TOwnerDrawState State)
{
 TCanvas *tCanvas = ComboBox1->Canvas;
 String cText = ComboBox1->Items->Strings[Index];

 int x = ( ComboBox1->ItemHeight - tCanvas->TextHeight(cText) ) / 2 - 1;

 if(State.Contains(odSelected))
 {
  tCanvas->Brush->Color = clYellow;
  tCanvas->Font->Color = clRed;
 }
 else
 {
  tCanvas->Brush->Color = ComboBox1->Color;
  tCanvas->Font->Color = ComboBox1->Font->Color;
 }

 tCanvas->FillRect(Rect);

 ImageList1->Draw(tCanvas, Rect.Left + 1, Rect.Top + 1, Index, true);

 TRect cRect = Rect;
 cRect.Left  = Rect.Left  + ImageList1->Width + 2;
 cRect.Right = Rect.Right - 1;
 cRect.Top   = Rect.Top + x;

 DrawText( tCanvas->Handle, cText.c_str(), -1, &cRect,
           DT_LEFT | DT_VCENTER | DT_END_ELLIPSIS | DT_NOCLIP );

 if(State.Contains(odFocused))
 {
  tCanvas->DrawFocusRect(Rect);
 }
}


Otrzymasz taki efekt:

combo2.png


To wszystko kod dla środowiska C++Builder. Mnie nie pytaj jak go dostosować do potrzeb VC++, gdyż nie wiem.
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

Re: DropDownStyle dla ComboBox

Nowy postprzez Slynx » niedziela, 3 kwietnia 2011, 15:41

Wydawało mi się, że dość wyraźnie się wyraziłem. Piszę, że... piszę własną wersję komponentu, tak by można było dodać obrazki dla każdego elementu, bo standardowo NIE można. Więc jeśli piszę samemu to oczywiście, że DrawMode = csOwnerDrawFixed.
Wyrażnie powiedziałem, że gdy komponent rysowany jest przez System (DrawMode = Normal) to uzyskuje efekt jak na pierwszym obrazku. Natomiast gdy chcę ręcznie pokierować rysowaniem (czyli obsłużyć OnDraw) ustawiając DrawMOde = csOwnerDrawFixed (choć w .NET jest to chyba OwnerDrawFixed) uzyskuje efekt jak na drugim obrazku. A pytanie brzmiało - Czego mi brakuje w obsłudze rysowania by uzyskać efekt jak na pierwszym obrazku.

Czegoś po prostu nie ustawiłem, czegoś co jest ustawione przy DrawMode = Normal. Nie wiem, jak jaśniej to przedstawić.

To co napisałeś Cyfrowy Baronie jest właśnie tym co już mam. Teraz chodzi mi o to, by dodać taki wygląd jak na pierwszym (wstawionym przeze mnie) obrazku.
Chyba widać różnicę ? (Poszarzałe tło pierwszego elementu - i to nie jest jednolity kolor)
Avatar użytkownika
Slynx
Mądrosław
Mądrosław
 
Posty: 350
Dołączył(a): piątek, 17 grudnia 2010, 21:59
Podziękował : 11
Otrzymał podziękowań: 0
System operacyjny: Windows 7 32
Kompilator: Visual C++ 2005; Visual C++ 2008; Visual C++ 2010; Visual C# 2010;
Gadu Gadu: 0
    Windows 7Chrome

Re: DropDownStyle dla ComboBox

Nowy postprzez Cyfrowy Baron » niedziela, 3 kwietnia 2011, 20:12

Slynx napisał(a):Wyrażnie powiedziałem, że gdy komponent rysowany jest przez System (DrawMode = Normal) to uzyskuje efekt jak na pierwszym obrazku. Natomiast gdy chcę ręcznie pokierować rysowaniem (czyli obsłużyć OnDraw) ustawiając DrawMOde = csOwnerDrawFixed


W C++Builder nie ma właściwość DrawMode, a csOwnerDrawFixed znajduje się we właściwości Style. Zmiana właściwości Style nie zmienia wyglądu tegoż obiektu. Spróbuj z wartością csOwnerDrawVariable, która również pozwala rysować w tym komponencie.
To tyle jeżeli chodzi o podobieństwa w C++Builder i VC++. Tutaj może pomóc tylko osoba używająca środowiska VC++.

Slynx napisał(a):A pytanie brzmiało - Czego mi brakuje w obsłudze rysowania by uzyskać efekt jak na pierwszym obrazku.

Niczego nie brakuje, wygląda raczej na to, że u Ciebie ustawienie stylu csOwnerDrawFixed wyłącza style Windows XP/Vista\7. Nie pamiętam już jak to było we wcześniejszych wersjach środowiska C++Builder, ale tam przy zmianie stylu na ręczne rysowanie też się chyba wyłączał styl Windows XP. Sytuacja zmieniła się dopiero w nowszych wersjach środowiska, gdy zmieniły się również biblioteki, wcześniej nie dało się nic z tym zrobić, oczywiście poza napisaniem komponentu od podstaw. Jeżeli masz taką możliwość, to sprawdź, czy w VC++ 2010 też występuje ten problem.
Slynx napisał(a):Chyba widać różnicę ? (Poszarzałe tło pierwszego elementu - i to nie jest jednolity kolor)


To gradient i takie efekt dla wybranego elementu dałoby się uzyskać ryzując zamiast pojedynczego koloru - gradient. Problemem pozostaje jednak sam przycisk rozwijania listy, gdyż akurat na nim rysować się nie da. Trudno jednak mi coś doradzić, gdyż w C++Builder ten komponent korzysta z API i tam jest zdefiniowany, natomiast w przypadku platformy .NET korzysta z .NET Framework i chyba tam właśnie jest zdefiniowany jego wygląd.
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: DropDownStyle dla ComboBox

Nowy postprzez Cyfrowy Baron » niedziela, 3 kwietnia 2011, 21:29

Kod na efekt z gradientem:

Plik nagłówkowy np. Unit1.h
KOD cpp:     UKRYJ  
private:
        Graphics::TBitmap *cBmp;


Plik źródłowy np. Unit1.cpp
KOD cpp:     UKRYJ  
__fastcall TForm1::TForm1(TComponent* Owner)
        : TForm(Owner)
{
 ComboBox1->ItemHeight = ImageList1->Height + 2;

 cBmp = new Graphics::TBitmap;
 cBmp->Width = ComboBox1->Width;
 cBmp->Height = ComboBox1->Height;

 int l = 0;

 for(int g = 0; g <= cBmp->Height; g++)
 {
   l += 3;
   TColor kolor = RGB(255 - l, 255 - l, 255 - l);

   cBmp->Canvas->Pen->Color = kolor;
   cBmp->Canvas->MoveTo(0, g);
   cBmp->Canvas->LineTo(cBmp->Width, g);
 }
}
//---------------------------------------------------------------------------
void __fastcall TForm1::ComboBox1DrawItem(TWinControl *Control, int Index,
        TRect &Rect, TOwnerDrawState State)
{
 TCanvas *tCanvas = ComboBox1->Canvas;
 String cText = ComboBox1->Items->Strings[Index];

 int x = ( ComboBox1->ItemHeight - tCanvas->TextHeight(cText) ) / 2 - 1;

 tCanvas->Brush->Style = bsSolid;

 if(State.Contains(odSelected))
 {
  tCanvas->Brush->Color = clYellow;
  tCanvas->Font->Color = clRed;
 }
 else
 {
  tCanvas->Brush->Color = ComboBox1->Color;
  tCanvas->Font->Color = ComboBox1->Font->Color;
 }

 if(State.Contains(odComboBoxEdit))
 {
  tCanvas->Brush->Bitmap = cBmp;
  tCanvas->Font->Color = clBlack;
 }

 tCanvas->FillRect(Rect);

 ImageList1->Draw(tCanvas, Rect.Left + 1, Rect.Top + 1, Index, true);

 TRect cRect = Rect;
 cRect.Left  = Rect.Left  + ImageList1->Width + 5;
 cRect.Right = Rect.Right - 1;
 cRect.Top   = Rect.Top + x;

 tCanvas->Brush->Style = bsClear;
 DrawText( tCanvas->Handle, cText.c_str(), -1, &cRect,
           DT_LEFT | DT_VCENTER | DT_END_ELLIPSIS | DT_NOCLIP );

 if(State.Contains(odFocused))
 {
  tCanvas->DrawFocusRect(Rect);
 }
}


A tak to wygląda:

combobox.png


Mój się nieco różni od tego, który Ty przedstawiłeś, ale ja korzystam z Windows XP i ze stylem tego systemu tak to właśnie wygląda.
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

Re: DropDownStyle dla ComboBox

Nowy postprzez Slynx » niedziela, 3 kwietnia 2011, 21:47

Ok, dzięki za informację. Z tego co wiem to komponenty do wersji 2008 Visuala są w wersji 2.0, dla Visuala 2010 wszystkie są w wersji 4.0, więc może tam znajduje się różnica.
Aktualnie pobieram wersję 2008 Proffesional Edition, która ma znacznie rozszerzone możliwości (np. pliki zasobów, ktorych nie ma w wersji EE), więc możliwe, że i w tej kwestii coś się zmieni (albo po prostu możliwość aktualizacji komponentów). Poczekamy, zobaczymy.
Avatar użytkownika
Slynx
Mądrosław
Mądrosław
 
Posty: 350
Dołączył(a): piątek, 17 grudnia 2010, 21:59
Podziękował : 11
Otrzymał podziękowań: 0
System operacyjny: Windows 7 32
Kompilator: Visual C++ 2005; Visual C++ 2008; Visual C++ 2010; Visual C# 2010;
Gadu Gadu: 0
    Windows 7Chrome

Re: DropDownStyle dla ComboBox

Nowy postprzez Cyfrowy Baron » poniedziałek, 4 kwietnia 2011, 09:13

Slynx napisał(a):Aktualnie pobieram wersję 2008 Proffesional Edition, która ma znacznie rozszerzone możliwości (np. pliki zasobów, ktorych nie ma w wersji EE)


To niczego nie zmieni, biblioteki będą w tej samej wersji nie do końca zgodnej z Windows XP. W przypadku C++Builder 6 problem występował zarówno w wersji Personal, Enterprise jak i Professional, więc przypuszczam, że w przypadku VC++ 2008 będzie podobnie. Musiałbyś użyć wersji 2010, gdyż tylko ta będzie w pełni zgodna z Windows 7.
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: DropDownStyle dla ComboBox

Nowy postprzez Slynx » poniedziałek, 4 kwietnia 2011, 12:25

No niestety w wersji 2010 nie pracuję ze względu na brak Intellisense, więc musi się bez tego jakoś obejść.
Avatar użytkownika
Slynx
Mądrosław
Mądrosław
 
Posty: 350
Dołączył(a): piątek, 17 grudnia 2010, 21:59
Podziękował : 11
Otrzymał podziękowań: 0
System operacyjny: Windows 7 32
Kompilator: Visual C++ 2005; Visual C++ 2008; Visual C++ 2010; Visual C# 2010;
Gadu Gadu: 0
    Windows 7Chrome

Re: DropDownStyle dla ComboBox

Nowy postprzez Cyfrowy Baron » poniedziałek, 4 kwietnia 2011, 13:17

Wcześniej czy później i tak będziesz musiał się przesiąść na nowsze wersje środowiska, szczególnie jeżeli chcesz tworzyć aplikacje zgodne z Windows 7. Z tego coś się orientuję to Intelisense w Visual Studio 2010 nie działa tylko dla języka C++/CLI. Czytałem gdzieś, że jest taki program Visual Assist X 10.6, który to zmienia, nie jest to jednak program darmowy, a licencja jednostanowiskowa kosztuje $99, a do celów edukacyjnych, czyli bez zastosowania komercyjnego kosztuje już tylko $49.
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: DropDownStyle dla ComboBox

Nowy postprzez Slynx » poniedziałek, 4 kwietnia 2011, 15:39

O tym wszystkim wiem. Szukałem na ten temat. Intellisense ma być dostępny w kolejnej wersji. W końcu wyrazili swoje oficjalne stanowisko i powiedzieli, że za dużo już pracy w to włożyli by teraz z tego rezygnować. Póki wszystko działa ( a przynajmniej częściowo, bo projekt się rozrasta i Visual zaczyna coraz bardziej spowalniać :/) będę się trzymał 2008, potem pewnie przeskoczę na najnowszą wersję jeśli żaden update nie wyjdzie do 2010.

Musiałbym po prostu język zmienić, a to jednak trochę... pracochłonne. I zaraz bym tu forum zasypał nowymi problemami związanymi z tą zmianą :/ Na razie jedyne co mogę zrobić to czekać.
Poza tym, no wiesz... wersja trial wersją trial. Może i 30 dni, ale te 30 dni to już od jakichś 6-7 miesięcy mam... ale jeśli tego oprogramowania nie sprzedaje ani nic, to zwyczajnie mam to gdzieś. Jak to będzie bardziej komercyjnie to wtedy się zaopatrzę w normalny soft.
Avatar użytkownika
Slynx
Mądrosław
Mądrosław
 
Posty: 350
Dołączył(a): piątek, 17 grudnia 2010, 21:59
Podziękował : 11
Otrzymał podziękowań: 0
System operacyjny: Windows 7 32
Kompilator: Visual C++ 2005; Visual C++ 2008; Visual C++ 2010; Visual C# 2010;
Gadu Gadu: 0
    Windows 7Chrome


  • Podobne tematy
    Odpowiedzi
    Wyświetlone
    Ostatni post

Powrót do Aplikacje multimedialne, graficzne

Kto przegląda forum

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

cron