ListView background image.
Posted: Sun Jun 04, 2006 12:14 am
Hi,
I've attacked some excellent code of Sparkie's in which he showed one way of constructing a transparent ListView:
http://www.purebasic.fr/english/viewtop ... ound+image
He basically paints the gadget onto an off-screen image and then BitBlit's it back as appropriate to produce a beautifully flicker-free gadget.
The same method is easily adapted to give a ListView gadget a background image (something which, unlike a ListIcon, Window's does not support natively). I wrote this after misunderstanding someone's request in the coding forum! :roll:
Anyhow, I thought I'd post the code (with Sparkie's blessing!) Someone might find it useful.
There are other ways of supporting background images in ListView's, but as I say, this one is essentially without flicker!
I've attacked some excellent code of Sparkie's in which he showed one way of constructing a transparent ListView:
http://www.purebasic.fr/english/viewtop ... ound+image
He basically paints the gadget onto an off-screen image and then BitBlit's it back as appropriate to produce a beautifully flicker-free gadget.
The same method is easily adapted to give a ListView gadget a background image (something which, unlike a ListIcon, Window's does not support natively). I wrote this after misunderstanding someone's request in the coding forum! :roll:
Anyhow, I thought I'd post the code (with Sparkie's blessing!) Someone might find it useful.
Code: Select all
;**BACKGROUND IMAGE IN LIST-VIEW GADGET**
;This code is based on code written by that genius Sparkie:
; (http://www.purebasic.fr/english/viewtopic.php?t=13623&highlight=background+image)
;and adapted by srod to show a background image in a list view gadget.
;/=========================================================
;/ Code : Background image in ListViewgadget
; (based upon 'Transparent ListViewgadget' by Sparkie).
;/ Author : Adapted by srod.
;/ Rel Date : 03/06/06
;/ PB Version : PB 4.00
;/ OS Support : Windows
;/=========================================================
;/===============================================
;/ Globals
;/===============================================
Global oldCallback
#Window_Main=0
#ListView_1=0
Enumeration
#lv_image
#back_image
EndEnumeration
;/===============================================
;/ Image
;/===============================================
UseJPEGImageDecoder()
UsePNGImageDecoder()
LoadImage(#back_image, "katie.jpg") ;Include your own image here.
;/===============================================
;/ Procedure: SizeBackImage
;/===============================================
Procedure.l SizeBackImage(hwnd, *rc.RECT)
Protected hdc, dc
If IsImage(#lv_image)
ResizeImage(#lv_image, *rc\right-*rc\left, *rc\bottom-*rc\top)
Else
CreateImage(#lv_image, *rc\right-*rc\left, *rc\bottom-*rc\top)
EndIf
hdc=StartDrawing(ImageOutput(#lv_image))
dc = CreateCompatibleDC_(hdc)
If dc
SelectObject_(dc,ImageID(#back_image))
StretchBlt_(hdc, 0,0,*rc\right-*rc\left, *rc\bottom-*rc\top,dc,0,0,ImageWidth(#back_image),ImageHeight(#back_image),#SRCCOPY)
DeleteDC_(dc)
result=1
Else
result=0
EndIf
StopDrawing()
ProcedureReturn result
EndProcedure
;/===============================================
;/ Procedure: Do Painting of ListViewGadget
;/===============================================
Procedure PaintIt(hwnd)
Protected gadRc.RECT, lvDc, bgDc, gadId, firstItem, totalItems, isBorder, i, itemRc.RECT
Protected itemText$, itemState, si.SCROLLINFO
Static previousScrollPos
;...Get client rect for ListViewGadget
GetClientRect_(hwnd, gadRc)
SizeBackImage(hwnd, gadRc)
;...Get ListView DC
lvDc = GetDC_(hwnd)
;...Get image DC
bgDc = StartDrawing(ImageOutput(#lv_image))
;...Get gadget#
gadId = GetDlgCtrlID_(hwnd)
;...Get first visible item
firstItem = SendMessage_(hwnd, #LB_GETTOPINDEX, 0, 0)
;...Get total number of items
totalItems = SendMessage_(hwnd, #LB_GETCOUNT, 0, 0) - 1
;...Determine border size
isBorder = GetWindowLong_(GadgetID(gadId), #GWL_EXSTYLE) & #WS_EX_CLIENTEDGE
If isBorder
border = GetSystemMetrics_(#SM_CYEDGE)
Else
border = 0
EndIf
;...Set drawing mode for text and focus rect
DrawingMode(#PB_2DDrawing_Outlined | #PB_2DDrawing_Transparent)
;...Draw new text if visible
For i = firstItem To totalItems
SendMessage_(hwnd, #LB_GETITEMRECT, i, itemRc)
If itemRc\bottom <= gadRc\bottom
;...Get item text and state
itemText$ = GetGadgetItemText(gadId, i, 0)
itemState = GetGadgetItemState(gadId, i)
If itemState = 0
itemRc\left + 5
;...Draw selected text
DrawText(itemRc\left, itemRc\top, itemText$, #Black)
Else
;...Create a 5 px left margin
itemRc\left + 5
;...Draw selected text
DrawText(itemRc\left, itemRc\top, itemText$, #Black)
;...Reset margin
itemRc\left - 5
;...Draw our focus rect
Box(itemRc\left, itemRc\top, itemRc\right - itemRc\left, itemRc\bottom - itemRc\top, #Black)
EndIf
Else
Break
EndIf
Next i
;...Copy our background image onto ListViewGadget DC
BitBlt_(lvDc, 0, 0, gadRc\right - gadRc\left, gadRc\bottom - gadRc\top, bgDc, 0, 0, #SRCCOPY)
;...Clean up
ReleaseDC_(hwnd, lvDc)
StopDrawing()
;...Redraw scrollbar position as needed
si\cbSize = SizeOf(SCROLLINFO)
si\fMask = #SIF_POS
GetScrollInfo_(hwnd, #SB_VERT, @si)
If si\nPos <> previousScrollPos
SetScrollInfo_(hwnd, #SB_VERT, @si, #True)
EndIf
previousScrollPos = si\nPos
EndProcedure
;/===============================================
;/ Procedure: ListViewGadget Callback
;/===============================================
Procedure LVcallback(hwnd, msg, wParam, lParam)
result = CallWindowProc_(oldCallback, hwnd, msg, wParam, lParam)
doPaint = #False
Select msg
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
doPaint = #True
EndIf
Case #WM_LBUTTONDOWN
doPaint = #True
result = 0
Case #WM_MOUSEMOVE
If wParam <> 0
doPaint = #True
result = 0
EndIf
Case #WM_ERASEBKGND
doPaint = #True
result = 1
Case #WM_PAINT
doPaint = #False
result = 0
Case #WM_VSCROLL
doPaint = #True
result = 0
Case #WM_MOUSEWHEEL
doPaint = #True
result = 0
EndSelect
;...Redraw the ListViewGadget as needed
If doPaint
PaintIt(hwnd)
EndIf
ProcedureReturn result
EndProcedure
;/===============================================
;/ Create Main window and gadgets
;/===============================================
;...Get image to use for window background
If OpenWindow(#Window_Main, 0, 0, 640, 450, "image in ListViewGadget", #PB_Window_SizeGadget | #PB_Window_SystemMenu | #PB_Window_ScreenCentered) And CreateGadgetList(WindowID(#Window_Main))
;...Ownerdraw our ListViewGadget
ListViewGadget(#ListView_1, 20, 20, 200, 400, #PB_ListView_Multiselect|#LBS_OWNERDRAWFIXED)
;...Optional: Un-comment next line to remove the ListView border
;SetWindowLong_(GadgetID(#ListView_1), #GWL_EXSTYLE, GetWindowLong_(GadgetID(#ListView_1), #GWL_EXSTYLE) & ~#WS_EX_CLIENTEDGE)
;...Add some items
For i = 0 To 99
AddGadgetItem (#ListView_1, -1, "Item " + Str(i) + " of the Listview")
Next i
;...Disable system drawing for ListViewGadget. We'll handle it ourselves.
SendMessage_(GadgetID(#ListView_1), #WM_SETREDRAW, 0, 0)
;...Subclass the ListViewGadget
oldCallback = SetWindowLong_(GadgetID(#ListView_1), #GWL_WNDPROC, @LVcallback())
Repeat
event = WaitWindowEvent()
Until event = #PB_Event_CloseWindow
;...Clean-up
FreeImage(#back_image)
If IsImage(#lv_image) : FreeImage(#lv_image) : EndIf
EndIf
End