vb@rchiv
VB Classic
VB.NET
ADO.NET
VBA
C#
vb@rchiv Offline-Reader - exklusiv auf der vb@rchiv CD Vol.4  
 vb@rchiv Quick-Search: Suche startenErweiterte Suche starten   Impressum  | Datenschutz  | vb@rchiv CD Vol.6  | Shop Copyright ©2000-2024
 
zurück
Rubrik: Controls · ListView   |   VB-Versionen: VB4, VB5, VB609.12.01
Hintergrundfarbe von ListItems-Einträgen ändern

Ein Beispiel, wie man jede zweite Zeile eines ListView-Controls mit einer anderen Hintergrundfarbe versehen kann.

Autor:   Thomas BannertBewertung:     [ Jetzt bewerten ]Views:  27.812 
ohne HomepageSystem:  Win9x, WinNT, Win2k, WinXP, Win7, Win8, Win10, Win11 Beispielprojekt auf CD 

Das ListView-Control erfreut sich besonderer Beliebtheit bei den Programmieren, da es sehr flexible ist und sich auf diese Weise auch leicht mehrspaltige Listen erstellen lassen.

Gerade in der Report-Ansicht würden sich viele Entwickler wünschen, dass man die Hintergrundfarbe zur Darstellung der kompletten Zeile eines Eintrags individuell festlegen lassen kann. Auch nicht schlecht wäre die Möglichkeit für jeden zweiten Eintrag immer die selbe Hintergrundfarbe zu verwenden. Und genau diese Funktionalität zeigt Ihnen unser heutiger Tipp.

Hierzu muss man mal wieder tief in die API-Trickliste greifen

Vorab eins: WICHTIG !!!
Das was nachfolgend an Code kommt, ist mit größter Vorsicht zu genießen SubClassing ist ne super tolle Sache, kann aber auch super toll in die Hose gehen...
...also NIEMALS versuchen die Funktion WindowProc zu debuggen. Keine Haltepunkte oder Variablenüberwachung. Vor dem Testen immer speichern, vor dem Beenden immer die WindowProc wiederherstellen und NIEMALS versuchen die Funktion WindowProc zu debuggen!!! (Hab ich mich da etwa wiederholt

Mit diesem Code wird die ganze Sache gestartet.

Private Sub Form_Load()
  ' WindowProc umleiten (Subclassing)
  lCCHwnd = Me.ListView1.hwnd
  lWindowProcOld = SetWindowLong(hwnd, GWL_WNDPROC, _
    AddressOf WindowProc)
 
  ' Hintergrundfarbe jeder zweiten Zeile
  glbLVWBackColor = &H00C0E0FF&
 
  ' Hier das ListView-Control mit Daten füllen
  ...
End Sub
 
Private Sub Form_Unload(Cancel As Integer)
  ' Sublassing beenden
  Call SetWindowLong(Me.hwnd, GWL_WNDPROC, lWindowProcOld)
End Sub

Man kann das ganze natürlich auch in jeder anderen Funktion starten und beenden, aber bitte unbedingt an das Beenden denken!!!

Und hier ein bissel Code, der in ein neues Modul des Projekts gehört:

' modLSV_Color.bas
Option Explicit
 
' WM_NOTIFY
Public Enum WinNotifications
  NM_FIRST = (-0&)
  NM_LAST = (-99&)
  NM_OUTOFMEMORY = (NM_FIRST - 1&)
  NM_CLICK = (NM_FIRST - 2&)
  NM_DBLCLK = (NM_FIRST - 3&)
  NM_RETURN = (NM_FIRST - 4&)
  NM_RCLICK = (NM_FIRST - 5&)
  NM_RDBLCLK = (NM_FIRST - 6&)
  NM_SETFOCUS = (NM_FIRST - 7&)
  NM_KILLFOCUS = (NM_FIRST - 8&)
  NM_CUSTOMDRAW = (NM_FIRST - 12&)
  NM_HOVER = (NM_FIRST - 13&)
End Enum
 
Public Const WM_NOTIFY As Long = &H4E&
 
' CustomDraw Konstanten
Public Const CDDS_PREPAINT As Long = &H1&
Public Const CDRF_NOTIFYITEMDRAW As Long = &H20&
Public Const CDDS_ITEM As Long = &H10000
Public Const CDDS_ITEMPREPAINT As Long = CDDS_ITEM Or _
  CDDS_PREPAINT
 
' Notification Message Struktur
' Ist lParam einer WM_NOTIFY Message.
Public Type NMHDR
  ' Fensterhandle des Controls, welches die Nachricht
  ' sendet
  hWndFrom As Long
 
  ' ID des Controls
  idFrom As Long
 
  ' Nachrichten-Code
  code As Long
End Type
 
' RECHTECK siehe MSDN
Public Type RECT
  Left As Long
  Top As Long
  Right As Long
  Bottom As Long
End Type
 
' NM_CUSTOMDRAW Benachrichtigungs-Message
Public Type NMCUSTOMDRAW
  hdr As NMHDR
  dwDrawStage As Long
  hDC As Long
  rc As RECT
  dwItemSpec As Long
  uItemState As Long
  lItemlParam As Long
End Type
 
' NM_CUSTOMDRAW von einem ListView
Public Type NMLVCUSTOMDRAW
  nmcd As NMCUSTOMDRAW
  clrText As Long
  clrTextBk As Long
  iSubItem As Integer ' NUR IE >= 4.0
End Type
 
' API Funktionen
Public Declare Function CallWindowProc Lib "user32" _
  Alias "CallWindowProcA" ( _
  ByVal lpPrevWndFunc As Long, _
  ByVal hwnd As Long, _
  ByVal Msg As Long, _
  ByVal wParam As Long, _
  ByVal lParam As Long) As Long
 
Public Declare Sub CopyMemory Lib "kernel32" _
  Alias "RtlMoveMemory" ( _
  lpDest As Any, _
  lpSource As Any, _
  ByVal cBytes&)
 
Public Declare Function SetWindowLong Lib "user32" _
  Alias "SetWindowLongA" ( _
  ByVal hwnd As Long, _
  ByVal nIndex As Long, _
  ByVal dwNewLong As Long) As Long
 
' Pointer zum Original Message Handler des Forms
Public lWindowProcOld As Long
 
' Das Handle des CommonControl welches eigefärbt
' werden soll
Public lCCHwnd As Long
 
Public Const GWL_WNDPROC = (-4)
 
' Hintergrundfarbe
Public glbLVWBackColor As Long
Public Function WindowProc(ByVal hwnd As Long, _
  ByVal iMsg As Long, ByVal wParam As Long, _
  ByVal lParam As Long) As Long
 
  ' Die WM_NOTIFY message
  Dim oNMHDR As NMHDR
 
  ' CustomDraw eines ListViews
  Dim oNMLVCUSTOMDRAW As NMLVCUSTOMDRAW
 
  Select Case iMsg
    ' Uns interessieren nur WM_NOTIFY messages
    Case WM_NOTIFY
      ' Ah, da is ja schon eine ;-)
      ' lParam in eine WM_NOTIFY Struktur kopieren
      CopyMemory oNMHDR, ByVal lParam, 12&
 
      If oNMHDR.hWndFrom = lCCHwnd Then
        ' Kommt die Message auch vom richtigen Control?
        If oNMHDR.code = NM_CUSTOMDRAW Then
          ' Ahh ein CommonControl zeichnet da etwas
          CopyMemory oNMLVCUSTOMDRAW, ByVal lParam, _
            Len(oNMLVCUSTOMDRAW)
 
          With oNMLVCUSTOMDRAW.nmcd
            ' Wo wird gerade gezeichnet
            Select Case .dwDrawStage
              Case CDDS_PREPAINT
                ' PrePaint des ListViews ignorieren
                ' Windows mitteilen das alle Items
                ' einzeln gezeichnet werden sollen
                WindowProc = CDRF_NOTIFYITEMDRAW
                ' Funktion verlassen und Message dem
                ' Form "unterschlagen"
                Exit Function
 
              Case CDDS_ITEMPREPAINT
                ' Hier wird ein ListItem vorgezeichnet
                ' .dwItemSpec = ListItem Index
                If (.dwItemSpec Mod 2) = 0 Then
                  ' Bei jedem 2ten Listeneintrag die
                  ' Farbe ändern
 
                  ' Hintergrundfarbe
                  oNMLVCUSTOMDRAW.clrTextBk = glbLVWBackColor
 
                  ' Nun die CustomDraw Struktur wieder
                  ' nach lParam kopieren
                  CopyMemory ByVal lParam, oNMLVCUSTOMDRAW, _
                    Len(oNMLVCUSTOMDRAW)
 
                  WindowProc = CDRF_NOTIFYITEMDRAW
                  Exit Function
                End If
            End Select
          End With
        End If ' .code = NM_CUSTOMDRAW
      End If ' oNMHDR.hWndFrom = lCCHwnd
  End Select ' iMsg
 
  ' Die Message an VB weitergeben
  WindowProc = CallWindowProc(lWindowProcOld, hwnd, _
    iMsg, wParam, lParam)
End Function

Dieser Tipp wurde bereits 27.812 mal aufgerufen.

Voriger Tipp   |   Zufälliger Tipp   |   Nächster Tipp

Über diesen Tipp im Forum diskutieren
Haben Sie Fragen oder Anregungen zu diesem Tipp, können Sie gerne mit anderen darüber in unserem Forum diskutieren.

Neue Diskussion eröffnen

nach obenzurück


Anzeige

Kauftipp Unser Dauerbrenner!Diesen und auch alle anderen Tipps & Tricks finden Sie auch auf unserer aktuellen vb@rchiv  Vol.6
(einschl. Beispielprojekt!)

Ein absolutes Muss - Geballtes Wissen aus mehr als 8 Jahren vb@rchiv!
- nahezu alle Tipps & Tricks und Workshops mit Beispielprojekten
- Symbol-Galerie mit mehr als 3.200 Icons im modernen Look
Weitere Infos - 4 Entwickler-Vollversionen (u.a. sevFTP für .NET), Online-Update-Funktion u.v.m.
 
   

Druckansicht Druckansicht Copyright ©2000-2024 vb@rchiv Dieter Otter
Alle Rechte vorbehalten.
Microsoft, Windows und Visual Basic sind entweder eingetragene Marken oder Marken der Microsoft Corporation in den USA und/oder anderen Ländern. Weitere auf dieser Homepage aufgeführten Produkt- und Firmennamen können geschützte Marken ihrer jeweiligen Inhaber sein.

Diese Seiten wurden optimiert für eine Bildschirmauflösung von mind. 1280x1024 Pixel