Page 2 of 4

Posted: Sat Oct 13, 2007 3:41 am
by Sparkie
Let me see what I can come with. :)

Posted: Sat Oct 13, 2007 4:19 am
by PB
Just to prove I've been trying and not being lazy by asking you to do it, here
is a cut-down version of your code that ALMOST does what I want, but the
red text seems to be about 2 pixels to the left, and I haven't been able to
successfully move it those 2 pixels to the right. I'm probably overlooking
the obvious, but I've been at this for about an hour now with no luck. :(

Code: Select all

Enumeration
  #WindowMain=1
EndEnumeration

Enumeration
  #ListIcon1=1
  #Button1
EndEnumeration

#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

Procedure GetCharWidth(hListIcon,char$)
  ProcedureReturn SendMessage_(hListIcon,#LVM_GETSTRINGWIDTH,0,@char$)
EndProcedure

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
        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
              item$=GetGadgetItemText(#ListIcon1,*lvCD\nmcd\dwItemSpec,*lvCD\iSubItem)
              subItemRc.RECT\left=#LVIR_LABEL : subItemRc\top=*lvCD\iSubItem
              SendMessage_(*lvCD\nmcd\hdr\hwndFrom,#LVM_GETSUBITEMRECT,*lvCD\nmcd\dwItemSpec,@subItemRc)
              For char=1 To Len(item$)
                zz=#Black : If (char>7 And char<12) Or (char>16 And char<22) : zz=#Red : EndIf
                char$=Mid(item$,char,1) : SetTextColor_(*lvCD\nmcd\hdc,zz) : DrawText_(*lvCD\nmcd\hdc,char$,1,subItemRc,#DT_NOCLIP)
                subItemRc\left+GetCharWidth(*nmhdr\hwndFrom,char$) + *lvCD\nmcd\dwItemSpec + *lvCD\iSubItem
              Next char
            EndIf
            result=#CDRF_SKIPDEFAULT
        EndSelect
      EndIf
  EndSelect
  ProcedureReturn result
EndProcedure

If OpenWindow(#WindowMain,200,200,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)
  AddGadgetItem(#ListIcon1,-1,"I want THIS and THIS to be red")
  Repeat : Until WaitWindowEvent()=#PB_Event_CloseWindow
EndIf

Posted: Sat Oct 13, 2007 4:29 am
by Sparkie
Try adding this after creating the ListIconGadget. I will try to find a better answer ASAP. ;)

Code: Select all

SendMessage_(GadgetID(#ListIcon1), #LVM_SETTEXTCOLOR, 0, #White)

Posted: Sat Oct 13, 2007 4:36 am
by Sparkie
hmmm...not sure why I was doing all the fancy work in the #CDDS_ITEMPOSTPAINT|#CDDS_SUBITEM portion but try this. It does the work in the #CDDS_ITEMPREPAINT portion. No need for the above mentioned #LVM_SETTEXTCOLOR

Code: Select all

Enumeration 
  #WindowMain=1 
EndEnumeration 

Enumeration 
  #ListIcon1=1 
  #Button1 
EndEnumeration 

#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 

Procedure GetCharWidth(hListIcon,char$) 
  ProcedureReturn SendMessage_(hListIcon,#LVM_GETSTRINGWIDTH,0,@char$) 
EndProcedure 

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 
        SetBkMode_(*lvCD\nmcd\hdc,#TRANSPARENT) 
        Select *lvCD\nmcd\dwDrawStage 
          Case #CDDS_PREPAINT 
            result=#CDRF_NOTIFYITEMDRAW 
          Case #CDDS_ITEMPREPAINT 
            If *lvCD\nmcd\dwItemSpec>-1 And *lvCD\iSubItem>-1 
              item$=GetGadgetItemText(#ListIcon1,*lvCD\nmcd\dwItemSpec,*lvCD\iSubItem) 
              subItemRc.RECT\left=#LVIR_LABEL : subItemRc\top=*lvCD\iSubItem 
              SendMessage_(*lvCD\nmcd\hdr\hwndFrom,#LVM_GETSUBITEMRECT,*lvCD\nmcd\dwItemSpec,@subItemRc) 
              For Char=1 To Len(item$) 
                zz=#Black : If (Char>7 And Char<12) Or (Char>16 And Char<22) : zz=#Red : EndIf 
                char$=Mid(item$,Char,1) : SetTextColor_(*lvCD\nmcd\hdc,zz) : DrawText_(*lvCD\nmcd\hdc,char$,1,subItemRc,#DT_NOCLIP) 
                subItemRc\left+GetCharWidth(*nmhdr\hwndFrom,char$) + *lvCD\nmcd\dwItemSpec + *lvCD\iSubItem 
              Next Char 
            EndIf 
            result=#CDRF_SKIPDEFAULT;#CDRF_NOTIFYSUBITEMDRAW 
          Case #CDDS_ITEMPREPAINT|#CDDS_SUBITEM 
            result=#CDRF_NOTIFYPOSTPAINT 
        EndSelect 
      EndIf 
  EndSelect 
  ProcedureReturn result 
EndProcedure 

If OpenWindow(#WindowMain,200,200,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) 
  AddGadgetItem(#ListIcon1,-1,"I want THIS and THIS to be red") 
  Repeat : Until WaitWindowEvent()=#PB_Event_CloseWindow 
EndIf 

Posted: Sat Oct 13, 2007 4:48 am
by PB

Code: Select all

SendMessage_(GadgetID(#ListIcon1), #LVM_SETTEXTCOLOR, 0, #White)
For viewing it's fine, but if I click the item then it goes wrong again. :)

As for your updated example, I can't click the item at all?

Posted: Sat Oct 13, 2007 4:57 am
by Sparkie
Sorry PB, it's past my bedtime. :cry:

I added line 52 subItemRc\left + 2 and it seems to work. Must be a border issue. I can take a closer look tomorrow is necessary. :)

Code: Select all

Enumeration 
  #WindowMain=1 
EndEnumeration 

Enumeration 
  #ListIcon1=1 
  #Button1 
EndEnumeration 

#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 

Procedure GetCharWidth(hListIcon,char$) 
  ProcedureReturn SendMessage_(hListIcon,#LVM_GETSTRINGWIDTH,0,@char$) 
EndProcedure 

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 
        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 
              item$=GetGadgetItemText(#ListIcon1,*lvCD\nmcd\dwItemSpec,*lvCD\iSubItem) 
              subItemRc.RECT\left=#LVIR_LABEL : subItemRc\top=*lvCD\iSubItem 
              SendMessage_(*lvCD\nmcd\hdr\hwndFrom,#LVM_GETSUBITEMRECT,*lvCD\nmcd\dwItemSpec,@subItemRc) 
              subItemRc\left + 2
              For Char=1 To Len(item$) 
                zz=#Black : If (Char>7 And Char<12) Or (Char>16 And Char<22) : zz=#Red : EndIf 
                char$=Mid(item$,Char,1) : SetTextColor_(*lvCD\nmcd\hdc,zz) : DrawText_(*lvCD\nmcd\hdc,char$,1,subItemRc,#DT_NOCLIP) 
                subItemRc\left+GetCharWidth(*nmhdr\hwndFrom,char$) + *lvCD\nmcd\dwItemSpec + *lvCD\iSubItem 
              Next Char 
            EndIf 
            result=#CDRF_SKIPDEFAULT 
        EndSelect 
      EndIf 
  EndSelect 
  ProcedureReturn result 
EndProcedure 

If OpenWindow(#WindowMain,200,200,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) 
  AddGadgetItem(#ListIcon1,-1,"I want THIS and THIS to be red") 
  Repeat : Until WaitWindowEvent()=#PB_Event_CloseWindow 
EndIf 

Posted: Sat Oct 13, 2007 5:06 am
by Fluid Byte
Sorry but where does this code draws images? Maybe I'm to blind to see because of all the

Code: Select all

; //////////////////////////////////////////
and

Code: Select all

; ...................................................
Seriously, I can't read it. I get totally dizzy.

Posted: Sat Oct 13, 2007 5:12 am
by Sparkie
Read all the posts Fluid Byte, starting from the beginning :wink:

Posted: Sat Oct 13, 2007 5:31 am
by PB
> I can take a closer look tomorrow

It's okay; it works fine now. Good job! I owe you many beers. :D

Here is your code stripped down even more, but still working just fine.

Code: Select all

Procedure GetCharWidth(gad,c$)
  ProcedureReturn SendMessage_(gad,#LVM_GETSTRINGWIDTH,0,@c$)
EndProcedure

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(0)
        *lvCD.NMLVCUSTOMDRAW=lParam
        Select *lvCD\nmcd\dwDrawStage
          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
              item$=GetGadgetItemText(0,*lvCD\nmcd\dwItemSpec,*lvCD\iSubItem)
              subItemRc.RECT\left=#LVIR_LABEL : subItemRc\top=*lvCD\iSubItem
              SendMessage_(*lvCD\nmcd\hdr\hwndFrom,#LVM_GETSUBITEMRECT,*lvCD\nmcd\dwItemSpec,@subItemRc)
              subItemRc\left+2
              For c=1 To Len(item$)
                zz=#Black : If (c>7 And c<12) Or (c>16 And c<22) : zz=#Red : EndIf
                c$=Mid(item$,c,1) : SetTextColor_(*lvCD\nmcd\hdc,zz) : DrawText_(*lvCD\nmcd\hdc,c$,1,subItemRc,#DT_NOCLIP)
                subItemRc\left+GetCharWidth(*nmhdr\hwndFrom,c$) + *lvCD\nmcd\dwItemSpec + *lvCD\iSubItem
              Next
            EndIf
        EndSelect
      EndIf
  EndSelect
  ProcedureReturn result
EndProcedure

If OpenWindow(0,200,200,620,235,"Sparkies Multicolor ListIconGadget",#PB_Window_SystemMenu) And CreateGadgetList(WindowID(0))
  SetWindowCallback(@WinCallback())
  ListIconGadget(0,5,5,610,195,"Column 0",270,#PB_ListIcon_AlwaysShowSelection|#PB_ListIcon_FullRowSelect)
  AddGadgetItem(0,-1,"I want THIS and THIS to be red")
  Repeat : Until WaitWindowEvent()=#PB_Event_CloseWindow
EndIf

Posted: Sat Oct 13, 2007 11:57 am
by PB
Actually, just to be a pain: your code only colors the first item in a list. :?
I've tried to make it work with others but nothing. Any ideas? Thanks mate.

Posted: Sat Oct 13, 2007 1:12 pm
by srod
Had a little tinker with your code.

The thing is that if you are returning #CDRF_SKIPDEFAULT in a pre-paint notification (as you need to do with this code of yours) then you must take steps to erase the background of each item if you are to allow item selection etc.

REMOVED whilst making changes.

Posted: Sat Oct 13, 2007 1:33 pm
by srod
Further to my previous post, you get very strange effects if you add extra columns with the spacing between characters. This is because of the custom spacing you employ.

Because of this, it's best if you custom draw all the text in the control etc.

Consequently I really have to take charge of showing the selction box etc.

You'll need to add extra logic if you require multi-select etc.

Code: Select all

Procedure GetCharWidth(gad,c$) 
  ProcedureReturn SendMessage_(gad,#LVM_GETSTRINGWIDTH,0,@c$) 
EndProcedure 

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(0) 
        *lvCD.NMLVCUSTOMDRAW=lParam 
        Select *lvCD\nmcd\dwDrawStage 
          Case #CDDS_ITEMPREPAINT 
            result=#CDRF_NOTIFYSUBITEMDRAW 
          Case #CDDS_ITEMPREPAINT|#CDDS_SUBITEM 
            result=#CDRF_SKIPDEFAULT
            If *lvCD\nmcd\dwItemSpec>-1 And *lvCD\iSubItem>-1
              item$=GetGadgetItemText(0,*lvCD\nmcd\dwItemSpec,*lvCD\iSubItem) 
              subItemRc.RECT\left=#LVIR_LABEL : subItemRc\top=*lvCD\iSubItem 
              SendMessage_(*lvCD\nmcd\hdr\hwndFrom,#LVM_GETSUBITEMRECT,*lvCD\nmcd\dwItemSpec,@subItemRc) 
              If GetGadgetState(0)<>*lvCD\nmcd\dwItemSpec
                FillRect_(*lvCD\nmcd\hdc, subItemRc, GetStockObject_(#WHITE_BRUSH))
              Else
                hBrush = CreateSolidBrush_(GetSysColor_(#COLOR_HIGHLIGHT))
                  FillRect_(*lvCD\nmcd\hdc, subItemRc, hBrush)
                DeleteObject_(hBrush)
              EndIf
              For c=1 To Len(item$) 
                zz=#Black : If (c>7 And c<12) Or (c>16 And c<22) : zz=#Red : EndIf 
                c$=Mid(item$,c,1) : SetTextColor_(*lvCD\nmcd\hdc,zz) : DrawText_(*lvCD\nmcd\hdc,c$,1,subItemRc,#DT_NOCLIP) 
                subItemRc\left+GetCharWidth(*nmhdr\hwndFrom,c$) + *lvCD\iSubItem
              Next 
            EndIf 
        EndSelect 
      EndIf 
  EndSelect 
  ProcedureReturn result 
EndProcedure 

If OpenWindow(0,200,200,620,235,"Sparkies Multicolor ListIconGadget",#PB_Window_SystemMenu) And CreateGadgetList(WindowID(0)) 
  SetWindowCallback(@WinCallback()) 
  ListIconGadget(0,5,5,610,195,"Column 0",270,#PB_ListIcon_AlwaysShowSelection|#PB_ListIcon_FullRowSelect) 
  AddGadgetColumn(0,1,"ll",110)
  AddGadgetItem(0,-1,"I want THIS and THIS to be red"+Chr(10)+"kk") 
  AddGadgetItem(0,-1,"I want THIS and THIS to be red") 
  AddGadgetItem(0,-1,"I want THIS and THIS to be red") 
  AddGadgetItem(0,-1,"I want THIS and THIS to be red") 
  Repeat : Until WaitWindowEvent()=#PB_Event_CloseWindow 
EndIf 

Posted: Sat Oct 13, 2007 1:39 pm
by Sparkie
I still can't remember why I handled this in the post paint process. :? I thought this code was based on my multiline item ListIconGadget code, which handles all drawing, including selected and focused items, in pre-paint and post-paint process.

I'm on my way out to walk the dog so I'll let srod take over whilst I'm gone :)

Posted: Sat Oct 13, 2007 1:46 pm
by srod
Sparkie wrote:I still can't remember why I handled this in the post paint process. :? I thought this code was based on my multiline item ListIconGadget code, which handles all drawing, including selected and focused items, in pre-paint and post-paint process.

I'm on my way out to walk the dog so I'll let srod take over whilst I'm gone :)
...knowing that you'll need to repair all the damage done by that idiot srod when you return!

:)

Posted: Sat Oct 13, 2007 2:33 pm
by Sparkie
The only damage I see thus far is the damage to my brain. In my original code I think I was being lazy by drawing in postpaint. Why else would I try to draw text on top of text rather than on top of a blank background :oops:

@PB: I'll redo the code properly and post when it's done :)