Jump to content

_GUICtrlListView_SimpleSort and $NM_CUSTOMDRAW


Recommended Posts

#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <GuiListView.au3>
#include <GuiEdit.au3>
#include <FontConstants.au3>
#include <WinAPI.au3>
#include <ColorConstants.au3>
#include <GDIPlus.au3>
#include <GuiRichEdit.au3>
#include <ButtonConstants.au3>
Global $hEdit, $hDC, $hBrush, $Item = -1, $SubItem = 0 , $Index


Global $stRect = DllStructCreate("int;int;int;int")

Global $Start=True

Global $Clear=False

Global $tRect

Global $RichEdit

$Font = _WinAPI_CreateFont(15, 5, 0, 0, 400, False, False, False, Default,Default, Default, Default, 0, 'Arial')

$hGUI = GUICreate("ListView Subitems edit in place", 300, 210)

$hListView = _GUICtrlListView_Create($hGUI, "Items|SubItems", 2, 2, 296, 210)
_WinAPI_SetFont($hListView, $Font, True)
_GUICtrlListView_SetExtendedListViewStyle($hListView, $LVS_EX_GRIDLINES+$LVS_EX_FULLROWSELECT)
;~ ControlDisable($hGUI, "", HWnd(_GUICtrlListView_GetHeader($hListView)))
_GUICtrlListView_SetColumnWidth($hListView,1,$LVSCW_AUTOSIZE_USEHEADER)
_GUICtrlListView_SetColumnWidth($hListView,2,$LVSCW_AUTOSIZE_USEHEADER)
For $i = 1 To 10
    _GUICtrlListView_AddItem($hListView, "Item " & $i)
    _GUICtrlListView_AddSubItem($hListView, $i - 1, "SubItem " & $i, 1)
Next
$hButton = GUICtrlCreateButton("", 0, 0, 0, 0, BitOR($GUI_SS_DEFAULT_BUTTON, $BS_DEFPUSHBUTTON))
GUICtrlSetState($hButton, $GUI_HIDE)



GUIRegisterMsg($WM_NOTIFY, "WM_NOTIFY")
GUIRegisterMsg($WM_COMMAND,"WM_COMMAND")

GUISetState()






While 1
    Switch GUIGetMsg()
        Case $GUI_EVENT_CLOSE
            ExitLoop
        Case $hButton
            Update_Text()
    EndSwitch
WEnd


Func WM_NOTIFY($hWnd, $iMsg, $iwParam, $ilParam)
    Local $tNMHDR, $hWndFrom, $iCode
    $tNMHDR = DllStructCreate($tagNMHDR, $ilParam)
    $hWndFrom = DllStructGetData($tNMHDR, "hWndFrom")
    $iCode = DllStructGetData($tNMHDR, 3)
    Switch $hWndFrom
        Case $hListView
            Switch $iCode
                Case $NM_CUSTOMDRAW
                    If Not _GUICtrlListView_GetViewDetails($hWndFrom) Then Return $GUI_RUNDEFMSG
                    Local $tCustDraw = DllStructCreate('hwnd hwndFrom;int idFrom;int code;' & _
                            'dword DrawStage;hwnd hdc;long rect[4];dword ItemSpec;int ItemState;dword Itemlparam;' & _
                            'dword clrText;dword clrTextBk;int SubItem;' & _
                            'dword ItemType;dword clrFace;int IconEffect;int IconPhase;int PartID;int StateID;long rectText[4];int Align', _ ;winxp or later
                            $ilParam), $iDrawStage, $iItem, $iSubitem, $hDC, $tRect, $iColor1, $iColor2, $iColor3
                    $iDrawStage = DllStructGetData($tCustDraw, 'DrawStage')
                    Switch $iDrawStage
                        Case $CDDS_PREPAINT
                            Return $CDRF_NOTIFYITEMDRAW
                        Case $CDDS_ITEMPREPAINT
                            Return $CDRF_NOTIFYSUBITEMDRAW
                        Case $CDDS_ITEMPOSTPAINT
                        Case BitOR($CDDS_ITEMPREPAINT, $CDDS_SUBITEM)
                            $iItem = DllStructGetData($tCustDraw, 'ItemSpec')
                            $iSubitem = DllStructGetData($tCustDraw, 'SubItem')
                            If _GUICtrlListView_GetItemSelected($hWndFrom, $iItem) Then
                                $hDC = _WinAPI_GetDC($hWndFrom)
                                $tRect = DllStructCreate($tagRECT)
                                If $iSubitem = 0 Then
                                    _SendMessage($hWndFrom, $LVM_GETSUBITEMRECT, $iItem, DllStructGetPtr($tRect))
                                    DllStructSetData($tRect, 1, 2)
                                    DllStructSetData($tRect, 1, DllStructGetData($tRect, 1) - 2)
                                    _WinAPI_FillRect($hDC, DllStructGetPtr($tRect), _WinAPI_CreateSolidBrush(0XEAEAEA))
                                EndIf
                                DllStructSetData($tRect, 1, 2)
                                DllStructSetData($tRect, 2, $iSubitem)
                                _SendMessage($hWndFrom, $LVM_GETSUBITEMRECT, $iItem, DllStructGetPtr($tRect))
                                Local $sText = _GUICtrlListView_GetItemText($hWndFrom, $iItem, $iSubitem)
                                _WinAPI_SelectObject($hDC, $Font)
                                _WinAPI_SetBkMode($hDC, $TRANSPARENT)
                                $GetColumnWidth=_GUICtrlListView_GetColumnWidth($hWndFrom,0)/2
                                $GetStringWidth=_GUICtrlListView_GetStringWidth($hWndFrom, $sText)
;~                                 DllStructSetData($tRect, 1, DllStructGetData($tRect, 1)+ $GetColumnWidth -($GetStringWidth/2)-2)
                                DllStructSetData($tRect, 2, DllStructGetData($tRect, 2)+ 2)
                                _WinAPI_DrawText($hDC, $sText, $tRect, $DT_CENTER)
                                _WinAPI_ReleaseDC($hWndFrom, $hDC)
                                Return $CDRF_SKIPDEFAULT
                            EndIf
                            Return $CDRF_NEWFONT
                        Case BitOR($CDDS_ITEMPOSTPAINT, $CDDS_SUBITEM)
                        Case Else
                    EndSwitch
                Case $LVN_COLUMNCLICK
                    $tInfo = DllStructCreate($tagNMLISTVIEW, $ilParam)
                    $iCol     = DllStructGetData($tInfo, "SubItem")
                    _GUICtrlListView_SimpleSort($hListView, False, $iCol, False)


;~              Case $NM_CLICK
;~                  If $Clear=True Then
;~                      DllStructSetData($tRect, 1, DllStructGetData($tRect, 1) - 5)
;~                      DllStructSetData($tRect, 4, DllStructGetData($tRect, 4) - 1)
;~                      _WinAPI_FillRect($hDC, DllStructGetPtr($tRect), _WinAPI_CreateSolidBrush(0xFFFFFF))
;~                      DllStructSetData($tRect, 1, DllStructGetData($tRect, 1) + 5)
;~                      DllStructSetData($tRect, 4, DllStructGetData($tRect, 4) + 1)
;~                      _WinAPI_DrawText($hDC, $bText, $tRect,BitOR($DT_VCENTER, $DT_END_ELLIPSIS, $DT_SINGLELINE))
;~                  EndIf
;~                  $Info   = DllStructCreate($tagNMITEMACTIVATE, $ilParam)
;~                  $Index  = DllStructGetData($Info, "Index")
;~                  $SubItem= DllStructGetData($Info, "SubItem")
;~                  $Sub_Rect=_GUICtrlListView_GetSubItemRect($hListView,$Index,$SubItem)
;~                  $hDC = _WinAPI_GetDC($hWndFrom)
;~                  $tRect = DllStructCreate($tagRECT)
;~                  DllStructSetData($tRect, 1, 2)
;~                  DllStructSetData($tRect, 2, $SubItem)
;~                  _SendMessage($hWndFrom, $LVM_GETSUBITEMRECT, $Index, DllStructGetPtr($tRect))
;~                  If $SubItem < 1 Then
;~                      DllStructSetData($tRect, 1, DllStructGetData($tRect, 1) - 3)
;~                      DllStructSetData($tRect, 4, DllStructGetData($tRect, 4) - 2)
;~                      DllStructSetData($tRect, 3, DllStructGetData($tRect, 3) - 1)
;~                      DllStructSetData($tRect, 2, DllStructGetData($tRect, 2) + 1)
;~                  ElseIf $SubItem > 0 Then
;~                      DllStructSetData($tRect, 1, DllStructGetData($tRect, 1) + 2)
;~                      DllStructSetData($tRect, 4, DllStructGetData($tRect, 4) - 2)
;~                      DllStructSetData($tRect, 3, DllStructGetData($tRect, 3) - 1)
;~                      DllStructSetData($tRect, 2, DllStructGetData($tRect, 2) + 1)
;~                  EndIf
;~                  _WinAPI_FillRect($hDC, DllStructGetPtr($tRect), _WinAPI_CreateSolidBrush(0xD0D0D0))
;~                  If $SubItem < 1 Then
;~                      DllStructSetData($tRect, 1, DllStructGetData($tRect, 1) + 5)
;~                      DllStructSetData($tRect, 4, DllStructGetData($tRect, 4) + 1)
;~                  ElseIf $SubItem > 0 Then
;~                      DllStructSetData($tRect, 1, DllStructGetData($tRect, 1) + 4)
;~                      DllStructSetData($tRect, 4, DllStructGetData($tRect, 4) + 1)
;~                  EndIf
;~                  Global $sText = _GUICtrlListView_GetItemText($hWndFrom, $Index, $SubItem)
;~                  _WinAPI_SetBkMode($hDC, $TRANSPARENT)
;~                  _WinAPI_SelectObject($hDC, _SendMessage($hWndFrom, $WM_GETFONT))
;~                  _WinAPI_DrawText($hDC, $sText, $tRect,BitOR($DT_VCENTER, $DT_END_ELLIPSIS, $DT_SINGLELINE))
;~                  Global $bText=$sText
;~                  $Clear=True
                EndSwitch
    EndSwitch

    Return $GUI_RUNDEFMSG
EndFunc


Func WM_COMMAND($hWnd, $Msg, $wParam, $lParam)
    $iCode = BitShift($wParam, 16)
    Switch $lParam
        Case $RichEdit
            Switch $iCode
                Case $EN_KILLFOCUS
                    Update_Text()
            EndSwitch
    EndSwitch
EndFunc



Func Update_Text()
    $RichEdit_Text = _GUICtrlEdit_GetText($RichEdit)
    _GUICtrlListView_SetItemText($hListView, $Index, StringStripWS($RichEdit_Text, 3), $SubItem)
    _WinAPI_ReleaseDC($RichEdit, $hDC)
    _WinAPI_DestroyWindow($RichEdit)
EndFunc

I created code to highlight a certain item in a listview. But when I use _GUICtrlListView_SimpleSort to sort data in listview, this is only get data in first column to redraw . Now, I want redraw item and subitems of this item. Please help me !

 

Link to comment
Share on other sites

I can't see any issue with it once I fixed a couple of bugs (namely that SimpleSort takes the 2nd argument by reference, for some reason the listview is never recognised as being in report view, and your structure didn't work). 

The code has a lot of stuff that isn't used, making it a little tricky to figure out what it is you want to happen that doesn't already work.

#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <GuiListView.au3>
#include <GuiEdit.au3>
#include <FontConstants.au3>
#include <WinAPI.au3>
#include <ColorConstants.au3>
#include <GDIPlus.au3>
#include <GuiRichEdit.au3>
#include <ButtonConstants.au3>
Global $hEdit, $hDC, $hBrush, $Item = -1, $SubItem = 0, $Index


Global $stRect = DllStructCreate("int;int;int;int")

Global $Start = True

Global $Clear = False

Global $tRect

Global $RichEdit

$Font = _WinAPI_CreateFont(15, 5, 0, 0, 400, False, False, False, Default, Default, Default, Default, 0, 'Arial')

$hGUI = GUICreate("ListView Subitems edit in place", 300, 210)

$hListView = _GUICtrlListView_Create($hGUI, "Items|SubItems", 2, 2, 296, 210)
_WinAPI_SetFont($hListView, $Font, True)
_GUICtrlListView_SetExtendedListViewStyle($hListView, $LVS_EX_GRIDLINES + $LVS_EX_FULLROWSELECT)
;~ ControlDisable($hGUI, "", HWnd(_GUICtrlListView_GetHeader($hListView)))
_GUICtrlListView_SetColumnWidth($hListView, 1, $LVSCW_AUTOSIZE_USEHEADER)
_GUICtrlListView_SetColumnWidth($hListView, 2, $LVSCW_AUTOSIZE_USEHEADER)
For $i = 1 To 10
    _GUICtrlListView_AddItem($hListView, "Item " & $i)
    _GUICtrlListView_AddSubItem($hListView, $i - 1, "SubItem " & $i, 1)
Next
$hButton = GUICtrlCreateButton("", 0, 0, 0, 0, BitOR($GUI_SS_DEFAULT_BUTTON, $BS_DEFPUSHBUTTON))
GUICtrlSetState($hButton, $GUI_HIDE)



GUIRegisterMsg($WM_NOTIFY, "WM_NOTIFY")
GUIRegisterMsg($WM_COMMAND, "WM_COMMAND")

GUISetState()






While 1
    Switch GUIGetMsg()
        Case $GUI_EVENT_CLOSE
            ExitLoop
        Case $hButton
            Update_Text()
    EndSwitch
WEnd


Func WM_NOTIFY($hWnd, $iMsg, $iwParam, $ilParam)
    Local $tNMHDR, $hWndFrom, $iCode
    $tNMHDR = DllStructCreate($tagNMHDR, $ilParam)
    $hWndFrom = DllStructGetData($tNMHDR, "hWndFrom")
    $iCode = DllStructGetData($tNMHDR, 3)
    Switch $hWndFrom
        Case $hListView
            Switch $iCode
                Case $NM_CUSTOMDRAW
                    ; If Not _GUICtrlListView_GetViewDetails($hWndFrom) Then Return $GUI_RUNDEFMSG
                    Local $tCustDraw = DllStructCreate($tagNMLVCUSTOMDRAW, $ilParam), $iDrawStage, $iItem, $iSubitem, $hDC, $tRect, $iColor1, $iColor2, $iColor3
                    $iDrawStage = DllStructGetData($tCustDraw, 'dwDrawStage')
                    Switch $iDrawStage
                        Case $CDDS_PREPAINT
                            Return $CDRF_NOTIFYITEMDRAW
                        Case $CDDS_ITEMPREPAINT
                            Return $CDRF_NOTIFYSUBITEMDRAW
                        Case $CDDS_ITEMPOSTPAINT
                        Case BitOR($CDDS_ITEMPREPAINT, $CDDS_SUBITEM)
                            $iItem = DllStructGetData($tCustDraw, 'dwItemSpec')
                            $iSubitem = DllStructGetData($tCustDraw, 'iSubItem')
                            If _GUICtrlListView_GetItemSelected($hWndFrom, $iItem) Then
                                $hDC = _WinAPI_GetDC($hWndFrom)
                                $tRect = DllStructCreate($tagRECT)
                                If $iSubitem = 0 Then
                                    _SendMessage($hWndFrom, $LVM_GETSUBITEMRECT, $iItem, DllStructGetPtr($tRect))
                                    DllStructSetData($tRect, 1, 2)
                                    ; DllStructSetData($tRect, 1, DllStructGetData($tRect, 1) - 2)
                                    _WinAPI_FillRect($hDC, DllStructGetPtr($tRect), _WinAPI_CreateSolidBrush(0XEAEAEA))
                                EndIf
                                DllStructSetData($tRect, 1, 2)
                                DllStructSetData($tRect, 2, $iSubitem)
                                _SendMessage($hWndFrom, $LVM_GETSUBITEMRECT, $iItem, DllStructGetPtr($tRect))
                                Local $sText = _GUICtrlListView_GetItemText($hWndFrom, $iItem, $iSubitem)
                                _WinAPI_SelectObject($hDC, $Font)
                                _WinAPI_SetBkMode($hDC, $TRANSPARENT)
                                $GetColumnWidth = _GUICtrlListView_GetColumnWidth($hWndFrom, 0) / 2
                                $GetStringWidth = _GUICtrlListView_GetStringWidth($hWndFrom, $sText)
;~                                 DllStructSetData($tRect, 1, DllStructGetData($tRect, 1)+ $GetColumnWidth -($GetStringWidth/2)-2)
                                DllStructSetData($tRect, 2, DllStructGetData($tRect, 2) + 2)
                                _WinAPI_DrawText($hDC, $sText, $tRect, $DT_CENTER)
                                _WinAPI_ReleaseDC($hWndFrom, $hDC)
                                Return $CDRF_SKIPDEFAULT
                            EndIf
                            Return $CDRF_NEWFONT
                        Case BitOR($CDDS_ITEMPOSTPAINT, $CDDS_SUBITEM)
                        Case Else
                    EndSwitch
                Case $LVN_COLUMNCLICK
                    $tInfo = DllStructCreate($tagNMLISTVIEW, $ilParam)
                    $iCol = DllStructGetData($tInfo, "SubItem")
                    $bSortSense = False
                    _GUICtrlListView_SimpleSort($hListView, $bSortSense, $iCol, False)


;~              Case $NM_CLICK
;~                  If $Clear=True Then
;~                      DllStructSetData($tRect, 1, DllStructGetData($tRect, 1) - 5)
;~                      DllStructSetData($tRect, 4, DllStructGetData($tRect, 4) - 1)
;~                      _WinAPI_FillRect($hDC, DllStructGetPtr($tRect), _WinAPI_CreateSolidBrush(0xFFFFFF))
;~                      DllStructSetData($tRect, 1, DllStructGetData($tRect, 1) + 5)
;~                      DllStructSetData($tRect, 4, DllStructGetData($tRect, 4) + 1)
;~                      _WinAPI_DrawText($hDC, $bText, $tRect,BitOR($DT_VCENTER, $DT_END_ELLIPSIS, $DT_SINGLELINE))
;~                  EndIf
;~                  $Info   = DllStructCreate($tagNMITEMACTIVATE, $ilParam)
;~                  $Index  = DllStructGetData($Info, "Index")
;~                  $SubItem= DllStructGetData($Info, "SubItem")
;~                  $Sub_Rect=_GUICtrlListView_GetSubItemRect($hListView,$Index,$SubItem)
;~                  $hDC = _WinAPI_GetDC($hWndFrom)
;~                  $tRect = DllStructCreate($tagRECT)
;~                  DllStructSetData($tRect, 1, 2)
;~                  DllStructSetData($tRect, 2, $SubItem)
;~                  _SendMessage($hWndFrom, $LVM_GETSUBITEMRECT, $Index, DllStructGetPtr($tRect))
;~                  If $SubItem < 1 Then
;~                      DllStructSetData($tRect, 1, DllStructGetData($tRect, 1) - 3)
;~                      DllStructSetData($tRect, 4, DllStructGetData($tRect, 4) - 2)
;~                      DllStructSetData($tRect, 3, DllStructGetData($tRect, 3) - 1)
;~                      DllStructSetData($tRect, 2, DllStructGetData($tRect, 2) + 1)
;~                  ElseIf $SubItem > 0 Then
;~                      DllStructSetData($tRect, 1, DllStructGetData($tRect, 1) + 2)
;~                      DllStructSetData($tRect, 4, DllStructGetData($tRect, 4) - 2)
;~                      DllStructSetData($tRect, 3, DllStructGetData($tRect, 3) - 1)
;~                      DllStructSetData($tRect, 2, DllStructGetData($tRect, 2) + 1)
;~                  EndIf
;~                  _WinAPI_FillRect($hDC, DllStructGetPtr($tRect), _WinAPI_CreateSolidBrush(0xD0D0D0))
;~                  If $SubItem < 1 Then
;~                      DllStructSetData($tRect, 1, DllStructGetData($tRect, 1) + 5)
;~                      DllStructSetData($tRect, 4, DllStructGetData($tRect, 4) + 1)
;~                  ElseIf $SubItem > 0 Then
;~                      DllStructSetData($tRect, 1, DllStructGetData($tRect, 1) + 4)
;~                      DllStructSetData($tRect, 4, DllStructGetData($tRect, 4) + 1)
;~                  EndIf
;~                  Global $sText = _GUICtrlListView_GetItemText($hWndFrom, $Index, $SubItem)
;~                  _WinAPI_SetBkMode($hDC, $TRANSPARENT)
;~                  _WinAPI_SelectObject($hDC, _SendMessage($hWndFrom, $WM_GETFONT))
;~                  _WinAPI_DrawText($hDC, $sText, $tRect,BitOR($DT_VCENTER, $DT_END_ELLIPSIS, $DT_SINGLELINE))
;~                  Global $bText=$sText
;~                  $Clear=True
            EndSwitch
    EndSwitch

    Return $GUI_RUNDEFMSG
EndFunc   ;==>WM_NOTIFY


Func WM_COMMAND($hWnd, $Msg, $wParam, $lParam)
    $iCode = BitShift($wParam, 16)
    Switch $lParam
        Case $RichEdit
            Switch $iCode
                Case $EN_KILLFOCUS
                    Update_Text()
            EndSwitch
    EndSwitch
EndFunc   ;==>WM_COMMAND



Func Update_Text()
    $RichEdit_Text = _GUICtrlEdit_GetText($RichEdit)
    _GUICtrlListView_SetItemText($hListView, $Index, StringStripWS($RichEdit_Text, 3), $SubItem)
    _WinAPI_ReleaseDC($RichEdit, $hDC)
    _WinAPI_DestroyWindow($RichEdit)
EndFunc   ;==>Update_Text

Edit: Also - it would help if you'd linked to the topic where you got the custom draw code here so that other members could follow what it is supposed to do. https://www.autoitscript.com/forum/topic/123757-focushighlight-a-certain-item-in-a-listview/?do=findComment&comment=859598

Edited by Mat
Link to comment
Share on other sites

Mine redraws fine when sorting, but if I mouseover the subitem immediately after wards it goes blank as you say. That's quite a specific set of steps to reproduce so it's no wonder I didn't see it before.

The issue is that when hovering over the item after sorting, only the first subitem is repainted. Quick fix is to draw the background individually for each subitem, rather than for the whole item once. Just take out the code that draws the background for the whole item, and add just the filling the rectangle in before you draw the text.

OMG. Just looked at the code for SimpleSort. I'll see what I can come up with. 

 

Link to comment
Share on other sites

Well it's going to be a nightmare figuring out what's going on with simple sort, as it moves selection and focus around.

Instead I just quickly implemented a string sort of the items that doesn't require registering.

#include <GuiConstantsEx.au3>
#include <GuiListView.au3>
#include <ListViewConstants.au3>
#include <WindowsConstants.au3>
#include <WinAPI.au3>
#include <StructureConstants.au3>

$GUI = GUICreate("Listview Custom Draw", 400, 300)

$cListView = GUICtrlCreateListView("Column 1|Column 2|Column 3", 2, 2, 394, 268, -1, BitOR($LVS_EX_GRIDLINES, $LVS_EX_FULLROWSELECT))
$hListView = GUICtrlGetHandle($cListView)

; Add items
For $i = 1 To 30
    GUICtrlCreateListViewItem("Row" & $i & ": Col 1|Row" & $i & ": Col 2|Row" & $i & ": Col 3", $cListView)
Next

GUICtrlCreateInput("Click here to test focus", 50, 275, 200, 18)

GUIRegisterMsg($WM_NOTIFY, "WM_NOTIFY")
GUISetState()

Do
Until GUIGetMsg() = $GUI_EVENT_CLOSE

Exit

Func WM_NOTIFY($hWnd, $Msg, $wParam, $lParam)
    Local $hWndFrom, $iIDFrom, $iCode, $tNMHDR

    $tNMHDR = DllStructCreate($tagNMHDR, $lParam)
    $hWndFrom = HWnd(DllStructGetData($tNMHDR, "hWndFrom"))
    $iIDFrom = DllStructGetData($tNMHDR, "IDFrom")
    $iCode = DllStructGetData($tNMHDR, "Code")

    Switch $hWndFrom
        Case $hListView
            Switch $iCode
                Case $NM_CUSTOMDRAW
                    If _GUICtrlListView_GetView($hWndFrom) <> 1 Then Return $GUI_RUNDEFMSG ; Not in details mode

                    Local $tCustDraw, $iDrawStage, $iItem, $iSubitem, $hDC, $tRect, $iColor1, $iColor2, $iColor3

                    $tCustDraw = DllStructCreate($tagNMLVCUSTOMDRAW, $lParam)
                    $iDrawStage = DllStructGetData($tCustDraw, 'dwDrawStage')

                    Switch $iDrawStage
                        Case $CDDS_PREPAINT
                            Return $CDRF_NOTIFYITEMDRAW
                        Case $CDDS_ITEMPREPAINT
                            Return $CDRF_NOTIFYSUBITEMDRAW
                        Case $CDDS_ITEMPOSTPAINT
                            ; Not handled
                        Case BitOR($CDDS_ITEMPREPAINT, $CDDS_SUBITEM)
                            $iItem = DllStructGetData($tCustDraw, 'dwItemSpec')
                            $iSubitem = DllStructGetData($tCustDraw, 'iSubItem')

                            If _GUICtrlListView_GetItemSelected($hWndFrom, $iItem) Then ; Item to draw is selected
                                $hDC = _WinAPI_GetDC($hWndFrom)
                                $tRect = DllStructCreate($tagRECT)

                                ; We draw the background when we draw the first item.
                                If $iSubitem = 0 Then
                                    ; We must send the message as we want to use the struct. _GUICtrlListView_GetSubItemRect returns an array.
                                    _SendMessage($hWndFrom, $LVM_GETSUBITEMRECT, $iItem, DllStructGetPtr($tRect))

                                    DllStructSetData($tRect, "Left", 2)
                                    _WinAPI_FillRect($hDC, DllStructGetPtr($tRect), _WinAPI_GetStockObject($GRAY_BRUSH)) ; Change the bush here. You can use GDI+ to make your own.
                                EndIf

                                DllStructSetData($tRect, "Left", 2)
                                DllStructSetData($tRect, "Top", $iSubitem)
                                _SendMessage($hWndFrom, $LVM_GETSUBITEMRECT, $iItem, DllStructGetPtr($tRect))

                                Local $sText = _GUICtrlListView_GetItemText($hWndFrom, $iItem, $iSubitem)
                                _WinAPI_SetBkMode($hDC, $TRANSPARENT) ; It uses the background drawn for the first item.

                                ; Select the font we want to use
                                _WinAPI_SelectObject($hDC, _SendMessage($hWndFrom, $WM_GETFONT))

                                If $iSubitem = 0 Then
                                    DllStructSetData($tRect, "Left", DllStructGetData($tRect, "Left") + 2)
                                Else
                                    DllStructSetData($tRect, "Left", DllStructGetData($tRect, "Left") + 6)
                                EndIf
                                _WinAPI_DrawText($hDC, $sText, $tRect, BitOR($DT_VCENTER, $DT_END_ELLIPSIS, $DT_SINGLELINE))

                                _WinAPI_ReleaseDC($hWndFrom, $hDC)

                                Return $CDRF_SKIPDEFAULT ; Don't do default processing
                            EndIf

                            Return $CDRF_NEWFONT ; Let the system do the drawing for non-selected items
                        Case BitOR($CDDS_ITEMPOSTPAINT, $CDDS_SUBITEM)
                            ; Not handled
                    EndSwitch

                Case $LVN_COLUMNCLICK
                    $tInfo = DllStructCreate($tagNMLISTVIEW, $lParam)
                    $iCol = DllStructGetData($tInfo, "SubItem")
                    $hHdr = _GUICtrlListView_GetHeader($hWndFrom)

                    ; Work out sort from arrows in header, and clear other arrows
                    $fSort = True
                    For $i = 0 To _GUICtrlHeader_GetItemCount($hHdr)
                        $iFmt = _GUICtrlHeader_GetItemFormat($hHdr, $i)

                        If $i = $iCol Then
                            If BitAND($iFmt, $HDF_SORTUP) Then
                                $fSort = True
                                $iFmt = BitOR(BitAND($iFmt, BitNOT($HDF_SORTUP)), $HDF_SORTDOWN)
                            ElseIf BitAND($iFmt, $HDF_SORTDOWN) Then
                                $fSort = False
                                $iFmt = BitOR(BitAND($iFmt, BitNOT($HDF_SORTDOWN)), $HDF_SORTUP)
                            Else
                                ; Default
                                $iFmt = BitOR(BitAND($iFmt, BitNOT($HDF_SORTUP)), $HDF_SORTDOWN)
                                $fSort = True
                            EndIf

                            _GUICtrlHeader_SetItemFormat($hHdr, $i, $iFmt)
                        Else
                            $iFmt = BitAND($iFmt, BitNOT(BitOR($HDF_SORTUP, $HDF_SORTDOWN)))
                            _GUICtrlHeader_SetItemFormat($hHdr, $i, $iFmt)
                        EndIf
                    Next

                    $tInfo = DllStructCreate("HWND;int;int")
                    DllStructSetData($tInfo, 1, $hWndFrom)
                    DllStructSetData($tInfo, 2, $fSort)
                    DllStructSetData($tInfo, 3, $iCol)

                    $cb = DllCallbackRegister(__Compare, "int", "LPARAM;LPARAM;LPARAM")
                    _SendMessage($hWndFrom, $LVM_SORTITEMSEX, DllStructGetPtr($tInfo), DllCallbackGetPtr($cb))
                    DllCallbackFree($cb)
                    
                    Return True
            EndSwitch
    EndSwitch

    Return $GUI_RUNDEFMSG
EndFunc   ;==>WM_NOTIFY

; int CALLBACK CompareFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort);
Func __Compare($nItem1, $nItem2, $lParamSort)
    Local $tInfo = DllStructCreate("HWND;int;int", $lParamSort)
    Local $hWndFrom = DllStructGetData($tInfo, 1)
    Local $fSort = DllStructGetData($tInfo, 2)
    Local $iCol = DllStructGetData($tInfo, 3)

    Local $s1 = _GUICtrlListView_GetItemText($hWndFrom, $nItem1, $iCol)
    Local $s2 = _GUICtrlListView_GetItemText($hWndFrom, $nItem2, $iCol)

    Return StringCompare($s1, $s2) * ($fSort ? -1 : 1)
EndFunc   ;==>__Compare

This seems to work fine with the custom drawing code.

Link to comment
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
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...