Page 1 of 4

Listicon Gadget bitmap ?

Posted: Mon Feb 06, 2006 4:48 pm
by dontmailme
Does anyone have some code that allows you to paint an image into a cell in a listicon gadget ?

I'm trying to find examples by searching but am either searching for the wrong thing or there no examples.

I think I need to get the dimensions of the cell and then paint a bitmap over the top of it but have not yet found out how to do it.

The image will be the same size as the row, probably 300x14 which will contain coloured text. ( Each Character can be a different colour! )

Unless anyone has an easier way to paint coloured text into a listicon gadget ?

I'm not too good with the API which is why I'm stuck!

Anyone ?

Posted: Wed Feb 08, 2006 6:42 am
by Sparkie
This may be a little overkill for your needs, but feel free to pick this code apart and use what you need. :)

If you'd rather use an image instead, I'll see what I can come up with. ;)

Code written for PB 3.94 but can be easily modified for 4.0b

Code: Select all

; ************************************************************************ 
; Code:   Multicolor Text in ListIconGadget
; Author: Sparkie 
; Date:   February 07, 2006 
; OS:     Windows only 
; PB ver: 3.94
; Notes:  
; ************************************************************************ 
; ########################################
; Window constants
; ########################################
Enumeration
  #WindowMain = 1
EndEnumeration
; ########################################
; Gadget constants
; ########################################
Enumeration
  #ListIcon1 = 1
  #Button1
EndEnumeration

; ########################################
; ListIconGadget NMLVCUSTOMDRAW constants
; ########################################
#LVM_GETSUBITEMRECT = #LVM_FIRST + 56
#CDDS_ITEM = $10000
#CDDS_POSTERASE = 4
#CDDS_POSTPAINT = 2
#CDDS_PREERASE = 3
#CDDS_PREPAINT = 1
#CDDS_ITEMPOSTERASE = #CDDS_ITEM | #CDDS_POSTERASE
#CDDS_ITEMPOSTPAINT = #CDDS_ITEM | #CDDS_POSTPAINT
#CDDS_ITEMPREERASE = #CDDS_ITEM | #CDDS_PREERASE
#CDDS_ITEMPREPAINT = #CDDS_ITEM | #CDDS_PREPAINT
#CDDS_SUBITEM = $20000
#CDRF_DODEFAULT = 0
#CDRF_NOTIFYITEMDRAW = $20
#CDRF_NOTIFYPOSTERASE = $40
#CDRF_NOTIFYPOSTPAINT = $10
#CDRF_NOTIFYSUBITEMDRAW = $20
#CDRF_SKIPDEFAULT = 4
; //////////////////////////////////////////
; Array to hold character colors
; //////////////////////////////////////////
Dim charColor(255)
; //////////////////////////////////////////
; Global brush for ListIcon background
; //////////////////////////////////////////
Global blackBrush
blackBrush = GetStockObject_(#BLACK_BRUSH)
; //////////////////////////////////////////
; Procedure to create random text colors
; //////////////////////////////////////////
Procedure CreateRandomColors()
  For char = 0 To 255
    ; ..........................................................
    ; I'll keep the RGB values between 100 and 255 for brighness
    ; ..........................................................
    charColor(char) = RGB(Random(155)+100, Random(155)+100, Random(155)+100) 
  Next char
EndProcedure
; //////////////////////////////////////////
; Procedure to get character width
; //////////////////////////////////////////
Procedure GetCharWidth(hListIcon, char$)
  charwidth = SendMessage_(hListIcon, #LVM_GETSTRINGWIDTH, 0, @char$)
  ProcedureReturn charwidth
EndProcedure
; //////////////////////////////////////////
; Procedure for changing text colors
; //////////////////////////////////////////
Procedure ChangeColors()
  CreateRandomColors()
  SendMessage_(GadgetID(#ListIcon1), #LVM_REDRAWITEMS, 0, 11)
EndProcedure
; //////////////////////////////////////////
; Main window callback
; //////////////////////////////////////////
Procedure WinCallback(hwnd, msg, wparam, lparam)
  result = #PB_ProcessPureBasicEvents
  Select msg
    Case #WM_NOTIFY
      *nmhdr.NMHDR = lparam
      If *nmhdr\code = #NM_CUSTOMDRAW And *nmhdr\hwndFrom = GadgetID(#ListIcon1)
        *lvCD.NMLVCUSTOMDRAW = lparam
        ; ...................................................
        ; --> Make sure text background is always transparent
        ; ...................................................
        SetBkMode_(*lvCD\nmcd\hdc, #TRANSPARENT)
        Select *lvCD\nmcd\dwDrawStage
          Case #CDDS_PREPAINT 
            result = #CDRF_NOTIFYITEMDRAW 
          Case #CDDS_ITEMPREPAINT 
            result = #CDRF_NOTIFYSUBITEMDRAW
          Case #CDDS_ITEMPREPAINT | #CDDS_SUBITEM
            result = #CDRF_NOTIFYPOSTPAINT 
          Case #CDDS_ITEMPOSTPAINT | #CDDS_SUBITEM
            If *lvCD\nmcd\dwItemSpec > -1 And  *lvCD\iSubItem > -1
              ; ................................................
              ; --> Get item text
              ; ................................................
              item$ = GetGadgetItemText(#ListIcon1, *lvCD\nmcd\dwItemSpec, *lvCD\iSubItem)
              ; ................................................
              ; --> Get item rect
              ; ................................................
              subItemRc.RECT\left = #LVIR_LABEL
              subItemRc\top = *lvCD\iSubItem
              SendMessage_(*lvCD\nmcd\hdr\hwndFrom, #LVM_GETSUBITEMRECT, *lvCD\nmcd\dwItemSpec, @subItemRc) 
              ; ................................................
              ; --> Fill item rect with our brush color (black)
              ; ................................................
              FillRect_(*lvCD\nmcd\hdc, subItemRc, blackBrush)
              ; ................................................
              ; --> Adjust left margin
              ; ................................................
              If *lvCD\iSubItem = 0
                subItemRc\left + (GetSystemMetrics_(#SM_CXEDGE) * 3) - 2
              Else
                subItemRc\left + GetSystemMetrics_(#SM_CXEDGE) * 3
              EndIf
              ; ................................................
              ; --> Colorize each character and draw it
              ; ................................................
              For char = 1 To Len(item$)
                char$ = Mid(item$, char, 1)
                ; ........................................................
                ; --> I am adding + *lvCD\nmcd\dwItemSpec + *lvCD\iSubItem
                ;     only for variety of colors, so this is optional
                ; ........................................................
                SetTextColor_(*lvCD\nmcd\hdc, charColor(Asc(char$) + *lvCD\nmcd\dwItemSpec + *lvCD\iSubItem))
                DrawText_(*lvCD\nmcd\hdc, char$, 1, subItemRc, #DT_NOCLIP)
                ; ........................................................
                ; --> Get the current character width (pixels) and move
                ;     the drawing rect\left for the next character.
                ;     I am adding + *lvCD\nmcd\dwItemSpec + *lvCD\iSubItem
                ;     only for increased spacing, so this is optional
                ; ........................................................
                subItemRc\left + GetCharWidth(*nmhdr\hwndFrom, char$) + *lvCD\nmcd\dwItemSpec + *lvCD\iSubItem
              Next char
            EndIf
            result = #CDRF_SKIPDEFAULT
        EndSelect
      EndIf
  EndSelect
  ProcedureReturn result
EndProcedure
; //////////////////////////////////////////
; Main Window
; //////////////////////////////////////////
If OpenWindow(#WindowMain, 0, 0, 620, 235,#PB_Window_SystemMenu,"Sparkies Multicolor ListIconGadget") And CreateGadgetList(WindowID(#WindowMain)) 
  SetWindowCallback(@WinCallback())
  ListIconGadget(#ListIcon1, 5, 5, 610, 195, "Column 0", 270, #PB_ListIcon_AlwaysShowSelection | #PB_ListIcon_FullRowSelect)
  ButtonGadget(#Button1, 260, 205, 100, 25, "Change colors")
  ; ................................................
  ; --> Uncomment next line if text shadowing occurs
  ;     that will make text invisible (text color on back color)
  ; ................................................
  ;SendMessage_(GadgetID(0), #LVM_SETTEXTCOLOR, 0, #Black)
  SendMessage_(GadgetID(#ListIcon1), #LVM_SETBKCOLOR, 0, #Black)
  ; ................................................
  ; --> Change font is optional
  ; ................................................
  hCourierNew = LoadFont(0, "Courier New", 10, #PB_Font_Bold)
  SetGadgetFont(0, hCourierNew)
  ; ................................................
  ; --> Add our ListIcon items
  ; ................................................
  AddGadgetColumn(#ListIcon1, 1, "Column 1", 335)
  For i = 0 To 11
    AddGadgetItem(#ListIcon1, -1, "Experience the " + Chr(10) + "Power of PureBasic")
  Next
  ; ................................................
  ; --> Create random text color
  ; ................................................
  CreateRandomColors()
  ; //////////////////////////////////////////
  ; Main window event loop
  ; //////////////////////////////////////////
  Repeat
    event = WaitWindowEvent()
    If event = #PB_EventGadget And EventGadgetID() = #Button1
      ChangeColors()
    EndIf
  Until event = #PB_Event_CloseWindow 
  ; ................................................
  ; Optional for GetStockObject
  ; ................................................
  DeleteObject_(blackBrush)
EndIf 
End

Posted: Wed Feb 08, 2006 8:04 am
by Fangbeast
Too much late night coding eh sparkie? "Image" is exactly what he asked for (ROFLMAO).

/me goes hunting the forums, was sure there was an example somewhere

Posted: Wed Feb 08, 2006 1:57 pm
by dontmailme
Fangbeast wrote:Too much late night coding eh sparkie? "Image" is exactly what he asked for (ROFLMAO).

/me goes hunting the forums, was sure there was an example somewhere
No need to do that Fangie!

Sparkie hit the nail on the head :D

That's exactly what I want !!!!!!! Even though I didn't know it, somehow sparkie did ;)

He's too good, you know :)

Posted: Wed Feb 08, 2006 2:09 pm
by Fangbeast
Yes, you are right, Us poor humans have to bathe in his reflected wisdom and glory:(

Posted: Wed Feb 08, 2006 2:14 pm
by Sparkie
@Fangles:
dontmailme wrote:...Unless anyone has an easier way to paint coloured text into a listicon gadget ?
Seemed easy enough to me. :D

...

...

...

...

Well ok, maybe not as easy as using an image. :P

Posted: Wed Feb 08, 2006 2:18 pm
by Sparkie
@dontmailme: Glad to hear it's what you were looking for. I was afraid the code was more for me than for you. ;)

Posted: Wed Feb 08, 2006 2:27 pm
by Sparkie
Fangles wrote:...bathe in his reflected wisdom and glory
Sorry Fangles, but the only other person I bathe is my wife. :D


Side note: Damn I'm slow on this dial-up account. No DSL for me this week :cry: as I'm house sitting for my inlaws. Old wiring = many reconnects. :evil:

Posted: Wed Feb 08, 2006 2:28 pm
by Dare2
:D

Posted: Thu Feb 09, 2006 12:56 am
by dontmailme
@Sparkie, or another bright spark!

The example works fine, but there one small issue :(

If you set a different brush colour, say grey ... you can then see that the non text parts of the listicongadget are still black.

It's even more noticable if there are less rows of text than the listicongadget can show.

I would like to remove this 'border', but need some help!

I'm sure it's simple, but I cannot see it :oops:

Posted: Thu Feb 09, 2006 1:04 am
by Sparkie
Try changing the background color to match the brush. Line 160 of my original code is where the background color is set. ;)

Code: Select all

SendMessage_(GadgetID(#ListIcon1), #LVM_SETBKCOLOR, 0, same_color_as_brush)

Posted: Thu Feb 09, 2006 2:45 am
by dontmailme
Knew it was simple ;)

But not that simple :roll:

Thanks again :D

Posted: Sat Oct 13, 2007 2:17 am
by PB
Modified by myself for v4.10 B3:

Code: Select all

; ************************************************************************
; Code:   Multicolor Text in ListIconGadget
; Author: Sparkie
; Date:   February 07, 2006
; OS:     Windows only
; PB ver: 3.94
; Notes:  Modified for v4.10 B3 on 13 Oct 2007 by PB.
; ************************************************************************
; ########################################
; Window constants
; ########################################
Enumeration
  #WindowMain = 1
EndEnumeration
; ########################################
; Gadget constants
; ########################################
Enumeration
  #ListIcon1 = 1
  #Button1
EndEnumeration

; ########################################
; ListIconGadget NMLVCUSTOMDRAW constants
; ########################################
#LVM_GETSUBITEMRECT = #LVM_FIRST + 56
#CDDS_ITEM = $10000
#CDDS_POSTERASE = 4
#CDDS_POSTPAINT = 2
#CDDS_PREERASE = 3
#CDDS_PREPAINT = 1
#CDDS_ITEMPOSTERASE = #CDDS_ITEM | #CDDS_POSTERASE
#CDDS_ITEMPOSTPAINT = #CDDS_ITEM | #CDDS_POSTPAINT
#CDDS_ITEMPREERASE = #CDDS_ITEM | #CDDS_PREERASE
#CDDS_ITEMPREPAINT = #CDDS_ITEM | #CDDS_PREPAINT
#CDDS_SUBITEM = $20000
#CDRF_DODEFAULT = 0
#CDRF_NOTIFYITEMDRAW = $20
#CDRF_NOTIFYPOSTERASE = $40
#CDRF_NOTIFYPOSTPAINT = $10
#CDRF_NOTIFYSUBITEMDRAW = $20
#CDRF_SKIPDEFAULT = 4
; //////////////////////////////////////////
; Array to hold character colors
; //////////////////////////////////////////
Global Dim charColor(255)
; //////////////////////////////////////////
; Global brush for ListIcon background
; //////////////////////////////////////////
Global blackBrush
blackBrush = GetStockObject_(#BLACK_BRUSH)
; //////////////////////////////////////////
; Procedure to create random text colors
; //////////////////////////////////////////
Procedure CreateRandomColors()
  For char = 0 To 255
    ; ..........................................................
    ; I'll keep the RGB values between 100 and 255 for brighness
    ; ..........................................................
    charColor(char) = RGB(Random(155)+100, Random(155)+100, Random(155)+100)
  Next char
EndProcedure
; //////////////////////////////////////////
; Procedure to get character width
; //////////////////////////////////////////
Procedure GetCharWidth(hListIcon, char$)
  charwidth = SendMessage_(hListIcon, #LVM_GETSTRINGWIDTH, 0, @char$)
  ProcedureReturn charwidth
EndProcedure
; //////////////////////////////////////////
; Procedure for changing text colors
; //////////////////////////////////////////
Procedure ChangeColors()
  CreateRandomColors()
  SendMessage_(GadgetID(#ListIcon1), #LVM_REDRAWITEMS, 0, 11)
EndProcedure
; //////////////////////////////////////////
; Main window callback
; //////////////////////////////////////////
Procedure WinCallback(hwnd, msg, wparam, lparam)
  result = #PB_ProcessPureBasicEvents
  Select msg
    Case #WM_NOTIFY
      *nmhdr.NMHDR = lparam
      If *nmhdr\code = #NM_CUSTOMDRAW And *nmhdr\hwndFrom = GadgetID(#ListIcon1)
        *lvCD.NMLVCUSTOMDRAW = lparam
        ; ...................................................
        ; --> Make sure text background is always transparent
        ; ...................................................
        SetBkMode_(*lvCD\nmcd\hdc, #TRANSPARENT)
        Select *lvCD\nmcd\dwDrawStage
          Case #CDDS_PREPAINT
            result = #CDRF_NOTIFYITEMDRAW
          Case #CDDS_ITEMPREPAINT
            result = #CDRF_NOTIFYSUBITEMDRAW
          Case #CDDS_ITEMPREPAINT | #CDDS_SUBITEM
            result = #CDRF_NOTIFYPOSTPAINT
          Case #CDDS_ITEMPOSTPAINT | #CDDS_SUBITEM
            If *lvCD\nmcd\dwItemSpec > -1 And  *lvCD\iSubItem > -1
              ; ................................................
              ; --> Get item text
              ; ................................................
              item$ = GetGadgetItemText(#ListIcon1, *lvCD\nmcd\dwItemSpec, *lvCD\iSubItem)
              ; ................................................
              ; --> Get item rect
              ; ................................................
              subItemRc.RECT\left = #LVIR_LABEL
              subItemRc\top = *lvCD\iSubItem
              SendMessage_(*lvCD\nmcd\hdr\hwndFrom, #LVM_GETSUBITEMRECT, *lvCD\nmcd\dwItemSpec, @subItemRc)
              ; ................................................
              ; --> Fill item rect with our brush color (black)
              ; ................................................
              FillRect_(*lvCD\nmcd\hdc, subItemRc, blackBrush)
              ; ................................................
              ; --> Adjust left margin
              ; ................................................
              If *lvCD\iSubItem = 0
                subItemRc\left + (GetSystemMetrics_(#SM_CXEDGE) * 3) - 2
              Else
                subItemRc\left + GetSystemMetrics_(#SM_CXEDGE) * 3
              EndIf
              ; ................................................
              ; --> Colorize each character and draw it
              ; ................................................
              For char = 1 To Len(item$)
                char$ = Mid(item$, char, 1)
                ; ........................................................
                ; --> I am adding + *lvCD\nmcd\dwItemSpec + *lvCD\iSubItem
                ;     only for variety of colors, so this is optional
                ; ........................................................
                SetTextColor_(*lvCD\nmcd\hdc, charColor(Asc(char$) + *lvCD\nmcd\dwItemSpec + *lvCD\iSubItem))
                DrawText_(*lvCD\nmcd\hdc, char$, 1, subItemRc, #DT_NOCLIP)
                ; ........................................................
                ; --> Get the current character width (pixels) and move
                ;     the drawing rect\left for the next character.
                ;     I am adding + *lvCD\nmcd\dwItemSpec + *lvCD\iSubItem
                ;     only for increased spacing, so this is optional
                ; ........................................................
                subItemRc\left + GetCharWidth(*nmhdr\hwndFrom, char$) + *lvCD\nmcd\dwItemSpec + *lvCD\iSubItem
              Next char
            EndIf
            result = #CDRF_SKIPDEFAULT
        EndSelect
      EndIf
  EndSelect
  ProcedureReturn result
EndProcedure
; //////////////////////////////////////////
; Main Window
; //////////////////////////////////////////
If OpenWindow(#WindowMain, 0, 0, 620, 235, "Sparkies Multicolor ListIconGadget", #PB_Window_SystemMenu) And CreateGadgetList(WindowID(#WindowMain))
  SetWindowCallback(@WinCallback())
  ListIconGadget(#ListIcon1, 5, 5, 610, 195, "Column 0", 270, #PB_ListIcon_AlwaysShowSelection | #PB_ListIcon_FullRowSelect)
  ButtonGadget(#Button1, 260, 205, 100, 25, "Change colors")
  ; ................................................
  ; --> Uncomment next line if text shadowing occurs
  ;     that will make text invisible (text color on back color)
  ; ................................................
  ;SendMessage_(GadgetID(0), #LVM_SETTEXTCOLOR, 0, #Black)
  SendMessage_(GadgetID(#ListIcon1), #LVM_SETBKCOLOR, 0, #Black)
  ; ................................................
  ; --> Change font is optional
  ; ................................................
  hCourierNew = LoadFont(0, "Courier New", 10, #PB_Font_Bold)
  SetGadgetFont(0, hCourierNew)
  ; ................................................
  ; --> Add our ListIcon items
  ; ................................................
  AddGadgetColumn(#ListIcon1, 1, "Column 1", 335)
  For i = 0 To 11
    AddGadgetItem(#ListIcon1, -1, "Experience the " + Chr(10) + "Power of PureBasic")
  Next
  ; ................................................
  ; --> Create random text color
  ; ................................................
  CreateRandomColors()
  ; //////////////////////////////////////////
  ; Main window event loop
  ; //////////////////////////////////////////
  Repeat
    event = WaitWindowEvent()
    If event = #PB_Event_Gadget And EventGadget() = #Button1
      ChangeColors()
    EndIf
  Until event = #PB_Event_CloseWindow
  ; ................................................
  ; Optional for GetStockObject
  ; ................................................
  DeleteObject_(blackBrush)
EndIf

Posted: Sat Oct 13, 2007 2:40 am
by Sparkie
Thanks PB :)

Posted: Sat Oct 13, 2007 3:28 am
by PB
No problem. I needed it for my own app, but I'm having trouble converting it
for my own app. Below is what I want do to do; I want both "THIS" words to
be in red. Any chance you can help? :)

Code: Select all

If OpenWindow(0,200,200,250,120,"test",#PB_Window_SystemMenu)
  CreateGadgetList(WindowID(0))
  ListIconGadget(0,10,10,200,100,"test",190)
  AddGadgetItem(0,-1,"I'd like THIS and THIS to be red.")
  Repeat : Until WaitWindowEvent()=#PB_Event_CloseWindow
EndIf