Sign in to follow this  
Followers 0
Spiff59

Protect ListView subitem color

6 posts in this topic

I'm popping up a second gui on top of a large ListView, one that has individual cells colored via customdraw. When I delete the temporary GUI, the colors beneath have reverted to the default, black. Tried a forum search, tried playing with some styles and extended styles. Is there a way to protect the colors beneath so I won't have to repeatedly recreate the main listview?

Thanks.

Share this post


Link to post
Share on other sites



#3 ·  Posted (edited)

I'd about given up on this one.

Ok, took 40 mins to chop 1000 lines down to a working 100.

No more databases, files, subscripts, images, buttons, timers, etc.

This example is similar to what I was experiencing when I made this post.

In that state, the text/bg color of cells gets trashed by the sub-GUI.

Uncommenting the SW_LOCK and SW_UNLOCK statements in this example is what I'm running now.

Now, dragging the second GUI around is ugly, but the colors are at least restored after it's closed (the users dont drag the popup anyway).

Typically, my listview will be fully populated, so you'll need to drag the popup GUI around to see how it effects text color.

Double-click "CLICK ME" to launch the second GUI.

I made a couple comments on interesting (confusing) areas in the code.

Am sure there's a style or two that would make things prettier, or a patch to my WM_NOTIFY code?

Thanks much.

#include <GuiConstants.au3>
#include <GuiListView.au3>
#include <WindowsConstants.au3>
Global $hListItem[2]
Global $hWndFrom, $iIDFrom, $iCode, $tNMHDR, $hWndListView, $tInfo, $aHit
Global $iColor, $iColorBk

$Main_GUI = GuiCreate("test", 924, 604, 60, 20)
$hListView = GuiCtrlCreateListView("", 10, 44, 904, 535, -1, BitOR($LVS_ICON, $LVS_EX_GRIDLINES, $LVS_EX_DOUBLEBUFFER, $LVS_EX_TWOCLICKACTIVATE))
$hListView = GUICtrlGetHandle($hListView) ; necessary for _SubItemHitTest
_GUICtrlListView_AddColumn($hListView, " ", 20)
_GUICtrlListView_AddColumn($hListView, "TIME", 40, 1)
_GUICtrlListView_AddColumn($hListView, "PROVIDER ", 70)
_GUICtrlListView_AddColumn($hListView, "CHART # ", 70)
_GUICtrlListView_AddColumn($hListView, "PATIENT NAME ", 155)
_GUICtrlListView_AddColumn($hListView, "NOTE ", 158)
_GUICtrlListView_AddColumn($hListView, "RESOURCE", 72)
_GUICtrlListView_AddColumn($hListView, "STATUS ", 74)
_GUICtrlListView_AddColumn($hListView, "CLAIM(S) ", 80)
_GUICtrlListView_AddColumn($hListView, "LEDGER", 72)
_GUICtrlListView_AddColumn($hListView, "DICTATION", 72)

$Status_Message = GUICtrlCreateLabel("", 20, 582, 180, 20)
GUISetState()
GUIRegisterMsg($WM_NOTIFY, "WM_NOTIFY")

;_GUICtrlListView_BeginUpdate($hListView)
$hListItem[1] = _GUICtrlListView_AddItem($hListView, " ")
_GUICtrlListView_AddSubItem($hListView, 0, "11:30", 1)
_GUICtrlListView_AddSubItem($hListView, 0, "XYZZY", 2)
_GUICtrlListView_AddSubItem($hListView, 0, "PLUGH", 3)
_GUICtrlListView_AddSubItem($hListView, 0, "DOE, JOHN", 4)
_GUICtrlListView_AddSubItem($hListView, 0, "PLOVER", 5)
_GUICtrlListView_AddSubItem($hListView, 0, "FOOBAR", 6)
_GUICtrlListView_AddSubItem($hListView, 0, "CLICK ME", 7)
_GUICtrlListView_AddSubItem($hListView, 0, "12345", 8)
_GUICtrlListView_AddSubItem($hListView, 0, "01-01-2009", 9)
_GUICtrlListView_AddSubItem($hListView, 0, "01-31-2009", 10)    
;_GUICtrlListView_EndUpdate($hListView)

;-----------------------------------------------------------------------------------------------------------
While 1
    $msg = GUIGetMsg()  
    Switch $msg
        Case -3 ; $GUI_EVENT_CLOSE
            ExitLoop
    EndSwitch
Wend
Exit

;-----------------------------------------------------------------------------------------------------------
Func WM_NOTIFY($hWnd, $iMsg, $iwParam, $ilParam)
    #forceref $hWnd, $iMsg, $iwParam
    $hWndListView = $hListView
    If Not IsHWnd($hListView) Then $hWndListView = GUICtrlGetHandle($hListView)
    $tNMHDR = DllStructCreate($tagNMHDR, $ilParam)
    $hWndFrom = HWnd(DllStructGetData($tNMHDR, "hWndFrom"))
    $iIDFrom = DllStructGetData($tNMHDR, "IDFrom")
    $iCode = DllStructGetData($tNMHDR, "Code")

    Switch $hWndFrom
        Case $hWndListView
            Switch $iCode
                Case $LVN_ENDSCROLL
                    $tNMHDR = DllStructCreate("hwnd hWnd;uint cID;int code", $ilParam)
                    $hLV = HWnd(DllStructGetData($tNMHDR, "hWnd"))
                    _WinAPI_InvalidateRect($hLV)
                Case $NM_DBLCLK 
                    $tInfo = DllStructCreate($tagNMITEMACTIVATE, $ilParam)
                    $aHit = _GUICtrlListView_SubItemHitTest($hListView)
                    If $aHit[0] < 0 Then Return $GUI_RUNDEFMSG
                    Switch $aHit[1]
                        Case 7
                            Child_GUI($aHit[0])
                    EndSwitch
                Case $NM_CUSTOMDRAW
                    Local $tCustDraw = DllStructCreate($tagNMLVCUSTOMDRAW, $ilParam)
                    Local $iDrawStage = DllStructGetData($tCustDraw, "dwDrawStage")
                    If $iDrawStage = $CDDS_PREPAINT Then Return $CDRF_NOTIFYITEMDRAW
                    If $iDrawStage = $CDDS_ITEMPREPAINT Then Return $CDRF_NOTIFYSUBITEMDRAW
                    Local $iItem = DllStructGetData($tCustDraw, "dwItemSpec")
                    Local $iSubItem = DllStructGetData($tCustDraw, "iSubItem")
                    
                    If $iSubItem Then
                        $iColor = 0x000000
                        $iColorBk = 0xFFFFFF 
                        Switch $iSubItem
                            Case 4 
                                $iColor = 0xFFFFFF 
                                $iColorBk = 8421376
                            Case 6 
                                $iColor = 0x0080FF
                            Case 7 
                                $iColor = 0x888888
                            Case 8 
                                $iColor = 0x228B22
                            Case 9 
                                $iColor = 0xFF0000
                            Case 10
                                $iColor = 0x0000FF
                        EndSwitch
                        DllStructSetData($tCustDraw, "clrTextBk", $iColorBk)
                        DllStructSetData($tCustDraw, "clrText", $iColor)
                    EndIf
            EndSwitch
    EndSwitch
    Return $GUI_RUNDEFMSG
EndFunc

;-----------------------------------------------------------------------------------------------------------
Func Child_GUI($y)
;   GUISetState(@SW_LOCK, $Main_GUI) ; uncommented changes behaviour
    $APPTSTAT_GUI = GUICreate("", 230, 180, 560, 140)
    GUISetState(@SW_SHOW, $APPTSTAT_GUI)
    While 1
        $msg2 = GUIGetMsg()
        Switch $msg2
            Case $GUI_EVENT_CLOSE
                ExitLoop
        EndSwitch
        Sleep(50) ; why is this necessary? otherwise crashes
    Wend
    GUIDelete($APPTSTAT_GUI)
    GUISetState(@SW_RESTORE, $Main_GUI)
;   GUISetState(@SW_UNLOCK, $Main_GUI); uncommented changes behaviour
EndFunc

typos

Edited by Spiff59

Share this post


Link to post
Share on other sites

Something like this

#include <GuiListView.au3>
#include <WindowsConstants.au3>
#include <GUIConstantsEx.au3>

Global $hListItem[2]
Global $hWndFrom, $iIDFrom, $iCode, $tNMHDR, $hWndListView, $tInfo, $aHit
Global $iColor, $iColorBk, $fChildGui = False

$Main_GUI = GuiCreate("test", 924, 604, 60, 20)
$hListView = GuiCtrlCreateListView("", 10, 44, 904, 535, -1, BitOR($LVS_ICON, $LVS_EX_GRIDLINES, $LVS_EX_DOUBLEBUFFER, $LVS_EX_TWOCLICKACTIVATE))
$hListView = GUICtrlGetHandle($hListView) ; necessary for _SubItemHitTest
_GUICtrlListView_AddColumn($hListView, " ", 20)
_GUICtrlListView_AddColumn($hListView, "TIME", 40, 1)
_GUICtrlListView_AddColumn($hListView, "PROVIDER ", 70)
_GUICtrlListView_AddColumn($hListView, "CHART # ", 70)
_GUICtrlListView_AddColumn($hListView, "PATIENT NAME ", 155)
_GUICtrlListView_AddColumn($hListView, "NOTE ", 158)
_GUICtrlListView_AddColumn($hListView, "RESOURCE", 72)
_GUICtrlListView_AddColumn($hListView, "STATUS ", 74)
_GUICtrlListView_AddColumn($hListView, "CLAIM(S) ", 80)
_GUICtrlListView_AddColumn($hListView, "LEDGER", 72)
_GUICtrlListView_AddColumn($hListView, "DICTATION", 72)

$Status_Message = GUICtrlCreateLabel("", 20, 582, 180, 20)
GUISetState()
GUIRegisterMsg($WM_NOTIFY, "WM_NOTIFY")

;_GUICtrlListView_BeginUpdate($hListView)
$hListItem[1] = _GUICtrlListView_AddItem($hListView, " ")
_GUICtrlListView_AddSubItem($hListView, 0, "11:30", 1)
_GUICtrlListView_AddSubItem($hListView, 0, "XYZZY", 2)
_GUICtrlListView_AddSubItem($hListView, 0, "PLUGH", 3)
_GUICtrlListView_AddSubItem($hListView, 0, "DOE, JOHN", 4)
_GUICtrlListView_AddSubItem($hListView, 0, "PLOVER", 5)
_GUICtrlListView_AddSubItem($hListView, 0, "FOOBAR", 6)
_GUICtrlListView_AddSubItem($hListView, 0, "CLICK ME", 7)
_GUICtrlListView_AddSubItem($hListView, 0, "12345", 8)
_GUICtrlListView_AddSubItem($hListView, 0, "01-01-2009", 9)
_GUICtrlListView_AddSubItem($hListView, 0, "01-31-2009", 10)   
;_GUICtrlListView_EndUpdate($hListView)

;-----------------------------------------------------------------------------------------------------------
While 1
    $msg = GUIGetMsg() 
    Switch $msg
        Case -3 ; $GUI_EVENT_CLOSE
            ExitLoop
    EndSwitch
    If $fChildGui Then
        Child_GUI($aHit[0])
        $fChildGui = False
    EndIf
Wend
Exit

;-----------------------------------------------------------------------------------------------------------
Func WM_NOTIFY($hWnd, $iMsg, $iwParam, $ilParam)
    #forceref $hWnd, $iMsg, $iwParam
    $hWndListView = $hListView
    If Not IsHWnd($hListView) Then $hWndListView = GUICtrlGetHandle($hListView)
    $tNMHDR = DllStructCreate($tagNMHDR, $ilParam)
    $hWndFrom = HWnd(DllStructGetData($tNMHDR, "hWndFrom"))
    $iIDFrom = DllStructGetData($tNMHDR, "IDFrom")
    $iCode = DllStructGetData($tNMHDR, "Code")

    Switch $hWndFrom
        Case $hWndListView
            Switch $iCode
                Case $LVN_ENDSCROLL
                    $tNMHDR = DllStructCreate("hwnd hWnd;uint cID;int code", $ilParam)
                    $hLV = HWnd(DllStructGetData($tNMHDR, "hWnd"))
                    _WinAPI_InvalidateRect($hLV)
                Case $NM_DBLCLK
                    $tInfo = DllStructCreate($tagNMITEMACTIVATE, $ilParam)
                    $aHit = _GUICtrlListView_SubItemHitTest($hListView)
                    If $aHit[0] < 0 Then Return $GUI_RUNDEFMSG
                    Switch $aHit[1]
                        Case 7
                            $fChildGui = True
                            ;Child_GUI($aHit[0])
                    EndSwitch
                Case $NM_CUSTOMDRAW
                    Local $tCustDraw = DllStructCreate($tagNMLVCUSTOMDRAW, $ilParam)
                    Local $iDrawStage = DllStructGetData($tCustDraw, "dwDrawStage")
                    If $iDrawStage = $CDDS_PREPAINT Then Return $CDRF_NOTIFYITEMDRAW
                    If $iDrawStage = $CDDS_ITEMPREPAINT Then Return $CDRF_NOTIFYSUBITEMDRAW
                    Local $iItem = DllStructGetData($tCustDraw, "dwItemSpec")
                    Local $iSubItem = DllStructGetData($tCustDraw, "iSubItem")
                   
                    If $iSubItem Then
                        $iColor = 0x000000
                        $iColorBk = 0xFFFFFF
                        Switch $iSubItem
                            Case 4
                                $iColor = 0xFFFFFF
                                $iColorBk = 8421376
                            Case 6
                                $iColor = 0x0080FF
                            Case 7
                                $iColor = 0x888888
                            Case 8
                                $iColor = 0x228B22
                            Case 9
                                $iColor = 0xFF0000
                            Case 10
                                $iColor = 0x0000FF
                        EndSwitch
                        DllStructSetData($tCustDraw, "clrTextBk", $iColorBk)
                        DllStructSetData($tCustDraw, "clrText", $iColor)
                    EndIf
            EndSwitch
    EndSwitch
    Return $GUI_RUNDEFMSG
EndFunc

;-----------------------------------------------------------------------------------------------------------
Func Child_GUI($y)
;   GUISetState(@SW_LOCK, $Main_GUI) ; uncommented changes behaviour
    $APPTSTAT_GUI = GUICreate("", 230, 180, 560, 140)
    GUISetState(@SW_SHOW, $APPTSTAT_GUI)
    While 1
        $msg2 = GUIGetMsg()
        Switch $msg2
            Case $GUI_EVENT_CLOSE
                ExitLoop
        EndSwitch
        Sleep(50) ; why is this necessary? otherwise crashes
    Wend
    GUIDelete($APPTSTAT_GUI)
    GUISetState(@SW_RESTORE, $Main_GUI)
;   GUISetState(@SW_UNLOCK, $Main_GUI); uncommented changes behaviour
EndFunc

Share this post


Link to post
Share on other sites

Just general note:

If you need to invoke some GUI interactive/long lasting code from WM_NOTIFY then do it indirectly using global helper variable

as picaxe did.

I have solved similar problems in my script the same way.

Share this post


Link to post
Share on other sites

#6 ·  Posted (edited)

Very nice!

Makes complete sense...

I was launching my second GUI from within the middle of the WM_NOTIFY function.

Apparently not good timing for creating new controls :P

So, instead, flip a flag, let WM_NOTIFY finish it's mystical stuff, and then launch the second GUI outside of WM_NOTIFY.

The weird Sleep(50) is no longer required and SW_LOCK and SW_UNLOCK are no longer needed either (although I'll park a SW_DISABLE/ENABLE on the main GUI to keep users from trying to perform tricks prior to closing the child GUI).

Thank you very much, Gentlemen.

Edit: typo (as always, vey (sic) first word this time!)

Edited by Spiff59

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0