Jump to content

Move controls within a ListView with WM_PAINT


Recommended Posts

Hi,

i have covered the old ListView_Progress UDF but instead of moving the controls on WM_NOTIFY, i want to move them on WM_PAINT, cause i think i can get better performance with it, but on rezising the columns the GUI gets freezed.

Doese someone know how to avoid to get stucked?

#include <GuiConstantsEx.au3>
#include <WindowsConstants.au3>
#include <FontConstants.au3>
#include <GuiListView.au3>
#include <Constants.au3>
#include <WinAPIGdi.au3>
#include <ListView_Progress.au3>
#include <WinAPISys.au3>
#include <WinAPIShellEx.au3>

Opt('MustDeclareVars', 1)

Global $hGUI, $cListView, $hListView
Global $iDllUSER32 = DllOpen("user32.dll")

Global Const $ODT_LISTVIEW = 102
Global Const $ODA_DRAWENTIRE = 0x1
Global Const $ODA_SELECT = 0x2
Global Const $ODA_FOCUS = 0x4
Global Const $ODS_SELECTED = 0x0001


$hGUI = GUICreate("Set Listview Header Colour ", 500, 500)
$cListView = GUICtrlCreateListView("Items List", 10, 10, 480, 480, BitOR($LVS_REPORT, $LVS_SHOWSELALWAYS, $WS_BORDER));, $LVS_OWNERDRAWFIXED))
$hListView = GUICtrlGetHandle($cListView)
_GUICtrlListView_SetExtendedListViewStyle($hListView, BitOR($LVS_EX_DOUBLEBUFFER, $LVS_EX_GRIDLINES, $LVS_EX_FULLROWSELECT))

; Register DLL callback that will be used as window subclass procedure
Global $g_hDll = DllCallbackRegister('_SubclassProc', 'lresult', 'hwnd;uint;wparam;lparam;uint_ptr;dword_ptr')
Global $g_pDll = DllCallbackGetPtr($g_hDll)

; Install window subclass callback
_WinAPI_SetWindowSubclass($hListView, $g_pDll, 1000, 0)


_SendMessage($hListView, $LVM_SETTEXTBKCOLOR, 0, 0xFFFFFF) ; trick to get better performance

_GUICtrlListView_BeginUpdate($hListView)
For $i = 1 To 15
    GUICtrlCreateListViewItem("", $cListView)
    _ListView_InsertProgressBar($hListView, $i-1, 0) ; insert control
Next
_GUICtrlListView_EndUpdate($hListView)


GUIRegisterMsg($WM_DRAWITEM, "WM_DRAWITEM")
GUISetState()

Do
Until GUIGetMsg() = $GUI_EVENT_CLOSE

GUIDelete()
Exit


Func _SubclassProc($hWnd, $iMsg, $wParam, $lParam, $iID, $pData)
    #forceref $iID, $pData

    ConsoleWrite("Proc $hWnd: " & $hWnd  & " imsg: " & $iMsg & " $wParam: " & $wParam & " $lParam: " & $lParam & @CRLF)

    Switch $iMsg
        Case $WM_NCPAINT
        Case $WM_SIZE
        Case $WM_ERASEBKGND
        Case $WM_PAINT
            Local $struct
            _WinAPI_BeginPaint($hWnd, $struct)

            For $i = 1 To $aProgress[0][0]
                If $aProgress[$i][3] = $hWnd Then _
                _MoveProgress($hWnd, $aProgress[$i][0], $aProgress[$i][1], $aProgress[$i][2]) ; move controls
            Next
            _WinAPI_EndPaint($hWnd, $struct)
    EndSwitch


    Return _WinAPI_DefSubclassProc($hWnd, $iMsg, $wParam, $lParam)
EndFunc   ;==>_SubclassProc


; not used yet
Func WM_DRAWITEM($hWnd, $Msg, $wParam, $lParam)
;~  ConsoleWrite("Draw   $hWnd: " & $hWnd  & " imsg: " & $Msg & " $wParam: " & $wParam & " $lParam: " & $lParam & @CRLF)
    Local $tagDRAWITEMSTRUCT, $iBrushColor, $cID, $itmID, $itmAction, $itmState, $hItm, $hDC, $bSelected
    $tagDRAWITEMSTRUCT = DllStructCreate( _
       "uint cType;" & _
       "uint cID;" & _
       "uint itmID;" & _
       "uint itmAction;" & _
       "uint itmState;" & _
       "hwnd hItm;" & _
       "handle hDC;" & _
       "long itmRect[4];" & _
       "ulong_ptr itmData" _
       , $lParam)
    If DllStructGetData($tagDRAWITEMSTRUCT, "cType") <> $ODT_LISTVIEW Then Return $GUI_RUNDEFMSG
    $cID = DllStructGetData($tagDRAWITEMSTRUCT, "cID")
    $itmID = DllStructGetData($tagDRAWITEMSTRUCT, "itmID")
    $itmAction = DllStructGetData($tagDRAWITEMSTRUCT, "itmAction")
    $itmState = DllStructGetData($tagDRAWITEMSTRUCT, "itmState")
    $hItm = DllStructGetData($tagDRAWITEMSTRUCT, "hItm")
    $hDC = DllStructGetData($tagDRAWITEMSTRUCT, "hDC")
    $bSelected = BitAND($itmState, $ODS_SELECTED)
        Switch $itmAction
            Case $ODA_DRAWENTIRE
                ; don't forget, this is BGR, not RGB
                If $itmState = $bSelected Then ; item is not selected
                    $iBrushColor = 0xCCEECC
                Else ; item is selected
                    $iBrushColor = 0xEEDDBB
                EndIf
                Local $aBrush = DllCall("gdi32.dll", "hwnd", "CreateSolidBrush", "int", $iBrushColor)
                Local $aBrushOld = _WinAPI_SelectObject($hDC, $aBrush[0])
                Local $iLeft = DllStructGetData($tagDRAWITEMSTRUCT, "itmRect", 1)
                DllStructSetData($tagDRAWITEMSTRUCT, "itmRect", $iLeft + 1, 1) ; rectangle coordinates for coloring
                ; +1 is the left margin
                _WinAPI_FillRect($hDC, DllStructGetPtr($tagDRAWITEMSTRUCT, "itmRect"), $aBrush[0])
                _WinAPI_SelectObject($hDC, $aBrushOld)
                _WinAPI_DeleteObject($aBrush[0])
                ; for all columns of the row:
                ConsoleWrite("hITm: " & $hItm & @CRLF)
                For $i = 0 To _GUICtrlListView_GetColumnCount($hItm) - 1
                    ; 1. get subitem text:
                    Local $iSubItmText = _GUICtrlListView_GetItemText($hItm, $itmID);, $i)
                    ; 2. get subitem coordinates for drawing its respective text
                    Local $aSubItmRect = _GUICtrlListView_GetSubItemRect($hItm, $itmID, $i)
                    ; the function above accepts not only subitems (one-based index), but also main item (index=0)
                    ; 3. pass the coordinates to a DLL struct
                    Local $iSubItmRect = DllStructCreate("long[4]")
                    DllStructSetData($iSubItmRect, 1, $aSubItmRect[0] + 6, 1) ; +6 is left margin (X)
                    DllStructSetData($iSubItmRect, 1, $aSubItmRect[1] + (-2), 2) ; + (-2) is upper margin (Y)
                    DllStructSetData($iSubItmRect, 1, $aSubItmRect[2], 3)
                    DllStructSetData($iSubItmRect, 1, $aSubItmRect[3], 4)
                    DllCall("user32.dll", "int", "DrawTextW", "hwnd", $hDC, "wstr", $iSubItmText, "int", StringLen($iSubItmText), _
                        "ptr", DllStructGetPtr($iSubItmRect), "int", $DT_LEFT)
                Next
        EndSwitch

    Return $GUI_RUNDEFMSG
EndFunc   ;==>WM_DRAWITEM

ListView_Progress.au3

Link to comment
Share on other sites

wow thanks for this information, i never thought about a bug. But what is the solution? Do i take

Func CallWindowProc($lpPrevWndFunc, $hWnd, $Msg, $wParam, $lParam)
  Return DllCall("user32.dll", "lresult", "CallWindowProc", "ptr", $lpPrevWndFunc, "hwnd", $hWnd, "uint", $Msg, "wparam", $wParam, "lparam", $lParam)[0]
EndFunc 

instead of _WinAPI_CallWindowProc?

And since when is it possible to access an array in this way?

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...