Jump to content
Sign in to follow this  
Trolleule

ListView - WM_DrawItem not work with WM_Notify

Recommended Posts

Trolleule

Hey peoplez,

In All i try to have a listview control which subitems have InputBoxes instead of simple Text. I have a good start, by creating an Edit control with _WinAPI_CreateWindowEx and position it right. That works great.

Then I set the row height of a listview item, because the Edit controls are too small. For that problem i found this code:

#include 
#include 
#include 
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

Global $default_font = "Arial"
Global $default_font_size = 9
Global $GUI_main = GUICreate("", 300, 300, -1, -1, -1, $WS_EX_ACCEPTFILES)
Global $hGUI_tab_listview[2][10]
GUIRegisterMsg($WM_MEASUREITEM, "WM_MEASUREITEM") ;place before listview creation - message sent once for each ownerdrawn control created
$hGUI_tab_listview[0][0] = GUICtrlCreateListView("", 15, 68, 250, 90, _
BitOR($LVS_REPORT, $LVS_SHOWSELALWAYS, $LVS_OWNERDRAWFIXED), _
BitOR($LVS_EX_FULLROWSELECT, $LVS_EX_GRIDLINES)) ; + $LVS_EX_CHECKBOXES + $LVS_SINGLESEL
GUICtrlSetFont(-1, $default_font_size + 8, 400, 0, $default_font, 5)
_GUICtrlListView_AddColumn(-1, "Name")
_GUICtrlListView_SetColumnWidth(-1, 0, 155)
_GUICtrlListView_AddColumn(-1, "Count")
_GUICtrlListView_SetColumnWidth(-1, 1, 72)
For $i = 0 To 10 ; populate the listview for testing purposes
_GUICtrlListView_AddItem(-1, "test " & $i)
_GUICtrlListView_AddSubItem(-1, $i, $i, 1)
Next

GUIRegisterMsg($WM_DRAWITEM, "WM_DRAWITEM")
GUISetState(@SW_SHOW)
While 1
Sleep(100)
WEnd
Exit

Func WM_MEASUREITEM($hWnd, $Msg, $wParam, $lParam)
Local $tMEASUREITEMS = DllStructCreate("uint cType;uint cID;uint itmID;uint itmW;uint itmH;ulong_ptr itmData", $lParam)
If DllStructGetData($tMEASUREITEMS, "cType") <> $ODT_LISTVIEW Then Return $GUI_RUNDEFMSG
DllStructSetData($tMEASUREITEMS, "itmH", 20);row height
;GUIRegisterMsg($WM_MEASUREITEM, "") ;call this after last ownerdrawn listview created
Return 1
EndFunc ;==>WM_MEASUREITEM

Func WM_DRAWITEM($hWnd, $Msg, $wParam, $lParam)
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 $cID ; will look for ControlID, not window handle.
Case $hGUI_tab_listview[0][0]
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:
$local_alignment = $DT_LEFT
For $i = 0 To _GUICtrlListView_GetColumnCount($hGUI_tab_listview[0][0]) - 1
; 1. get subitem text:
Local $iSubItmText = _GUICtrlListView_GetItemText($hGUI_tab_listview[0][0], $itmID, $i)
; 2. get subitem coordinates for drawing its respective text
Local $aSubItmRect = _GUICtrlListView_GetSubItemRect($hGUI_tab_listview[0][0], $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", $local_alignment)
Next
;#ce
EndSwitch
EndSwitch
Return $GUI_RUNDEFMSG
EndFunc ;==>WM_DRAWITEM

That works fine too. It's an UDF and the user used WM_DrawItem

Now I try to have Edit Controls + adjusted row height. I combined both, but have problem, when i resize a column. When i resize the column, the edit control resizes too, but then the items are gone.

Here the code where i combined both:

;~ #include

;~ #include
#include ; used for Lo/Hi word
#include
#include

#include
#include
#include

#include
#include
#include

#include
#include
#include
#include
#include
#include

Global $aProgress[1][4]

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

Global Const $SW_HIDE = 0
Global Const $SW_SHOW = 5

Global $default_font = "Arial"
Global $default_font_size = 9

global $count = 0

$hGui = GUICreate("ListView with progressbar", 520, 400, -1, -1, BitOR($GUI_SS_DEFAULT_GUI, $WS_SIZEBOX))

GUIRegisterMsg($WM_MEASUREITEM, "WM_MEASUREITEM") ;place before listview creation - message sent once for each ownerdrawn control created
;~ GUIRegisterMsg($WM_NOTIFY, "WM_DRAWITEM") ; "_ListView_Notify" ; das macht probleme
;~ GUIRegisterMsg($WM_SIZE, "WM_DRAWITEM")


;~ $hListView = _GUICtrlListView_Create($hGui, "Files|Path|Progress", 10, 10, 450, 200, BitOR($LVS_REPORT, $LVS_SHOWSELALWAYS, $LVS_OWNERDRAWFIXED))
$test = GUIRegisterMsg($WM_NOTIFY, "_ListView_Notify2") ;

;~ MsgBox(0, "sdfdsf", $test)



$hListView = GUICtrlCreateListView("Files|Path|Progress", 10, 10, 450, 250, BitOR($LVS_REPORT, $LVS_SHOWSELALWAYS, $LVS_OWNERDRAWFIXED))
_GUICtrlListView_SetExtendedListViewStyle($hListView, BitOR($LVS_EX_TRACKSELECT, $LVS_EX_FULLROWSELECT))
_GUICtrlListView_JustifyColumn($hListView, 0, 2) ; 2 = center
;~ GUICtrlSetFont(-1, $default_font_size + 12, 400, 0, $default_font, 5)



For $i = 0 To 10 ; populate the listview for testing purposes
_GUICtrlListView_AddItem(-1, "test " & $i)
_GUICtrlListView_AddSubItem(-1, $i, $i, 1)
Next

;~ GUIRegisterMsg($WM_NOTIFY, "_ListView_Notify2")

$hProgress3 = _ListView_InsertProgressBar($hListView, 0, 1)
_Progress_SetBarColor($hProgress3,0x0000FF)

;~ _ArrayDisplay($aProgress)


GUIRegisterMsg($WM_DRAWITEM, "WM_DRAWITEM")
;~ GUIRegisterMsg($WM_DRAWITEM, "_ListView_Notify")
GUISetState(@SW_SHOW)


Func WM_MEASUREITEM($hWnd, $Msg, $wParam, $lParam)
Local $tMEASUREITEMS = DllStructCreate("uint cType;uint cID;uint itmID;uint itmW;uint itmH;ulong_ptr itmData", $lParam)
If DllStructGetData($tMEASUREITEMS, "cType") <> $ODT_LISTVIEW Then Return $GUI_RUNDEFMSG
DllStructSetData($tMEASUREITEMS, "itmH", 25);row height
;GUIRegisterMsg($WM_MEASUREITEM, "") ;call this after last ownerdrawn listview created
Return 1
EndFunc ;==>WM_MEASUREITEM


Func WM_DRAWITEM($hWnd, $Msg, $wParam, $lParam)
Local $tagDRAWITEMSTRUCT, $iBrushColor, $cID, $itmID, $itmAction, $itmState, $hItm, $hDC, $bSelected
Local $tNMHEADER, $hWndFrom, $iCode, $i ; edit control variables
;~ GUIRegisterMsg($WM_NOTIFY, "_ListView_Notify")

$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)

;~ $tNMHEADER = DllStructCreate($tagNMHEADER, $lParam)
;~ $hWndFrom = DllStructGetData($tNMHEADER, "hwndFrom")
;~ $iCode = DllStructGetData($tNMHEADER, "Code")

;~ MsgBox(0, "asdsad", $tNMHEADER & " " & $hWndFrom & " " & $iCode & " ")

;~ If $iCode <> $LVN_ENDSCROLL Then $hWndFrom = _WinAPI_GetParent($hWndFrom)

;~ $hWndFrom = _WinAPI_GetParent($hWndFrom)

;~ For $i = 1 To $aProgress[0][0]
;~ MsgBox(0, "sdfsd", "drinne")
;~ If $aProgress[$i][3] = $hWndFrom Then _
;~ _MoveProgress($hWndFrom, $aProgress[$i][0], $aProgress[$i][1], $aProgress[$i][2])
;~ Next
;~ _WinAPI_InvalidateRect($hWndFrom)

Switch $cID ; will look for ControlID, not window handle.
Case $hListView
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:
$local_alignment = $DT_LEFT

For $i = 0 To _GUICtrlListView_GetColumnCount($hListView) - 1
; 1. get subitem text:
Local $iSubItmText = _GUICtrlListView_GetItemText($hListView, $itmID, $i)
; 2. get subitem coordinates for drawing its respective text
Local $aSubItmRect = _GUICtrlListView_GetSubItemRect($hListView, $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] + 4, 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", $local_alignment)
$count += 1
ConsoleWrite($count & " hier" & @CR)
Next
;~ MsgBox(0, "sdfdsf", "hier")
;~ _MoveProgress($hWndFrom, $aProgress[$i][0], $aProgress[$i][1], $aProgress[$i][2])

EndSwitch
EndSwitch

Return $GUI_RUNDEFMSG
EndFunc ;==>WM_DRAWITEM

Func _ListView_Notify2($hWnd, $Msg, $wParam, $lParam)
If $Msg = $WM_SIZE Then
_WinAPI_InvalidateRect($hWnd)
Return $GUI_RUNDEFMSG
EndIf

Local $tNMHEADER, $hWndFrom, $iCode, $i

$tNMHEADER = DllStructCreate($tagNMHEADER, $lParam)
$hWndFrom = DllStructGetData($tNMHEADER, "hwndFrom")
$iCode = DllStructGetData($tNMHEADER, "Code")

Switch $iCode
Case $HDN_ITEMCHANGED, $HDN_ITEMCHANGEDW, $LVN_ENDSCROLL
If $iCode <> $LVN_ENDSCROLL Then $hWndFrom = _WinAPI_GetParent($hWndFrom)

For $i = 1 To $aProgress[0][0]
If $aProgress[$i][3] = $hWndFrom Then _
_MoveProgress($hWndFrom, $aProgress[$i][0], $aProgress[$i][1], $aProgress[$i][2])
Next

;~ _WinAPI_InvalidateRect($hWndFrom)
EndSwitch
GUIRegisterMsg($WM_DRAWITEM, "WM_DRAWITEM")
Return $GUI_RUNDEFMSG
EndFunc ;==>_ListView_Notify






; #FUNCTION# ======================================================================================
; Function Name: _ListView_InsertProgressBar()
; Description: Inserts a progressbar control in the ListView control.
; Syntax.........: _ListView_InsertProgressBar($sHwnd, $sItemIndex[, $sSubItemIndex])
; Parameter(s): $sHwnd - Handle to the ListView control.
; $sItemIndex - Zero based index of the item at which the progressbar should be inserted.
; $sSubItemIndex - [Optional] One based index of the subitem where progressbar should be placed, default is 1.
;
; Return Value(s): Returns the identifier (controlID) of the new progressbar control.
; Requirement(s): AutoIt 3.2.10.0 and above
; Note(s): Optimal amount of progressbar controls is 5-10. Don`t abuse with many amount of progressbar controls.
;
; Author(s): R.Gilman (a.k.a rasim), arcker
;==================================================================================================
Func _ListView_InsertProgressBar($sHwnd, $sItemIndex, $sSubItemIndex = 0)
If Not IsHWnd($sHwnd) Then $sHwnd = GUICtrlGetHandle($sHwnd)

Local $iStyle = _WinAPI_GetWindowLong($sHwnd, $GWL_STYLE)

If BitAND($iStyle, $WS_CLIPCHILDREN) <> $WS_CLIPCHILDREN Then
_WinAPI_SetWindowLong($sHwnd, $GWL_STYLE, BitOR($iStyle, $WS_CLIPCHILDREN))
EndIf

Local $aRect

If $sSubItemIndex = 0 Then
$aRect = _GUICtrlListView_GetItemRect($sHwnd, $sItemIndex, 2)
Else
$aRect = _GUICtrlListView_GetSubItemRect($sHwnd, $sItemIndex, $sSubItemIndex)
EndIf

$aProgress[0][0] += 1
ReDim $aProgress[$aProgress[0][0] + 1][4]
$aProgress[$aProgress[0][0]][0] = _Progress_Create($sHwnd, $aRect[0] + 6, $aRect[1] + 2, ($aRect[2] - $aRect[0]) - 12, ($aRect[3] - $aRect[1]) - 4)

$aProgress[$aProgress[0][0]][1] = $sItemIndex
$aProgress[$aProgress[0][0]][2] = $sSubItemIndex
$aProgress[$aProgress[0][0]][3] = $sHwnd

Return $aProgress[$aProgress[0][0]][0]
EndFunc ;==>_ListView_InsertProgressBar

Func _Progress_Create($hWnd, $iX, $iY, $iWidth = -1, $iHeight = -1, $iStyle = 0, $iExStyle = 0)

$iExStyle = 0x00000200
$iStyle = BitOR($WS_TABSTOP, $WS_CHILD, $WS_VISIBLE, $ES_LEFT, $ES_AUTOHSCROLL, $ES_NOHIDESEL)

Local $hEdit = _WinAPI_CreateWindowEx($iExStyle, "EDIT", "", $iStyle, $iX, $iY, $iWidth, $iHeight, $hWnd)
_SendMessage($hEdit, $__EDITCONSTANT_WM_SETFONT, _WinAPI_GetStockObject($__EDITCONSTANT_DEFAULT_GUI_FONT), True)
_GUICtrlEdit_SetLimitText($hEdit, 0)

;~ Return _WinAPI_CreateWindowEx($iExStyle, "EDIT", "", $iStyle, $iX, $iY, $iWidth, $iHeight, $hWnd)
Return $hEdit
EndFunc ;==>_Progress_Create







Func _MoveProgress($hListView, $hProgress, $sItemIndex, $sSubItemIndex)
Local $aRect

If $sSubItemIndex = 0 Then
$aRect = _GUICtrlListView_GetItemRect($hListView, $sItemIndex, 2)
Else
$aRect = _GUICtrlListView_GetSubItemRect($hListView, $sItemIndex, $sSubItemIndex)
EndIf

If $aRect[1] < 10 Then
_WinAPI_ShowWindow($hProgress, $SW_HIDE)
ElseIf $aRect[1] >= 10 Then
_WinAPI_ShowWindow($hProgress, $SW_SHOW)
EndIf

_WinAPI_MoveWindow($hProgress, $aRect[0], $aRect[1], $aRect[2] - $aRect[0], $aRect[3] - $aRect[1], True)
EndFunc ;==>_MoveProgress


; #FUNCTION# ====================================================================================================
; Description ...: Sets the color of the indicator bar
; Parameters ....: $hWnd - Handle to the control
; $iColor - The new progress indicator bar color. Specify the CLR_DEFAULT value to cause the progress bar
; +to use its default progress indicator bar color.
; Return values .: Success - The previous progress indicator bar color, or CLR_DEFAULT if the progress indicator bar color
; +is the default color.
; Author ........: Paul Campbell (PaulIA), Updated By Arcker
; Remarks .......: This message is supported only in the Windows Classic theme
; Related .......:
; ====================================================================================================
Func _Progress_SetBarColor($hWnd, $iColor)
Return _SendMessage($hWnd, $PBM_SETBARCOLOR, 0, $iColor)
EndFunc










Do
Until GUIGetMsg() = $GUI_EVENT_CLOSE

Sorry the code has no order, you can see i made a lot of tests there but damn nothing seems to work nearly.

I have no idea how i get it to work, please help me!

Thank you guys!

Edited by Trolleule

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  

×