'In a form
Option Explicit
Private Sub Form_Load()
Dim i As Integer
'*************************************
'NEED TO SET THIS LINE IN DESIGN TIME AS READONLY PROPERTY!!!
'List1.Style = 1 '(checkbox)
'*************************************
For i = 0 To 15
'Set to the QBColours 0 - 15
List1.AddItem "Colour " & i
List1.itemData(List1.NewIndex) = QBColor(i)
Next
'Subclass the form
lPrevWndProc = SetWindowLong(hwnd, GWL_WNDPROC, AddressOf SubClassedList)
End Sub
Private Sub Form_Unload(Cancel As Integer)
'Release the subClassing
Call SetWindowLong(hwnd, GWL_WNDPROC, lPrevWndProc)
End Sub
'In a module
Option Explicit
'Co ordinates for rectangle items
Public Type RECT
Left As Long
Top As Long
Right As Long
Bottom As Long
End Type
'Info for each draw item
Public Type DRAWITEMSTRUCT
CtlType As Long
CtlID As Long
itemID As Long
itemAction As Long
itemState As Long
hwndItem As Long
hdc As Long
rcItem As RECT
itemData As Long
End Type
Public Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)
'Used for subclassing
Public lPrevWndProc As Long
Public Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
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 Const GWL_WNDPROC = (-4)
Public Const WM_DRAWITEM = &H2B
Public Const ODT_LISTBOX = 2
'used to get the text in the listitem
Public Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long
Public Const LB_GETTEXT = &H189
'used to create a brush for drawing
Public Declare Function CreateSolidBrush Lib "gdi32" (ByVal crColor As Long) As Long
Public Declare Function DeleteObject Lib "gdi32" (ByVal hObject As Long) As Long
'used to set the background colour and text colours etc
Public Declare Function FillRect Lib "user32" (ByVal hdc As Long, lpRect As RECT, ByVal hBrush As Long) As Long
Public Declare Function SetBkColor Lib "gdi32" (ByVal hdc As Long, ByVal crColor As Long) As Long
Public Declare Function SetTextColor Lib "gdi32" (ByVal hdc As Long, ByVal crColor As Long) As Long
Public Declare Function TextOut Lib "gdi32" Alias "TextOutA" (ByVal hdc As Long, ByVal x As Long, ByVal y As Long, ByVal lpString As String, ByVal nCount As Long) As Long
'used to draw the dotted focus rectangle when something has the focus
Public Declare Function DrawFocusRect Lib "user32" (ByVal hdc As Long, lpRect As RECT) As Long
Public Const ODS_FOCUS = &H10
'used to get system colours
Public Declare Function GetSysColor Lib "user32" (ByVal nIndex As Long) As Long
Public Const COLOR_HIGHLIGHT = 13
Public Const COLOR_HIGHLIGHTTEXT = 14
Public Function SubClassedList(ByVal hwnd As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Dim tItem As DRAWITEMSTRUCT
Dim sBuff As String * 255
Dim sItem As String
Dim lBack As Long
Dim lngBkColour As Long
Dim lngTextColour As Long
'if windows (OS) is drawing items on the form (window)
If Msg = WM_DRAWITEM Then 'Redraw the listbox
'This function only passes the Address of the DrawItem Structure, so we need to
'use the CopyMemory API to Get a Copy into the Variable we setup:
Call CopyMemory(tItem, ByVal lParam, Len(tItem))
'Make sure we're dealing with a Listbox (listbox items)
If tItem.CtlType = ODT_LISTBOX Then
'DECIDE WHAT COLOURS WE WANT TO USE DEPENDING ON WHETHER THE LIST ITEM
'HAS FOCUS OR NOT
If (tItem.itemState And ODS_FOCUS) Then
'Item has focus, so highlight it
lngBkColour = GetSysColor(COLOR_HIGHLIGHT)
lngTextColour = GetSysColor(COLOR_HIGHLIGHTTEXT)
Else
'Item doesnt have focus so draw colour we specified in itemdatda
lngBkColour = tItem.itemData
'make sure text will be visible
lngTextColour = IIf(tItem.itemData = vbBlack, vbWhite, vbBlack)
End If
'DRAW THE BACKGROUND COLOUR
'Create a Brush
lBack = CreateSolidBrush(lngBkColour)
'Paint the item area
Call FillRect(tItem.hdc, tItem.rcItem, lBack)
'GET THE ITEM TEXT
Call SendMessage(tItem.hwndItem, LB_GETTEXT, tItem.itemID, ByVal sBuff)
sItem = Left(sBuff, InStr(sBuff, Chr(0)) - 1)
'SET THE TEXT COLOURS
'Set the text background colour
Call SetBkColor(tItem.hdc, lngBkColour)
'Set the text foreground colour
Call SetTextColor(tItem.hdc, lngTextColour)
'DRAW THE TEXT ITSELF
TextOut tItem.hdc, tItem.rcItem.Left, tItem.rcItem.Top, ByVal sItem, Len(sItem)
'dont forget to draw the focus rectangle if it had the focus
If (tItem.itemState And ODS_FOCUS) Then DrawFocusRect tItem.hdc, tItem.rcItem
'Release the brush object from memory that we created
Call DeleteObject(lBack)
Exit Function
End If
End If
SubClassedList = CallWindowProc(lPrevWndProc, hwnd, Msg, wParam, lParam)
End Function