Quantcast
Channel: AutoIt v3 - General Help and Support
Viewing all articles
Browse latest Browse all 12506

ListView - WM_DrawItem not work with WM_Notify

$
0
0
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:

[ autoit ]         
#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:

[ autoit ]         
;~ #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!

Viewing all articles
Browse latest Browse all 12506

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>