SetGadgetItemColor doesn't work after windowcallback code

Just starting out? Need help? Post your questions and find answers here.
User avatar
Fangbeast
PureBasic Protozoa
PureBasic Protozoa
Posts: 4790
Joined: Fri Apr 25, 2003 3:08 pm
Location: Not Sydney!!! (Bad water, no goats)

SetGadgetItemColor doesn't work after windowcallback code

Post by Fangbeast »

Finally!! After years of wondering, I accidentally disabled my main SetWindowCallback(@MainWindowCallback()) and my SetGadgetItemColor started working again.

Prior to that, no combination of SetGadgetItemColor would work anywhere in my code.

Now that I know what killed it, I still don't know how to fix it.

Could someone smart person look over my window callback code and maybe suggest how I can prevent it from killing my colouring?

Code: Select all

Procedure MainWindowCallback(hWnd, uMsg, wParam, lParam)
  
  Result = #PB_ProcessPureBasicEvents
  
  ; Netmaestro's windowsnap code

  Static Snapped1.i, Snapped2.i, Snapped3.i, Snapped4.i
  
  Select uMsg

    ; Netmaestro's windowsnap code
    
    Case #WM_MOVING
      
      If Toggle\ScreenSnap = 1
        *view.RECT = lparam
        curwidth  = *view\right - *view\left
        curheight = *view\bottom - *view\top
        If AutoSnap                                                                         ; AutoSnap Section
          If *view\left < SnapD
            If Not Snapped1
              *view\left = 0
              *view\right = curwidth
              snapped1 = #True
              ReturnValue = #True
            EndIf
          Else
            snapped1 = #False
          EndIf
          If *view\top < SnapD
            If Not Snapped2
              *view\top = 0
              *view\bottom = curheight
              snapped2 = #True
              ReturnValue = #True
            EndIf
          Else
            snapped2 = #False
          EndIf
          If *view\right > screenw - SnapD
            If Not Snapped3
              *view\left  = ScreenW - curwidth
              *view\right = screenW
              snapped3 = #True
              ReturnValue = #True
            EndIf
          Else
            snapped3 = #False
          EndIf     
          If *view\bottom > screenH - SnapD
            If Not Snapped4
              *view\top = screenH - curheight
              *view\bottom = screenH
              snapped4 = #True
              ReturnValue = #True
            EndIf
          Else
            snapped4 = #False
          EndIf     
        EndIf
        If *view\top < 0                                                                    ;  Inside Desktop Section
          *view\top = 0
          *view\bottom = curheight
        EndIf
        If *view\left < 0 
          *view\left = 0
          *view\right = curwidth
        EndIf
        If *view\right > screenW
          *view\right = screenW
          *view\left = *view\right - curwidth
        EndIf
        If *view\bottom > screenH
          *view\bottom = screenH
          *view\top = *view\bottom - curheight
        EndIf
        MoveWindow_(WindowID, *view\left, *view\top, *view\right - *view\left, *view\bottom - *view\top, #True)
        ReturnValue = #True
      EndIf
      
      ; Draw a line through an item to indicate its deleted state
    
    Case #WM_NOTIFY
    
      *nmhdr.NMHDR = lParam
      
      *lvCD.NMLVCUSTOMDRAW = lParam
      
      If IsGadget(#Gadget_MyInfo_Titles)
        If *lvCD\nmcd\hdr\hwndFrom = GadgetID(#Gadget_MyInfo_Titles) And *lvCD\nmcd\hdr\code = #NM_CUSTOMDRAW
          Select *lvCD\nmcd\dwDrawStage
            Case #CDDS_PREPAINT
              result = #CDRF_NOTIFYITEMDRAW
            Case #CDDS_ITEMPREPAINT
              result = #CDRF_NOTIFYSUBITEMDRAW;
            Case #CDDS_ITEMPREPAINT | #CDDS_SUBITEM
              thisRow = *lvCD\nmcd\dwItemSpec
              thisCol = *lvCD\iSubItem
              on_off = GetGadgetItemData(#Gadget_MyInfo_Titles, thisRow)
              ; If thisCol = 0 And on_off. Specifically for column 0. You can change this to any or just use on_off to set all columns
              If on_off
                SelectObject_(*lvCD\nmcd\hdc, FontID(#FontStrikeoutYes))
                result = #CDRF_NEWFONT; | #CDRF_DODEFAULT
              Else
                SelectObject_(*lvCD\nmcd\hdc, FontID(#FontStrikeoutNo))
                result = #CDRF_NEWFONT   
              EndIf
              
              ; Proper colour banding in listicons. This would have worked in main code with SetGadgetItemColor
              ; if something else in this callback didn't kill it.
              
              If Toggle\ColourBand = #True  ;<-----------Add This Block (Paul Leischow)
                If (thisRow / 2) * 2 = thisRow
                  ;*lvCD\clrText   = $000000
                  ;*lvCD\clrTextBk = $D4D4D4
                  *lvCD\clrText   = $000000
                  *lvCD\clrTextBk = $EEEEEE
                Else
                  ;*lvCD\clrText   = $FFFFFF
                  ;*lvCD\clrTextBk = $C1C1C1
                  *lvCD\clrText   = $484848
                  *lvCD\clrTextBk = $DADADA
                EndIf
              EndIf
              
          EndSelect
          
        EndIf
        
      EndIf
      
  EndSelect ; uMsg

  ProcedureReturn Result
  
EndProcedure
Amateur Radio/VK3HAF, (D-STAR/DMR and more), Arduino, ESP32, Coding, Crochet
User avatar
mk-soft
Always Here
Always Here
Posts: 6249
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

Re: SetGadgetItemColor doesn't work after windowcallback cod

Post by mk-soft »

What does your GadgetCallback look like?
It is important in which order and with which return value these are executed.

Your own callback may not always call the previous callback. This would lead to double processing of the event and thus overwrite your own processing.

P.S.
The same is true for WindowCallback.
It does not always return '#PB_ProcessPureBasicEvents'.
For some events a True must be returned to confirm that the event would be processed.

Short Example with RichEditCallback...

Code: Select all

;-TOP

; Comment : Module SetGadgetCallback (Windows Only)
; Author  : mk-soft
; Version : v0.02
; Created : 10.06.2018
; Updated : 
; Link    : https://www.purebasic.fr/english/viewtopic.php?f=12&t=70842
;
; Syntax Callback:
;           Procedure GadgetCB(hWnd,uMsg,wParam,lParam)
;             Select uMsg
;               ;TODO
;             EndSelect
;             ; Call previous gadget procedure
;             ProcedureReturn CallGadgetProc(hWnd,uMsg,wParam,lParam)
;           EndProcedure
;
; *****************************************************************************

DeclareModule GadgetCallback
  
  Declare SetGadgetCallback(Gadget, *lpNewFunc) 
  Declare CallGadgetProc(hWnd, uMsg, wParam, lParam)
  
EndDeclareModule

Module GadgetCallback
  
  EnableExplicit
  
  Global NewMap *lpPrevFunc()
  Global MutexCB = CreateMutex()
  
  ; ---------------------------------------------------------------------------
  
  Procedure SetGadgetCallback(Gadget, *lpNewFunc)
    Protected GadgetID, GadgetKey.s
    
    GadgetID = GadgetID(Gadget)
    GadgetKey = Hex(GadgetID)
    
    ; Remove exists Callback
    If FindMapElement(*lpPrevFunc(), GadgetKey)
      SetWindowLongPtr_(GadgetID, #GWL_WNDPROC, *lpPrevFunc())
      DeleteMapElement(*lpPrevFunc())
    EndIf
    
    If *lpNewFunc
      If AddMapElement(*lpPrevFunc(), GadgetKey)
        *lpPrevFunc() = SetWindowLongPtr_(GadgetID, #GWL_WNDPROC, *lpNewFunc)
        ProcedureReturn *lpPrevFunc()
      EndIf
    EndIf
    
    ProcedureReturn 0
    
  EndProcedure
  
  ; ---------------------------------------------------------------------------
  
  Procedure CallGadgetProc(hWnd, uMsg, wParam, lParam)
    Protected result
    
    LockMutex(MutexCB)
    If FindMapElement(*lpPrevFunc(), Hex(hWnd))
      result = CallWindowProc_(*lpPrevFunc(), hWnd, uMsg, wParam, lParam)
    EndIf
    UnlockMutex(MutexCB)
    
    ProcedureReturn result
    
  EndProcedure
  
EndModule

; *****************************************************************************

; Example

CompilerIf #PB_Compiler_IsMainFile
  
  UseModule GadgetCallback
  
  Procedure RichEditProc(hWnd,uMsg,wParam,lParam)
    Select uMsg
      Case #WM_KEYDOWN
        Select wParam
          Case #VK_DELETE
            ;ProcedureReturn 1
          Case #VK_BACK
            ;ProcedureReturn 1
        EndSelect
        
      Case #WM_CHAR
        Select wParam
          Case #VK_TAB
            SetFocus_(GetWindow_(hWnd,#GW_HWNDNEXT))
            ProcedureReturn 1
        EndSelect
        
    EndSelect
    ProcedureReturn CallGadgetProc(hWnd,uMsg,wParam,lParam)
  EndProcedure
  
  If OpenWindow(0,0,0,740,250,"Example SetGadgetCallback",#PB_Window_SystemMenu|#PB_Window_ScreenCentered)
    EditorGadget(1,10,10,230,200)
    EditorGadget(2,250,10,230,200)
    EditorGadget(3,490,10,230,200)
    
    SetGadgetCallback(1, @RichEditProc())
    SetGadgetCallback(2, @RichEditProc())
    SetGadgetCallback(3, @RichEditProc())
    
    ; SetGadgetCallback(1, 0)
    ; SetGadgetCallback(2, 0)
    
    Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow
  EndIf
  
CompilerEndIf
My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
User avatar
Fangbeast
PureBasic Protozoa
PureBasic Protozoa
Posts: 4790
Joined: Fri Apr 25, 2003 3:08 pm
Location: Not Sydney!!! (Bad water, no goats)

Re: SetGadgetItemColor doesn't work after windowcallback cod

Post by Fangbeast »

What does your GadgetCallback look like?
Hello, thanks for looking into this. There is no actual separate gadget callback. The WindowCallback on line 178 intercepts the Case #WM_NOTIFY flag on the #Gadget_MyInfo_Titles on the main form (A ListIconGadget) in order to be able to draw a line through a column of text. (I use it to indicate a deleted item).

If I rip out all other sections of code, that is the exact block of code that is causing the problem. Let me show you the stripped down version.

Code: Select all

Procedure MainWindowCallback(hWnd, uMsg, wParam, lParam)
  
  Result = #PB_ProcessPureBasicEvents
    
      ; Draw a line through an item to indicate its deleted state
    
    Case #WM_NOTIFY
    
      *nmhdr.NMHDR = lParam
      
      *lvCD.NMLVCUSTOMDRAW = lParam
      
      If IsGadget(#Gadget_MyInfo_Titles)
        If *lvCD\nmcd\hdr\hwndFrom = GadgetID(#Gadget_MyInfo_Titles) And *lvCD\nmcd\hdr\code = #NM_CUSTOMDRAW
          Select *lvCD\nmcd\dwDrawStage
            Case #CDDS_PREPAINT
              result = #CDRF_NOTIFYITEMDRAW
            Case #CDDS_ITEMPREPAINT
              result = #CDRF_NOTIFYSUBITEMDRAW;
            Case #CDDS_ITEMPREPAINT | #CDDS_SUBITEM
              thisRow = *lvCD\nmcd\dwItemSpec
              thisCol = *lvCD\iSubItem
              on_off = GetGadgetItemData(#Gadget_MyInfo_Titles, thisRow)
              ; If thisCol = 0 And on_off. Specifically for column 0. You can change this to any or just use on_off to set all columns
              If on_off
                SelectObject_(*lvCD\nmcd\hdc, FontID(#FontStrikeoutYes))
                result = #CDRF_NEWFONT; | #CDRF_DODEFAULT
              Else
                SelectObject_(*lvCD\nmcd\hdc, FontID(#FontStrikeoutNo))
                result = #CDRF_NEWFONT   
              EndIf
          EndSelect
        EndIf
      EndIf
  EndSelect ; uMsg
  
  ProcedureReturn Result
  
EndProcedure

It is important in which order and with which return value these are executed.
I understand what you say but I lack the windows api skill to know what to do about this, sorry.
Your own callback may not always call the previous callback.
As mentioned above, there is no other callback operating for this gadget. And no other callbacks for the current code.
It does not always return '#PB_ProcessPureBasicEvents'.
Even though it was defined at the top of the code already? I think I see what you mean though but what do I do? I realise now that the result = #PB_ProcessPureBasicEvents as defined at the top is replaced by the result in the custom draw routine so the SetGadgetItemColor is never processed right?

What do I do about it?
Amateur Radio/VK3HAF, (D-STAR/DMR and more), Arduino, ESP32, Coding, Crochet
User avatar
mk-soft
Always Here
Always Here
Posts: 6249
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

Re: SetGadgetItemColor doesn't work after windowcallback cod

Post by mk-soft »

Info
Module SetGadgetCallback for Gadgets does the same us SetWindowCallback for Windows;)

Its work

Code: Select all

EnableExplicit

#ColoredColumn = 0
#HeaderTextColor = #Red
#LVM_GETHEADER = #LVM_FIRST + 31

#Gadget_MyInfo_Titles = 0

Enumeration fonts
  #FontStrikeoutYes
  #FontStrikeoutNo
EndEnumeration

LoadFont(#FontStrikeoutYes, "", 12, #PB_Font_StrikeOut)
LoadFont(#FontStrikeoutNo, "", 12)


Define DefaultListIconCallback.I

Procedure CustomListIconCallback(hWnd, uMsg, wParam, lParam)
  Shared DefaultListIconCallback.I
  
  Protected *NMCUSTOMDRAW.NMCUSTOMDRAW
  Protected *NMHDR.NMHDR
  Protected Result.I
  
  If hWnd = GadgetID(#Gadget_MyInfo_Titles)
    If uMsg = #WM_NOTIFY
      *NMHDR = lParam
      
      If *NMHDR\code = #NM_CUSTOMDRAW
        *NMCUSTOMDRAW = lParam
        Select *NMCUSTOMDRAW\dwDrawStage
          Case #CDDS_PREPAINT
            ;TODO
            ProcedureReturn #CDRF_NOTIFYITEMDRAW
          Case #CDDS_ITEMPREPAINT
            If *NMCUSTOMDRAW\dwItemSpec = #ColoredColumn
              SetTextColor_(*NMCUSTOMDRAW\hdc, #HeaderTextColor)
              ProcedureReturn #CDDS_ITEMPREPAINT
            EndIf
        EndSelect
      EndIf
    EndIf
  EndIf  
  ProcedureReturn CallWindowProc_(DefaultListIconCallback, hWnd, uMsg, wParam, lParam)
EndProcedure


Procedure MainWindowCallback(hWnd, uMsg, wParam, lParam)
  
  Protected Result = #PB_ProcessPureBasicEvents
  Protected *nmhdr.NMHDR, *lvCD.NMLVCUSTOMDRAW
  Protected thisRow, thisCol, on_off
  
  ; Draw a line through an item to indicate its deleted state
  Select uMsg 
      
    Case #WM_NOTIFY
      
      *nmhdr.NMHDR = lParam
      
      *lvCD.NMLVCUSTOMDRAW = lParam
      
      If IsGadget(#Gadget_MyInfo_Titles)
        If *lvCD\nmcd\hdr\hwndFrom = GadgetID(#Gadget_MyInfo_Titles) And *lvCD\nmcd\hdr\code = #NM_CUSTOMDRAW
          Select *lvCD\nmcd\dwDrawStage
            Case #CDDS_PREPAINT
              ;result = #CDRF_NOTIFYITEMDRAW ; <- Not used
            Case #CDDS_ITEMPREPAINT
              ;result = #CDRF_NOTIFYSUBITEMDRAW; <- Not used
            Case #CDDS_ITEMPREPAINT | #CDDS_SUBITEM
              thisRow = *lvCD\nmcd\dwItemSpec
              thisCol = *lvCD\iSubItem
              on_off = GetGadgetItemData(#Gadget_MyInfo_Titles, thisRow)
              ; If thisCol = 0 And on_off. Specifically for column 0. You can change this to any or just use on_off to set all columns
              If on_off
                SelectObject_(*lvCD\nmcd\hdc, FontID(#FontStrikeoutYes))
                result = #CDRF_NEWFONT ; | #CDRF_DODEFAULT
              Else
                SelectObject_(*lvCD\nmcd\hdc, FontID(#FontStrikeoutNo))
                result = #CDRF_NEWFONT   
              EndIf
          EndSelect
        EndIf
      EndIf
  EndSelect ; uMsg
  
  ProcedureReturn Result
  
EndProcedure


OpenWindow(0, 200, 100, 400, 100, "ListIconGadget with colored header text")
ListIconGadget(0, 10, 10, WindowWidth(0) - 20, WindowHeight(0) - 20,
               "Name", 110, #PB_ListIcon_GridLines)
AddGadgetColumn(0, 1, "Address", GadgetWidth(0) - GetGadgetItemAttribute(0, 0,
                                                                         #PB_ListIcon_ColumnWidth) - 4)
AddGadgetItem(0, -1, "Harry Rannit" + #LF$ +
                     "12 Parliament Way, Battle Street, By the Bay")
AddGadgetItem(0, -1, "Ginger Brokeit" + #LF$ +
                     "130 PureBasic Road, BigTown, CodeCity")
AddGadgetItem(0, -1, "Didi Foundit" + #LF$ +
                     "321 Logo Drive, Mouse House, Downtown")

DefaultListIconCallback = SetWindowLongPtr_(GadgetID(0), #GWL_WNDPROC,
                                            @CustomListIconCallback())

SetGadgetItemData(0, 1, #True)

SetWindowCallback(@MainWindowCallback())

Repeat
Until WaitWindowEvent() = #PB_Event_CloseWindow
My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
User avatar
Fangbeast
PureBasic Protozoa
PureBasic Protozoa
Posts: 4790
Joined: Fri Apr 25, 2003 3:08 pm
Location: Not Sydney!!! (Bad water, no goats)

Re: SetGadgetItemColor doesn't work after windowcallback cod

Post by Fangbeast »

This is getting more and more complicated for me for follow.
Amateur Radio/VK3HAF, (D-STAR/DMR and more), Arduino, ESP32, Coding, Crochet
User avatar
mk-soft
Always Here
Always Here
Posts: 6249
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

Re: SetGadgetItemColor doesn't work after windowcallback cod

Post by mk-soft »

I don't think it's possible to change the background color and the font separately.

You have to completely redraw the item yourself...

Link: https://www.rsbasic.de/winapi-library/
My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
User avatar
Fangbeast
PureBasic Protozoa
PureBasic Protozoa
Posts: 4790
Joined: Fri Apr 25, 2003 3:08 pm
Location: Not Sydney!!! (Bad water, no goats)

Re: SetGadgetItemColor doesn't work after windowcallback cod

Post by Fangbeast »

mk-soft wrote:I don't think it's possible to change the background color and the font separately.

You have to completely redraw the item yourself...

Link: https://www.rsbasic.de/winapi-library/
That's beyond me so I'll study your example and see which callback I have to add the rest of the stuff in. And the colouring (the column shading), needs to be added to that gadget as well but depending on which database is showing, the colouring has to adapt so I don't know what to alter inside the callback as each database has different columns and the gadget is updated accordingly.

I'll take a look tomorrow. Today was full of backups and playing with the cat:):)
Amateur Radio/VK3HAF, (D-STAR/DMR and more), Arduino, ESP32, Coding, Crochet
User avatar
Fangbeast
PureBasic Protozoa
PureBasic Protozoa
Posts: 4790
Joined: Fri Apr 25, 2003 3:08 pm
Location: Not Sydney!!! (Bad water, no goats)

Re: SetGadgetItemColor doesn't work after windowcallback cod

Post by Fangbeast »

Had a play with it and don't understand how to use it. I have to be able to change the column colours whenever I need to, to cope with the fact that the gadget is changed with the number of columns to suit the database that is loaded at the time.

Same gadget, different database, different number of columns, different column colours.

Don't know how to do that with callbacks (or API in general) on demand.
Amateur Radio/VK3HAF, (D-STAR/DMR and more), Arduino, ESP32, Coding, Crochet
RASHAD
PureBasic Expert
PureBasic Expert
Posts: 4954
Joined: Sun Apr 12, 2009 6:27 am

Re: SetGadgetItemColor doesn't work after windowcallback cod

Post by RASHAD »

Hi Fang
To use the native commands for coloring the ListIcon()
You must disable the Customdraw(*lvCD.NMLVCUSTOMDRAW) in your windowcallback procedure

Code: Select all

EnableExplicit

#ColoredColumn = 0
#HeaderTextColor = #Red
#LVM_GETHEADER = #LVM_FIRST + 31

#Gadget_MyInfo_Titles = 0

Enumeration fonts
  #FontStrikeoutYes
  #FontStrikeoutNo
EndEnumeration

LoadFont(#FontStrikeoutYes, "", 12, #PB_Font_StrikeOut)
LoadFont(#FontStrikeoutNo, "", 12)

Procedure MainWindowCallback(hWnd, uMsg, wParam, lParam)
  Protected Result = #PB_ProcessPureBasicEvents
  Protected *nmhdr.NMHDR, *lvCD.NMLVCUSTOMDRAW
  Protected thisRow, thisCol, on_off
 
  ; Draw a line through an item to indicate its deleted state
  Select uMsg 
   
    Case #WM_NOTIFY
   
;       *nmhdr.NMHDR = lParam
;      
;       *lvCD.NMLVCUSTOMDRAW = lParam
;      
;       If IsGadget(#Gadget_MyInfo_Titles)
;         If *lvCD\nmcd\hdr\hwndFrom = GadgetID(#Gadget_MyInfo_Titles) And *lvCD\nmcd\hdr\code = #NM_CUSTOMDRAW
;           Select *lvCD\nmcd\dwDrawStage
;             Case #CDDS_PREPAINT
;               result = #CDRF_NOTIFYITEMDRAW
;             Case #CDDS_ITEMPREPAINT
;               result = #CDRF_NOTIFYSUBITEMDRAW;
;             Case #CDDS_ITEMPREPAINT | #CDDS_SUBITEM
;               thisRow = *lvCD\nmcd\dwItemSpec
;               thisCol = *lvCD\iSubItem
;               on_off = GetGadgetItemData(#Gadget_MyInfo_Titles, thisRow)
;               ; If thisCol = 0 And on_off. Specifically for column 0. You can change this to any or just use on_off to set all columns
;               If on_off
;                 SelectObject_(*lvCD\nmcd\hdc, FontID(#FontStrikeoutYes))
;                 result = #CDRF_NEWFONT; | #CDRF_DODEFAULT
;               Else
;                 SelectObject_(*lvCD\nmcd\hdc, FontID(#FontStrikeoutNo))
;                 result = #CDRF_DODEFAULT   
;               EndIf
;           EndSelect
;         EndIf
;       EndIf
  EndSelect ; uMsg
 
  ProcedureReturn Result
 
EndProcedure

OpenWindow(0, 200, 100, 400, 100, "ListIconGadget with colored header text")
ListIconGadget(0, 10, 10, WindowWidth(0) - 20, WindowHeight(0) - 20,
               "Name", 110, #PB_ListIcon_GridLines)
AddGadgetColumn(0, 1, "Address", GadgetWidth(0) - GetGadgetItemAttribute(0, 0,
                                                                         #PB_ListIcon_ColumnWidth) - 4)
AddGadgetItem(0, -1, "Harry Rannit" + #LF$ +
                     "12 Parliament Way, Battle Street, By the Bay")
AddGadgetItem(0, -1, "Ginger Brokeit" + #LF$ +
                     "130 PureBasic Road, BigTown, CodeCity")
AddGadgetItem(0, -1, "Didi Foundit" + #LF$ +
                     "321 Logo Drive, Mouse House, Downtown")

SetGadgetItemColor(0,1,#PB_Gadget_BackColor,$16FBF8)
SetGadgetItemData(0, 1, #True)

SetWindowCallback(@MainWindowCallback())

Repeat
Until WaitWindowEvent() = #PB_Event_CloseWindow
Egypt my love
User avatar
Fangbeast
PureBasic Protozoa
PureBasic Protozoa
Posts: 4790
Joined: Fri Apr 25, 2003 3:08 pm
Location: Not Sydney!!! (Bad water, no goats)

Re: SetGadgetItemColor doesn't work after windowcallback cod

Post by Fangbeast »

RASHAD wrote:Hi Fang
To use the native commands for coloring the ListIcon()
You must disable the Customdraw(*lvCD.NMLVCUSTOMDRAW) in your windowcallback procedure

Code: Select all

EnableExplicit

#ColoredColumn = 0
#HeaderTextColor = #Red
#LVM_GETHEADER = #LVM_FIRST + 31

#Gadget_MyInfo_Titles = 0

Enumeration fonts
  #FontStrikeoutYes
  #FontStrikeoutNo
EndEnumeration

LoadFont(#FontStrikeoutYes, "", 12, #PB_Font_StrikeOut)
LoadFont(#FontStrikeoutNo, "", 12)

Procedure MainWindowCallback(hWnd, uMsg, wParam, lParam)
  Protected Result = #PB_ProcessPureBasicEvents
  Protected *nmhdr.NMHDR, *lvCD.NMLVCUSTOMDRAW
  Protected thisRow, thisCol, on_off
 
  ; Draw a line through an item to indicate its deleted state
  Select uMsg 
   
    Case #WM_NOTIFY
   
;       *nmhdr.NMHDR = lParam
;      
;       *lvCD.NMLVCUSTOMDRAW = lParam
;      
;       If IsGadget(#Gadget_MyInfo_Titles)
;         If *lvCD\nmcd\hdr\hwndFrom = GadgetID(#Gadget_MyInfo_Titles) And *lvCD\nmcd\hdr\code = #NM_CUSTOMDRAW
;           Select *lvCD\nmcd\dwDrawStage
;             Case #CDDS_PREPAINT
;               result = #CDRF_NOTIFYITEMDRAW
;             Case #CDDS_ITEMPREPAINT
;               result = #CDRF_NOTIFYSUBITEMDRAW;
;             Case #CDDS_ITEMPREPAINT | #CDDS_SUBITEM
;               thisRow = *lvCD\nmcd\dwItemSpec
;               thisCol = *lvCD\iSubItem
;               on_off = GetGadgetItemData(#Gadget_MyInfo_Titles, thisRow)
;               ; If thisCol = 0 And on_off. Specifically for column 0. You can change this to any or just use on_off to set all columns
;               If on_off
;                 SelectObject_(*lvCD\nmcd\hdc, FontID(#FontStrikeoutYes))
;                 result = #CDRF_NEWFONT; | #CDRF_DODEFAULT
;               Else
;                 SelectObject_(*lvCD\nmcd\hdc, FontID(#FontStrikeoutNo))
;                 result = #CDRF_DODEFAULT   
;               EndIf
;           EndSelect
;         EndIf
;       EndIf
  EndSelect ; uMsg
 
  ProcedureReturn Result
 
EndProcedure

OpenWindow(0, 200, 100, 400, 100, "ListIconGadget with colored header text")
ListIconGadget(0, 10, 10, WindowWidth(0) - 20, WindowHeight(0) - 20,
               "Name", 110, #PB_ListIcon_GridLines)
AddGadgetColumn(0, 1, "Address", GadgetWidth(0) - GetGadgetItemAttribute(0, 0,
                                                                         #PB_ListIcon_ColumnWidth) - 4)
AddGadgetItem(0, -1, "Harry Rannit" + #LF$ +
                     "12 Parliament Way, Battle Street, By the Bay")
AddGadgetItem(0, -1, "Ginger Brokeit" + #LF$ +
                     "130 PureBasic Road, BigTown, CodeCity")
AddGadgetItem(0, -1, "Didi Foundit" + #LF$ +
                     "321 Logo Drive, Mouse House, Downtown")

SetGadgetItemColor(0,1,#PB_Gadget_BackColor,$16FBF8)
SetGadgetItemData(0, 1, #True)

SetWindowCallback(@MainWindowCallback())

Repeat
Until WaitWindowEvent() = #PB_Event_CloseWindow
But then I can't get the line drawn through the text if I want to. Is there any way around this Master RASHAD?

I need both colouring selectable whenever I want it and strikeout text always shown for deleted items.
Amateur Radio/VK3HAF, (D-STAR/DMR and more), Arduino, ESP32, Coding, Crochet
RASHAD
PureBasic Expert
PureBasic Expert
Posts: 4954
Joined: Sun Apr 12, 2009 6:27 am

Re: SetGadgetItemColor doesn't work after windowcallback cod

Post by RASHAD »

Hi Fang

Code: Select all

;EnableExplicit

#ColoredColumn = 0
#HeaderTextColor = #Red
#LVM_GETHEADER = #LVM_FIRST + 31

#Gadget_MyInfo_Titles = 0

Enumeration fonts
  #FontStrikeoutYes
  #FontStrikeoutNo
EndEnumeration

Global brush
brush = CreateSolidBrush_($15FBF8)

LoadFont(#FontStrikeoutYes, "", 12, #PB_Font_StrikeOut)
LoadFont(#FontStrikeoutNo, "", 12)

Procedure MainWindowCallback(hWnd, uMsg, wParam, lParam)
  Protected Result = #PB_ProcessPureBasicEvents
  Protected *nmhdr.NMHDR, *lvCD.NMLVCUSTOMDRAW
  Protected thisRow, thisCol, on_off
 
  ; Draw a line through an item to indicate its deleted state
  Select uMsg
   
    Case #WM_NOTIFY
   
      *nmhdr.NMHDR = lParam
    
      *lvCD.NMLVCUSTOMDRAW = lParam
    
      If IsGadget(#Gadget_MyInfo_Titles)
        If *lvCD\nmcd\hdr\hwndFrom = GadgetID(#Gadget_MyInfo_Titles) And *lvCD\nmcd\hdr\code = #NM_CUSTOMDRAW
          Select *lvCD\nmcd\dwDrawStage
            Case #CDDS_PREPAINT
              result = #CDRF_NOTIFYITEMDRAW
            Case #CDDS_ITEMPREPAINT
              result = #CDRF_NOTIFYSUBITEMDRAW;
            Case #CDDS_ITEMPREPAINT | #CDDS_SUBITEM
              thisRow = *lvCD\nmcd\dwItemSpec
              thisCol = *lvCD\iSubItem
              on_off = GetGadgetItemData(#Gadget_MyInfo_Titles, thisRow)
              ; If thisCol = 0 And on_off. Specifically for column 0. You can change this to any or just use on_off to set all columns
              If on_off
                SelectObject_(*lvCD\nmcd\hdc, FontID(#FontStrikeoutYes))
                text$ = GetGadgetItemText(0, thisRow ,thisCol)
                SetBkMode_(*lvCD\nmcd\hdc,#TRANSPARENT)
                FillRect_(*lvCD\nmcd\hdc, *lvCD\nmcd\rc, brush)
                SetTextColor_(*lvCD\nmcd\hdc, $0000FF)
                DrawText_(*lvCD\nmcd\hdc, @text$, Len(text$), *lvCD\nmcd\rc, #DT_CENTER|#DT_VCENTER|#DT_SINGLELINE|#DT_END_ELLIPSIS)
                result = #CDRF_SKIPDEFAULT
              Else
                SelectObject_(*lvCD\nmcd\hdc, FontID(#FontStrikeoutNo))
                result = #CDRF_DODEFAULT   
              EndIf
          EndSelect
        EndIf
      EndIf
  EndSelect ; uMsg
 
  ProcedureReturn Result
 
EndProcedure

OpenWindow(0, 200, 100, 400, 100, "ListIconGadget with colored header text")
ListIconGadget(0, 10, 10, WindowWidth(0) - 20, WindowHeight(0) - 20,
               "Name", 110, #PB_ListIcon_GridLines)
AddGadgetColumn(0, 1, "Address", GadgetWidth(0) - GetGadgetItemAttribute(0, 0,
                                                                         #PB_ListIcon_ColumnWidth) - 4)
AddGadgetItem(0, -1, "Harry Rannit" + #LF$ +
                     "12 Parliament Way, Battle Street, By the Bay")
AddGadgetItem(0, -1, "Ginger Brokeit" + #LF$ +
                     "130 PureBasic Road, BigTown, CodeCity")
AddGadgetItem(0, -1, "Didi Foundit" + #LF$ +
                     "321 Logo Drive, Mouse House, Downtown")

;SetGadgetItemColor(0,1,#PB_Gadget_BackColor,$16FBF8)
SetGadgetColor(0,#PB_Gadget_BackColor,$CFFED4)
SetGadgetItemData(0, 1, #True)

SetWindowCallback(@MainWindowCallback())

Repeat
Until WaitWindowEvent() = #PB_Event_CloseWindow

Egypt my love
User avatar
Fangbeast
PureBasic Protozoa
PureBasic Protozoa
Posts: 4790
Joined: Fri Apr 25, 2003 3:08 pm
Location: Not Sydney!!! (Bad water, no goats)

Re: SetGadgetItemColor doesn't work after windowcallback cod

Post by Fangbeast »

Sorry RASHAD, I am lost here. You are changing the text colour in the callback and I need to change the text colour on-the-fly when I need it to accomodate each database I am using. It isn't static.

Is there any way of changing the text colour whenever I want to and still be able to draw deleted lines through text?

API is good, happy to use it, don't understand it.

Thanks for being patient with me.
Amateur Radio/VK3HAF, (D-STAR/DMR and more), Arduino, ESP32, Coding, Crochet
RASHAD
PureBasic Expert
PureBasic Expert
Posts: 4954
Joined: Sun Apr 12, 2009 6:27 am

Re: SetGadgetItemColor doesn't work after windowcallback cod

Post by RASHAD »

Hi Fang
Replace SetGadgetItemColor() with _SetGadgetItemColor()
in your code and report if everything is OK (I hope so :) )
Use it once then at any time you can enable it selcol(col) = 1 or disable it selcol(col) = 0

Code: Select all

;EnableExplicit

#ColoredColumn = 0
#HeaderTextColor = #Red
#LVM_GETHEADER = #LVM_FIRST + 31

#Gadget_MyInfo_Titles = 0

Enumeration fonts
  #FontStrikeoutYes
  #FontStrikeoutNo
EndEnumeration

Global backcolor,textcolor,itemtext$
Global Dim selcol(10)
backcolor = CreateSolidBrush_($15FBF8)

LoadFont(#FontStrikeoutYes, "Tahoma", 12, #PB_Font_StrikeOut)
LoadFont(#FontStrikeoutNo, "Tahoma", 12)

Procedure _SetGadgetItemColor(Gadget, Item, ColorType ,color, Col)
  If ColorType = #PB_Gadget_BackColor
    DeleteObject_(backcolor)
    backcolor = CreateSolidBrush_(color)
  ElseIf ColorType = #PB_Gadget_FrontColor
    textcolor = color
  EndIf     
EndProcedure

Procedure MainWindowCallback(hWnd, uMsg, wParam, lParam)
  Protected Result = #PB_ProcessPureBasicEvents
  Protected *nmhdr.NMHDR, *lvCD.NMLVCUSTOMDRAW
  Protected  on_off
 
  ; Draw a line through an item to indicate its deleted state
  Select uMsg
   
    Case #WM_NOTIFY
   
      *nmhdr.NMHDR = lParam
   
      *lvCD.NMLVCUSTOMDRAW = lParam
   
      If IsGadget(#Gadget_MyInfo_Titles)
        If *lvCD\nmcd\hdr\hwndFrom = GadgetID(#Gadget_MyInfo_Titles) And *lvCD\nmcd\hdr\code = #NM_CUSTOMDRAW
          Select *lvCD\nmcd\dwDrawStage
            Case #CDDS_PREPAINT
              result = #CDRF_NOTIFYITEMDRAW
            Case #CDDS_ITEMPREPAINT
              result = #CDRF_NOTIFYSUBITEMDRAW;
            Case #CDDS_ITEMPREPAINT | #CDDS_SUBITEM
              thisRow = *lvCD\nmcd\dwItemSpec
              thisCol = *lvCD\iSubItem
              on_off = GetGadgetItemData(#Gadget_MyInfo_Titles, thisRow)
              ; If thisCol = 0 And on_off. Specifically for column 0. You can change this to any or just use on_off to set all columns
              itemtext$ = GetGadgetItemText(0,thisRow,thisCol)
              SelectObject_(*lvCD\nmcd\hdc, FontID(#FontStrikeoutNo))
              result = #CDRF_DODEFAULT
              If on_off And selcol(thisCol) = 1           
                SelectObject_(*lvCD\nmcd\hdc, FontID(#FontStrikeoutYes))
                SetBkMode_(*lvCD\nmcd\hdc,#TRANSPARENT)
                FillRect_(*lvCD\nmcd\hdc, *lvCD\nmcd\rc, backcolor)
                SetTextColor_(*lvCD\nmcd\hdc, textcolor)
                DrawText_(*lvCD\nmcd\hdc, @itemtext$, Len(itemtext$), *lvCD\nmcd\rc, #DT_CENTER|#DT_VCENTER|#DT_SINGLELINE|#DT_END_ELLIPSIS)
                result = #CDRF_SKIPDEFAULT
              EndIf
          EndSelect
        EndIf
      EndIf
  EndSelect ; uMsg
 
  ProcedureReturn Result
 
EndProcedure


OpenWindow(0, 0, 0, 600, 400, "ListIconGadget with colored header text",#PB_Window_SystemMenu |  #PB_Window_ScreenCentered)
SetWindowCallback(@MainWindowCallback())
ListIconGadget(0, 10, 10, WindowWidth(0) - 20, WindowHeight(0) - 20,
               "Name", 110, #PB_ListIcon_GridLines)
AddGadgetColumn(0, 1, "Address", GadgetWidth(0) - GetGadgetItemAttribute(0, 0,
                                                                         #PB_ListIcon_ColumnWidth) - 4)
AddGadgetItem(0, -1, "Harry Rannit" + #LF$ +
                     "12 Parliament Way, Battle Street, By the Bay")
AddGadgetItem(0, -1, "Ginger Brokeit" + #LF$ +
                     "130 PureBasic Road, BigTown, CodeCity")
AddGadgetItem(0, -1, "Didi Foundit" + #LF$ +
                     "321 Logo Drive, Mouse House, Downtown")

SetGadgetColor(0,#PB_Gadget_BackColor,$E4FEE1)
SetGadgetItemData(0, 1, #True)

_SetGadgetItemColor(0, 1 , #PB_Gadget_FrontColor ,$171FFF,0)
_SetGadgetItemColor(0, 1 , #PB_Gadget_BackColor ,$CEFEFD,0)
selcol(0) = 0
selcol(1) = 1

Repeat
Until WaitWindowEvent() = #PB_Event_CloseWindow
Last edited by RASHAD on Tue Jul 30, 2019 10:49 am, edited 1 time in total.
Egypt my love
User avatar
mk-soft
Always Here
Always Here
Posts: 6249
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

Re: SetGadgetItemColor doesn't work after windowcallback cod

Post by mk-soft »

Perhaps over structure

Code: Select all

;EnableExplicit

#ColoredColumn = 0
#HeaderTextColor = #Red
#LVM_GETHEADER = #LVM_FIRST + 31

#Gadget_MyInfo_Titles = 0

Enumeration fonts
  #FontStrikeoutYes
  #FontStrikeoutNo
EndEnumeration

Structure udtItemInfo
  On_Off.i
  TextColor.i
  BackColor.i
EndStructure

Global brush
brush = CreateSolidBrush_($15FBF8)

LoadFont(#FontStrikeoutYes, "", 10, #PB_Font_StrikeOut)
LoadFont(#FontStrikeoutNo, "", 10)

Procedure MainWindowCallback(hWnd, uMsg, wParam, lParam)
  Protected Result = #PB_ProcessPureBasicEvents
  Protected *nmhdr.NMHDR, *lvCD.NMLVCUSTOMDRAW
  Protected thisRow, thisCol, *ItemInfo.udtItemInfo, brush
 
  ; Draw a line through an item to indicate its deleted state
  Select uMsg
   
    Case #WM_NOTIFY
   
      *nmhdr.NMHDR = lParam
    
      *lvCD.NMLVCUSTOMDRAW = lParam
    
      If IsGadget(#Gadget_MyInfo_Titles)
        If *lvCD\nmcd\hdr\hwndFrom = GadgetID(#Gadget_MyInfo_Titles) And *lvCD\nmcd\hdr\code = #NM_CUSTOMDRAW
          Select *lvCD\nmcd\dwDrawStage
            Case #CDDS_PREPAINT
              result = #CDRF_NOTIFYITEMDRAW
            Case #CDDS_ITEMPREPAINT
              result = #CDRF_NOTIFYSUBITEMDRAW;
            Case #CDDS_ITEMPREPAINT | #CDDS_SUBITEM
              thisRow = *lvCD\nmcd\dwItemSpec
              thisCol = *lvCD\iSubItem
              *ItemInfo = GetGadgetItemData(#Gadget_MyInfo_Titles, thisRow)
              ; If thisCol = 0 And on_off. Specifically for column 0. You can change this to any or just use on_off to set all columns
              If *ItemInfo
                If *ItemInfo\On_Off
                  SelectObject_(*lvCD\nmcd\hdc, FontID(#FontStrikeoutYes))
                Else
                  SelectObject_(*lvCD\nmcd\hdc, FontID(#FontStrikeoutNo))
                EndIf
                brush = CreateSolidBrush_(*ItemInfo\BackColor)
                text$ = GetGadgetItemText(0, thisRow ,thisCol)
                SetBkMode_(*lvCD\nmcd\hdc,#TRANSPARENT)
                FillRect_(*lvCD\nmcd\hdc, *lvCD\nmcd\rc, brush)
                SetTextColor_(*lvCD\nmcd\hdc, *ItemInfo\TextColor)
                DrawText_(*lvCD\nmcd\hdc, @text$, Len(text$), *lvCD\nmcd\rc, #DT_CENTER|#DT_VCENTER|#DT_SINGLELINE|#DT_END_ELLIPSIS)
                DeleteObject_(brush)
                result = #CDRF_SKIPDEFAULT
              Else
                SelectObject_(*lvCD\nmcd\hdc, FontID(#FontStrikeoutNo))
                result = #CDRF_DODEFAULT   
              EndIf
          EndSelect
        EndIf
      EndIf
  EndSelect ; uMsg
 
  ProcedureReturn Result
 
EndProcedure

OpenWindow(0, 200, 100, 400, 100, "ListIconGadget with colored header text")
ListIconGadget(0, 10, 10, WindowWidth(0) - 20, WindowHeight(0) - 20,
               "Name", 110, #PB_ListIcon_GridLines)
AddGadgetColumn(0, 1, "Address", GadgetWidth(0) - GetGadgetItemAttribute(0, 0,
                                                                         #PB_ListIcon_ColumnWidth) - 4)
AddGadgetItem(0, -1, "Harry Rannit" + #LF$ +
                     "12 Parliament Way, Battle Street, By the Bay")
AddGadgetItem(0, -1, "Ginger Brokeit" + #LF$ +
                     "130 PureBasic Road, BigTown, CodeCity")
AddGadgetItem(0, -1, "Didi Foundit" + #LF$ +
                     "321 Logo Drive, Mouse House, Downtown")

;SetGadgetItemColor(0,1,#PB_Gadget_BackColor,$16FBF8)
SetGadgetColor(0,#PB_Gadget_BackColor,$CFFED4)

Dim ItemInfo.udtItemInfo(3)
ItemInfo(0)\On_Off = #False
ItemInfo(0)\BackColor = #Gray
ItemInfo(0)\TextColor = #White

ItemInfo(1)\On_Off = #True
ItemInfo(1)\BackColor = #Red
ItemInfo(1)\TextColor = #Yellow

ItemInfo(2)\On_Off = #False
ItemInfo(2)\BackColor = #Green
ItemInfo(2)\TextColor = #Black

SetGadgetItemData(0, 0, @ItemInfo(0))
SetGadgetItemData(0, 1, @ItemInfo(1))
SetGadgetItemData(0, 2, @ItemInfo(2))

SetWindowCallback(@MainWindowCallback())

Repeat
Until WaitWindowEvent() = #PB_Event_CloseWindow

My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
User avatar
Fangbeast
PureBasic Protozoa
PureBasic Protozoa
Posts: 4790
Joined: Fri Apr 25, 2003 3:08 pm
Location: Not Sydney!!! (Bad water, no goats)

Re: SetGadgetItemColor doesn't work after windowcallback cod

Post by Fangbeast »

mk-soft, you and RASHAD come up with some terrific stuff. I don't always understand it though!!!

One more question, can I address a specific column as well as a single line whenever I want to?
Amateur Radio/VK3HAF, (D-STAR/DMR and more), Arduino, ESP32, Coding, Crochet
Post Reply