Code: Select all
; ** LIST-VIEW GADGET BACKGROUND IMAGE & OWNERDRAW ITEMS **
;
; This code is based on code originally written by Sparkie,
; adapted by Srod and now heavily modified by me. It demonstrates
; how to display a background image in a ListView gadget featuring
; various types of drawing it. Furthermore this is an complete
; example of using listboxes with owner-draw items.
;
;
; Original Forum-Thread by Sparkie:
; http://www.purebasic.fr/english/viewtopic.php?t=13623
;
; Adapted Version by Srod:
; http://www.purebasic.fr/english/viewtopic.php?t=24449
;
;
; =================================================================
; Author : Fluid Byte
; Version : PB 4.XX
; Platform : Windows
; E-Mail: fluidbyte@web.de
; =================================================================
;
;
; Sourcecode Changes:
; -------------------
;
; * Cleanup:
;
; - Naming Conventions
; - Spacing / Tabbing
; - Paragraphs
; - Command Concatenation (:)
; - Codeflow
;
; * Optimizations:
;
; - Procedures have been split up and merged
; - Removed redundant code
; - Removed dublicated code
; - Error Checking
; - Linear stretchmode is now #COLORONCOLOR
; - API Usage Compatibility
;
; * Fixed:
;
; - Gadget didn't refresh after and while selecting multiple items via mouse dragging
; - Following default listbox messages were missing:
; >> #WM_CHAR
; >> #WM_SETFOCUS
; >> #WM_KILLFOCUS
;
; * Added:
;
; - Backdrop is now set with a single extra command: SetBackgroundImage()
; - Gadget / Image can be a Handle or Identifier
; - Stretch Mode: smooth / linear
; - Drawing Mode: fixed / tiled / stretched
; - Item Height: Height of current gadget font / user defined
; - Automatic item label positioning
; - Color Sheme: Operating System / user defined
; - Item Background Rectangle
; - Item Text Status: highlighted / disabled
; - Item Focus Rectangle: Operating System / user defined
EnableExplicit
Enumeration
#ODLV_FIXED
#ODLV_TILED
#ODLV_STRETCH
#ODLV_LINEAR
#ODLV_SMOOTH
EndEnumeration
Structure ODLV_DATA
DrawMode.b
StretchMode.b
ItemHeight.b
bSysColors.b
clrText.l
clrHiLight.l
clrGrayed.l
clrBack.l
clrFocus.l
dwReserved1.i
dwReserved2.i
EndStructure
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Procedure ODLV_ListboxProc(hWnd,uMsg,wParam,lParam)
Protected *odlv.ODLV_DATA, Result, bRepaint
*odlv = GetWindowLongPtr_(hwnd,#GWL_USERDATA)
; // REPAINT TRIGGER //
Result = CallWindowProc_(*odlv\dwReserved2,hwnd,uMsg,wParam,lParam)
Select uMsg
Case #WM_KEYDOWN
If wParam = #VK_DOWN Or wParam = #VK_UP Or wParam = #VK_NEXT Or wParam = #VK_PRIOR Or wParam = #VK_HOME Or wParam = #VK_END
bRepaint = #True
EndIf
Case #WM_MOUSEMOVE
If wParam <> 0
bRepaint = #True : Result = 0
EndIf
Case #WM_ERASEBKGND
bRepaint = #True : Result = 1
Case #WM_PAINT
bRepaint = #False : Result = 0
Case #WM_SETFOCUS, #WM_KILLFOCUS, #WM_CHAR, #WM_LBUTTONDOWN, #WM_LBUTTONUP, #WM_VSCROLL, #WM_MOUSEWHEEL
bRepaint = #True : Result = 0
EndSelect
; // REPAINT SETUP (logical order) //
If bRepaint
Protected crc.RECT, hbmOutput, hDC, hdcMem, bmp.BITMAP, hbrBackground
Protected ItemIndex, ItemCount, i, SelStart, SelEnd, SelDir
Protected bHighlight, irc.RECT, lpBuffer, hdcLB, si.SCROLLINFO
Static prevScrollPos
GetClientRect_(hwnd,crc)
hbmOutput = CreateImage(#PB_Any,crc\right-crc\left,crc\bottom-crc\top)
hdc = StartDrawing(ImageOutput(hbmOutput))
SelectObject_(hdc,GetGadgetFont(GetDlgCtrlID_(hwnd)))
SetBkMode_(hdc,#TRANSPARENT)
SetTextAlign_(hdc,#TA_NOUPDATECP)
; // DRAW BACKGROUND //
hdcMem = CreateCompatibleDC_(hdc)
SelectObject_(hdcMem,*odlv\dwReserved1)
GetObject_(*odlv\dwReserved1,SizeOf(BITMAP),bmp)
Select *odlv\DrawMode
Case #ODLV_FIXED
FillRect_(hdc,crc,GetSysColorBrush_(#COLOR_WINDOW))
BitBlt_(hdc,0,0,crc\right-crc\left,crc\bottom-crc\top,hdcMem,0,0,#SRCCOPY)
Case #ODLV_TILED
hbrBackground = CreatePatternBrush_(*odlv\dwReserved1)
FillRect_(hdc,crc,hbrBackground)
DeleteObject_(hbrBackground)
Case #ODLV_STRETCH
If *odlv\StretchMode = #ODLV_SMOOTH
SetStretchBltMode_(hdc,#HALFTONE)
Else
SetStretchBltMode_(hdc,#COLORONCOLOR)
EndIf
StretchBlt_(hdc,0,0,crc\right-crc\left,crc\bottom-crc\top,hdcMem,0,0,bmp\bmWidth,bmp\bmHeight,#SRCCOPY)
EndSelect
DeleteDC_(hdcMem)
; // ENUMERATE ITEMS //
ItemIndex = SendMessage_(hwnd,#LB_GETTOPINDEX,0,0)
ItemCount = SendMessage_(hwnd,#LB_GETCOUNT,0,0) - 1
For i = ItemIndex To ItemCount
SendMessage_(hwnd,#LB_GETITEMRECT,i,irc)
If irc\bottom <= crc\bottom
; // ITEM SELECTION //
If (uMsg = #WM_MOUSEMOVE And wParam & #MK_LBUTTON) Or (uMsg = #WM_LBUTTONDOWN And wParam & #MK_SHIFT)
SelStart = SendMessage_(hwnd,#LB_GETANCHORINDEX,0,0)
SelEnd = SendMessage_(hwnd,#LB_GETCARETINDEX,0,0)
SelDir = SelEnd - SelStart
If SelDir > 0
If i >= SelStart And i <= SelEnd : bHighlight = #True : EndIf
Else
If i>= SelEnd And i <= SelStart : bHighlight = #True : EndIf
EndIf
EndIf
If SendMessage_(hwnd,#LB_GETSEL,i,0) : bHighlight = #True : EndIf
; // DRAW ITEMS //
lpBuffer = AllocateMemory(SendMessage_(hwnd,#LB_GETTEXTLEN,i,0))
SendMessage_(hwnd,#LB_GETTEXT,i,lpBuffer)
If bHighlight
SetTextColor_(hdc,*odlv\clrHiLight)
Box(irc\left,irc\top,irc\right - irc\left,irc\bottom - irc\top,*odlv\clrBack)
irc\left + 5
DrawText_(hdc,lpBuffer,-1,irc,#DT_SINGLELINE | #DT_VCENTER)
irc\left - 5
If i = SendMessage_(hwnd,#LB_GETANCHORINDEX,0,0) And GetFocus_() = hwnd
If *odlv\clrFocus = -1
SetTextColor_(hdc,0)
DrawFocusRect_(hdc,irc)
Else
DrawingMode(#PB_2DDrawing_Transparent | #PB_2DDrawing_Outlined)
Box(irc\left,irc\top,irc\right - irc\left,irc\bottom - irc\top,*odlv\clrFocus)
EndIf
EndIf
Else
If IsWindowEnabled_(hwnd)
SetTextColor_(hdc,*odlv\clrText)
Else
SetTextColor_(hdc,*odlv\clrGrayed)
EndIf
irc\left + 5
DrawText_(hdc,lpBuffer,-1,irc,#DT_SINGLELINE | #DT_VCENTER)
EndIf
FreeMemory(lpBuffer) : bHighlight = #False
Else
Break
EndIf
Next
; // OUTPUT IMAGE + CLEANUP //
hdcLB = GetDC_(hwnd)
BitBlt_(hdcLB,0,0,crc\right - crc\left,crc\bottom - crc\top,hdc,0,0,#SRCCOPY)
ReleaseDC_(hwnd,hdcLB)
StopDrawing()
FreeImage(hbmOutput)
; // REFRESH SCROLLBAR (KEYBOARD INPUT) //
si\cbSize = SizeOf(SCROLLINFO)
si\fMask = #SIF_POS
GetScrollInfo_(hwnd,#SB_VERT,@si)
If si\nPos <> prevScrollPos
SetScrollInfo_(hwnd,#SB_VERT,@si,#True)
EndIf
prevScrollPos = si\nPos
EndIf
ProcedureReturn Result
EndProcedure
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Procedure SetBackgroundImage(GadgetID,ImageID,*odlv.ODLV_DATA)
Protected hwndListBox, fsz.SIZE, hdc
If IsGadget(GadgetID)
hwndListBox = GadgetID(GadgetID)
ElseIf IsWindow_(GadgetID)
hwndListBox = GadgetID
Else
ProcedureReturn 0
EndIf
If *odlv\ItemHeight <= 0
hdc = GetDC_(hwndListBox)
SelectObject_(hdc,SendMessage_(hwndListBox,#WM_GETFONT,0,0))
GetTextExtentPoint32_(hdc,"ABCDEF",6,fsz)
*odlv\ItemHeight = fsz\cy
ReleaseDC_(hwndListBox,hdc)
EndIf
If *odlv\bSysColors
*odlv\clrText = GetSysColor_(#COLOR_WINDOWTEXT)
*odlv\clrHiLight = GetSysColor_(#COLOR_HIGHLIGHTTEXT)
*odlv\clrGrayed = GetSysColor_(#COLOR_GRAYTEXT)
*odlv\clrBack = GetSysColor_(#COLOR_HIGHLIGHT)
EndIf
SendMessage_(hwndListBox,#LB_SETITEMHEIGHT,0,*odlv\ItemHeight)
SendMessage_(hwndListBox,#WM_SETREDRAW,0,0)
SetWindowLongPtr_(hwndListBox,#GWL_USERDATA,*odlv)
If IsImage(ImageID)
*odlv\dwReserved1 = ImageID(ImageID)
ElseIf GetObjectType_(ImageID) = #OBJ_BITMAP
*odlv\dwReserved1 = ImageID
Else
ProcedureReturn 0
EndIf
*odlv\dwReserved2 = SetWindowLongPtr_(hwndListBox,#GWL_WNDPROC,@ODLV_ListboxProc())
ProcedureReturn #True
EndProcedure
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
#LST_BackdropDemo = 100
Define i, odlv.ODLV_DATA, EventID
; Create custom background image
CreateImage(0,250,300)
StartDrawing(ImageOutput(0))
For i=0 To 299 : Box(0,i,250,1,RGB(255,55 + (i * 200 / 399),25)) : Next
StopDrawing()
; Create Listbox with background
OpenWindow(0,0,0,380,315,"Listbox Image Backdrop",#WS_OVERLAPPEDWINDOW | 1)
ListViewGadget(#LST_BackdropDemo,10,10,0,0,#PB_ListView_MultiSelect | #LBS_OWNERDRAWFIXED)
For i = 1 To 100
AddGadgetItem(#LST_BackdropDemo,-1,"Item #" + RSet(Str(i),3,"0") + " of the Listview")
Next
odlv\DrawMode = #ODLV_STRETCH ; Background will sized to fit window
odlv\StretchMode = #ODLV_LINEAR ; Background will not be smoothed (much faster when using #ODLV_STRETCH!)
odlv\ItemHeight = 0 ; Use height of the default gadget font
odlv\bSysColors = #True ; Use Windows colors to draw items
odlv\clrText = 0 ; Color of normal item labels
odlv\clrHiLight = 0 ; Color of selected item labels
odlv\clrGrayed = 0 ; Color of disbaled item labels
odlv\clrBack = 0 ; Color of the highlight background
odlv\clrFocus = -1 ; Color of the focus rect (-1 = system rect)
SetBackgroundImage(#LST_BackdropDemo,0,odlv)
; Main loop
Repeat
EventID = WaitWindowEvent()
If EventID = #PB_Event_SizeWindow
ResizeGadget(#LST_BackdropDemo,5,5,WindowWidth(0)-10,WindowHeight(0)-10)
EndIf
Until EventID = #WM_CLOSE