ListBox s farebnými položkami

Václav Antošík       13.04.2008       VB.NET, Komponenty, WinForms       12690 zobrazení

Článok ukazuje ako vytvárať vlastné usercontroly na základe štandardných z system.windows.forms

Úvod

ListBox je veľmi často používaný kontrol vo všetkých aplikáciách. Používa sa hlavne na výber konkrétnej položky zo sady položiek. V štandardnom ListBoxe mi chýbala možnosť zmeniť si farbu označenej položky, jej font a farbu rámiku ktorý ju obteká. Tento artikel ukazuje ako vytvoriť vlastný user kontrol, ktorý nám hore uvedené vlastnosti bude ponúkať.

image

Background

Náš novy usercontrol bude založený na triede štandardného listboxu.

Triedu ktorá dedí jeho vlastnosti som nazval ColorListBoxEx.

 Public Class ColorListBoxEx : Inherits System.Windows.Forms.ListBox

Naša nová trieda obsahuje všetky vlastnosti štandardného listboxu plus nove vlastnosti ktoré som pridal.

image

· Farba rámiku označenej položky

 Public Property ColorBorder() As Color

· Farba textu označenej položky

 Public Property FontColor() As Color

· Index stĺpčeka v ktorom je uložený text na zobrazenie

 Public Property TextCol() As Byte

· Font označenej položky

 Public Property FontText() As Font

· Dĺžka farebnej zmeny rámiku označenej položky na osi x

 Public Property SmoothWidth() As Single

Každý public properties je vnútri triedy zastúpený lokálnou premennou, ktorá nadobúda jeho stav.

   Private myColor As Color 'Color of select border
Private myFont As Font = New Font("Arial", 8, FontStyle.Bold) 'Font of text in select border
Private myFontBrushColor As Drawing.Brush = System.Drawing.Brushes.White 'Color of text in select border
Private myFontColor As Color = Color.White 'Color of text in select border
Private myTextCol As Byte = 0 'When you have more columns -> this column is source for text
Private mySmoothWidth As Single = 0 'Smooth width

Náš novy listbox zachytáva príznak na prekreslenie dvomi spôsobmi :

Čaka na vyvolanie eventu SelectedIndexChanged z materskej triedy.

 Protected Sub ColorListBox_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) _
Handles MyBase.SelectedIndexChanged
NewDraw()
End Sub

Prekrýva funkciu WndProc a zachytáva správy ktoré Windows posiela nášmu kontrolu.

 Protected Overrides Sub WndProc(ByRef msg As System.Windows.Forms.Message)
MyBase.WndProc(msg)
Select Case msg.Msg
'&H115 - WM_VSCROLL
'&HF - WM_PAINT
'&H360 - WM_AFXFIRST
'&H203 - WM_LBUTTONDBLCLK
'&H20A - WM_MOUSEWHEEL
Case &H115, &HF, &H360, &H203, &H20A
NewDraw()
End Select
End Sub

&H115, &HF, &H360, &H203, &H20A – sú čísla sprav.

Cely zoznam môžete nájsť napr. Internetovej adrese : klik

Kresliť si budem sám

Aby sme mohli niečo do ListBoxu rozumne kresliť, musíme mu nejako povedať, že chceme aby sa prestal automaticky prekresľovať. Na to nám výborné poslúži jeho vlastnosť DrawMode, ktorú v metóde InitializeComponent nastavíme nasledujúcim riadkom

  Me.DrawMode = DrawMode.OwnerDrawVariable

A ide sa kresliť

Keď zachytíme event alebo správu, že je potrebne ListBox prekresliť zavolá sa srdce nášho nového kontrolu metóda NewDraw. Ako to funguje?

Prekresľovanie kontrolu si rozdelíme na dve časti. Najprv sa vykreslia riadky, ktoré nie sú označené a v druhej časti vykreslime označené riadky a to s pekným dúhovaným rámikom. Na začiatok si teda vytvoríme v pamäti duhovaný rámik. V premennej p2 si uchováme okrajové súradnice výfarbeného obdĺžnika, ktorý bude obtekať okraj vyznačenej položky a nasledujúcim riadkom už vytvoríme nový štetec.

  Dim p1, p2 As System.Drawing.PointF
  p1.X = 0 : p1.Y = 0 'Starting points of rectangle
p2.X = mySmoothWidth : p2.Y = MyClass.ItemHeight 'Finish points of rectangle
brushStandard = New System.Drawing.Drawing2D.LinearGradientBrush(p1, p2, myColor, MyClass.BackColor)

Nasleduje cyklus ktorý prebehne všetky položky kontrolu od začiatku po koniec

 For i As Integer = 0 To MyBase.Items.Count - 1

Tento blok kódu nerobí nič iné len skontroluje či sa jedna v danom kroku cyklu o selectovanú položku alebo nie. Podľa toho potom nastaví premennú isSelectedItem

  For j As Integer = 0 To MyBase.SelectedIndices.Count - 1
If TypeOf (MyClass.Items.Item(0)) Is String Then
If MyBase.Items(i) = MyBase.Items(MyBase.SelectedIndices(j)) Then isSelectedItem = True
Else
If TypeOf (MyClass.Items.Item(0).item(myTextCol)) Is String Then
If MyBase.Items.Item(i).item(myTextCol) = MyBase.Items.Item(MyBase.SelectedIndices(j)).item(myTextCol) Then isSelectedItem = True
End If
End If
Next

A konečne vykreslenie pozadia itemov a napísanie textu

If Not isSelectedItem Then
MyClass.CreateGraphics.FillRectangle(brushBackground, GetItemRectangle(i))
If TypeOf (MyClass.Items.Item(0)) Is String Then
drawText = MyClass.Items.Item(i)
Else
If TypeOf (MyClass.Items.Item(0).item(myTextCol)) Is String Then
drawText = MyClass.Items.Item(i).item(myTextCol)
Else
drawText = String.Empty
End If
End If
MyClass.CreateGraphics.DrawString(drawText, baseFont, baseFontBrushColor, 0, MyBase.GetItemRectangle(i).Y)
End If

Vykreslenie farebného rámiku

         'NewPaint(this draw selected item)
'1. I get positions of selected items to str(i).mySelect and I get indexs selected items to str(i).myIndex
For i As Integer = 0 To MyClass.SelectedIndices.Count - 1
ReDim Preserve str(i)
str(i).mySelect =
MyClass.GetItemRectangle(MyClass.SelectedIndices.Item(i))
str(i).myIndex =
MyClass.SelectedIndices.Item(i)
Next
If Not IsNothing(str) Then
For i As Integer = 0 To UBound(str)
'2. I draw rectangle to selected items positions
MyClass.CreateGraphics.FillRectangle(brushStandard, 0, str(i).mySelect.Y, MyClass.Width, MyClass.ItemHeight)
'3. I draw text to new rectangles
If TypeOf (MyClass.Items.Item(0)) Is String Then
drawText = MyClass.Items.Item(str(i).myIndex)
Else
If TypeOf (MyClass.Items.Item(0).item(myTextCol)) Is String Then
drawText = MyClass.Items.Item(str(i).myIndex).item(myTextCol)
Else
drawText = String.Empty
End If
End If
MyClass.CreateGraphics.DrawString(drawText, myFont, myFontBrushColor, 0, str(i).mySelect.Y)
Next
End If

V prvom bode si uložíme pozíciu štvorčeka označenej položky do premennej mySelect štruktúry str a pridáme si tam rovno aj index tejto položky do premennej myIndex. V druhom bode vykreslíme obdĺžnik na miesto selectovanej položky a v tretom na toto miesto vypíšeme text.

Nakoniec ešte uvoľníme alokovanú pamäť a nový kontrol je na svete.

brushStandard.Dispose()

Záver

Dúfam, že tento príklad pomohol sa zorientovať začínajúcim programátorom a naznačil cestu ako vytvárať vlastné usercontroly. Všetky konštruktívne opravy, postrehy, návrhy a otázky sú vítané.

Celý zdrojový súbor si môžete stiahnuť tu :

 

hodnocení článku

2 bodů / 2 hlasů       Hodnotit mohou jen registrované uživatelé.

 

Mohlo by vás také zajímat

Řešené příklady v ASP.NET - díl 2.: Aplikace pro zamlouvání sedadel (část 2)

V této části si vysvětlíme základy používání LINQ to SQL a napíšeme si jednoduchou třídu, která bude vracet data, která potřebujeme ve stránce, a rezervovat jednotlivá sedadla.

Práce s časovými pásmy a letním časem v aplikaci a databázi - díl 1.: Úvod do časových pásem a letního času

Ve článku se snažím popsat úskalí, která přináší konverze času přes více časových pásem a pravidel pro počítání letního času.

Práce s časovými pásmy a letním časem v aplikaci a databázi - díl 2.: DateTime v .NET Frameworku

Práce se strukturou DateTime v .NET Frameworku lze využívat pro práci s lokálním časem i časem v jiných časových pásmech. Tento díl se věnuje základnímu popisu a konverzím mezi lokálním a UTC časovým údajem.

 

 

Nový příspěvek

 

Diskuse: ListBox s farebnými položkami

Zajímavý příklad, ovšem šlo by to udělat daleko jednodušeji bez subclassingu použitím událostí MeasureItem a DrawItem.

nahlásit spamnahlásit spam 2 / 2 odpovědětodpovědět

Áno, určite sa to dá spraviť viacej spôsobmi. Tento príklad ale mal ilustrovať niektoré postupy, ktoré sú v článku použité.

nahlásit spamnahlásit spam 2 / 2 odpovědětodpovědět

Sakra kdy opravite ten link na stahnuti, uz nejede Mesic .

Tipuju ze nikdy nefungoval.

http://cdn.dotnetportal.cz/files/Windows...

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Nevedel som, že link nefunguje, ospravedlňujem sa. Keď bude trochu času tak sa na to pozriem. Zatiaľ si môžte stiahnúť zdrojové kódy z adresy http://www.codeproject.com/KB/cpp/XtremL...

Článok som tam ale písal v angličtine a sú tam ešte nejaké "muchy", ktoré som v zdrojákoch pre tento server už opravil. Pokúsim sa to vyriešiť čo najskôr.

Vašo.

nahlásit spamnahlásit spam 1 / 1 odpovědětodpovědět
                       
Nadpis:
Antispam: Komu se občas házejí perly?
Příspěvek bude publikován pod identitou   anonym.

Nyní zakládáte pod článkem nové diskusní vlákno.
Pokud chcete reagovat na jiný příspěvek, klikněte na tlačítko "Odpovědět" u některého diskusního příspěvku.

Nyní odpovídáte na příspěvek pod článkem. Nebo chcete raději založit nové vlákno?

 

  • Administrátoři si vyhrazují právo komentáře upravovat či mazat bez udání důvodu.
    Mazány budou zejména komentáře obsahující vulgarity nebo porušující pravidla publikování.
  • Pokud nejste zaregistrováni, Vaše IP adresa bude zveřejněna. Pokud s tímto nesouhlasíte, příspěvek neodesílejte.

přihlásit pomocí externího účtu

přihlásit pomocí jména a hesla

Uživatel:
Heslo:

zapomenuté heslo

 

založit nový uživatelský účet

zaregistrujte se

 
zavřít

Nahlásit spam

Opravdu chcete tento příspěvek nahlásit pro porušování pravidel fóra?

Nahlásit Zrušit

Chyba

zavřít

feedback