Jump to content

Recommended Posts

Posted (edited)

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

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
×
×
  • Create New...