Andreik Posted August 21 Share Posted August 21 What do you think about this code? Bug or intended behavior? #include <GuiListView.au3> #include <Array.au3> $hGUI = GUICreate('Test', 400, 400) $cList = GUICtrlCreateListView('Col 1|Col 2|Col 3', 10, 10, 380, 380) GUISetState(@SW_SHOW, $hGUI) GUICtrlCreateListViewItem('Row 1 - Col 1|Row 1 - Col 2|Row 1 - Col 3', $cList) GUICtrlCreateListViewItem('Row 2 - Col 1|Row 2 - Col 2|Row 2 - Col 3', $cList) GUICtrlCreateListViewItem('Row 3 - Col 1|Row 3 - Col 2|Row 3 - Col 3', $cList) _GUICtrlListView_SetItemSelected($cList, 1, True) $iSelected = _GUICtrlListView_GetSelectedIndices($cList) ; Oups - this fails $aText = _GUICtrlListView_GetItemTextArray($cList, $iSelected) _ArrayDisplay($aText) ; This works $aText = _GUICtrlListView_GetItemTextArray($cList, Number($iSelected)) _ArrayDisplay($aText) ; This is 0-based sub item index, not 1-based as it's stated in the help file MsgBox(0, '', _GUICtrlListView_GetItemText($cList, Number($iSelected), 1)) Do Until GUIGetMsg() = -3 It looks like AutoIt does care in some cases about the data type used for some parameters in _GUICtrlListView_* functions (_GUICtrlListView_GetItemTextArray it's not the only function with this behavior). For some reason if the index it's not a number these functions fails. This has been encountered before by others but never properly addressed. Even if I suspect AutoIt internally it's confused sometimes about how to interpret data types, at least the UDF functions should ensure that proper data types are passed as parameters when some WinAPIs are called. Also it looks like the documentation it's dubious around sub item index in _GUICtrlListView_GetItemText() claiming it's 1-based when it's 0-based as shown in the example above. Any thoughts are appreciated. When the words fail... music speaks. Link to comment Share on other sites More sharing options...
argumentum Posted August 21 Share Posted August 21 Func _GUICtrlListView_GetItemTextString($hWnd, $iItem = -1) Local $sRow = "", $sSeparatorChar = Opt('GUIDataSeparatorChar'), $iSelected If $iItem = -1 Then $iSelected = _GUICtrlListView_GetNextItem($hWnd) ; get current row selected Else $iSelected = $iItem + 1 - 1 ; get row ; "+ 1 - 1" by argumentum EndIf ; here is required to check if _GUICtrlListView_GetNextItem() has failed If $iSelected < 0 Or $iSelected > _GUICtrlListView_GetItemCount($hWnd) - 1 Then Return SetError(1, 0, 0) For $x = 0 To _GUICtrlListView_GetColumnCount($hWnd) - 1 $sRow &= _GUICtrlListView_GetItemText($hWnd, $iSelected, $x) & $sSeparatorChar Next Return StringTrimRight($sRow, 1) EndFunc ;==>_GUICtrlListView_GetItemTextString would this do it ? ( y'all MVPs ) Follow the link to my code contribution ( and other things too ). FAQ - Please Read Before Posting. Link to comment Share on other sites More sharing options...
Andreik Posted August 22 Author Share Posted August 22 @argumentum forcing some arithmetics would definitely convert the index to a number but it's just a local fix and this issue hits in other functions as well. For a general fix I think GUICtrlSendMsg() should ensure (and convert if it's neccesarily) that parameters have proper data types. The example below highlights the real issue. #include <GuiListView.au3> $hGUI = GUICreate('Test', 400, 400) $cList = GUICtrlCreateListView('Col 1|Col 2|Col 3', 10, 10, 380, 380) GUISetState(@SW_SHOW, $hGUI) GUICtrlCreateListViewItem('Row 1 - Col 1|Row 1 - Col 2|Row 1 - Col 3', $cList) GUICtrlCreateListViewItem('Row 2 - Col 1|Row 2 - Col 2|Row 2 - Col 3', $cList) GUICtrlCreateListViewItem('Row 3 - Col 1|Row 3 - Col 2|Row 3 - Col 3', $cList) _GUICtrlListView_SetItemSelected($cList, 1, True) $iSelected = _GUICtrlListView_GetSelectedIndices($cList) $tBuffer = DllStructCreate('char Text[4096]') $tItem = DllStructCreate($tagLVITEM) $tBuffer.Text = '' $tItem.Mask = $LVIF_TEXT $tItem.SubItem = 0 $tItem.Text = DllStructGetPtr($tBuffer) $tItem.TextMax = DllStructGetSize($tBuffer) GUICtrlSendMsg($cList, $LVM_GETITEMTEXTA, $iSelected, DllStructGetPtr($tItem)) ConsoleWrite('Text: ' & $tBuffer.Text & @CRLF) GUICtrlSendMsg($cList, $LVM_GETITEMTEXTA, Number($iSelected), DllStructGetPtr($tItem)) ConsoleWrite('Text: ' & $tBuffer.Text & @CRLF) Do Until GUIGetMsg() = -3 Is there any case when wParam or lParam are not integers? If not then the function should always convert the parameter to the proper signed/unsigned integer. When the words fail... music speaks. Link to comment Share on other sites More sharing options...
argumentum Posted August 22 Share Posted August 22 (edited) 31 minutes ago, Andreik said: ...arithmetics would definitely convert the index to a number but it's just a local fix... I was hoping for @jpm to look at it. I don't have a setup to look at the current beta. Reformatted my PC and haven't reinstall the MVP setup yet My all encompassing fix: Spoiler expandcollapse popupFunc __GUICtrl_SendMsg($hWnd, $iMsg, $iIndex, ByRef $tItem, $tBuffer = 0, $bRetItem = False, $iElement = -1, $bRetBuffer = False, $iElementMax = $iElement) If $iElement > 0 Then DllStructSetData($tItem, $iElement, DllStructGetPtr($tBuffer)) If $iElement = $iElementMax Then DllStructSetData($tItem, $iElement + 1, DllStructGetSize($tBuffer)) EndIf Local $iRet If IsHWnd($hWnd) Then If _WinAPI_InProcess($hWnd, $__g_hGUICtrl_LastWnd) Then $iRet = DllCall("user32.dll", "lresult", "SendMessageW", "hwnd", $hWnd, "uint", $iMsg, "wparam", $iIndex, "struct*", $tItem)[0] Else Local $iItem = DllStructGetSize($tItem) Local $tMemMap, $pText Local $iBuffer = 0 If ($iElement > 0) Or ($iElementMax = 0) Then $iBuffer = DllStructGetSize($tBuffer) Local $pMemory = _MemInit($hWnd, $iItem + $iBuffer, $tMemMap) If $iBuffer Then $pText = $pMemory + $iItem If $iElementMax Then DllStructSetData($tItem, $iElement, $pText) Else $iIndex = $pText EndIf _MemWrite($tMemMap, $tBuffer, $pText, $iBuffer) EndIf _MemWrite($tMemMap, $tItem, $pMemory, $iItem) $iRet = DllCall("user32.dll", "lresult", "SendMessageW", "hwnd", $hWnd, "uint", $iMsg, "wparam", $iIndex, "ptr", $pMemory)[0] If $iBuffer And $bRetBuffer Then _MemRead($tMemMap, $pText, $tBuffer, $iBuffer) If $bRetItem Then _MemRead($tMemMap, $pMemory, $tItem, $iItem) _MemFree($tMemMap) EndIf Else $iRet = GUICtrlSendMsg($hWnd, $iMsg, $iIndex + 1 - 1, DllStructGetPtr($tItem)) EndIf Return $iRet EndFunc ;==>__GUICtrl_SendMsg ...because it all boils down to that =/ Edited August 22 by argumentum more Follow the link to my code contribution ( and other things too ). FAQ - Please Read Before Posting. Link to comment Share on other sites More sharing options...
jpm Posted August 23 Share Posted August 23 Hi, As the return can be several values separated by "|" it is normal for me that the return is a string even if only one is returned Melba23 1 Link to comment Share on other sites More sharing options...
argumentum Posted August 23 Share Posted August 23 52 minutes ago, jpm said: ...it is normal for me that the return is a string... if __GUICtrl_SendMsg() gets patch along the lines of the change I made: $iRet = GUICtrlSendMsg($hWnd, $iMsg, $iIndex + 1 - 1, DllStructGetPtr($tItem)) That would solve all these to behave as expected** ? **because is expected don't mean that is computationally correct but will perform the scripter "wishes/expectations" out of this scripting language. After all, the change does not brake past scripts and makes AutoIt friendlier Follow the link to my code contribution ( and other things too ). FAQ - Please Read Before Posting. Link to comment Share on other sites More sharing options...
Andreik Posted August 23 Author Share Posted August 23 (edited) @jpm In AutoIt we don't really have to care much about data types because AutoIt decides how to interpret the datatype of a variable depending on the situation. I know the result of _GUICtrlListView_GetSelectedIndices() it's a string even for a single item selected, so none question how this function work or what returns. My question it's why AutoIt decides that wParam in GUICtrlSendMsg() can be a string and why it's not converted to the apropriate data type? @argumentum Your fix would work but the real problem it's that the function itself doesn't work correct unless you ensure the parameters have the proper data type, whici is kinda against how AutoIt works in general. It should be the function the one that validate the parameters and decide if a data conversion it's required. I would argue that how GUICtrlSendMsg() works right now it's not how AutoIt works in general. The line below works as expected because the argument of the Cos function it's a number so the string passed as argument it's converted (internally, not by the user) to value zero. This is the expected behavior for GUICtrlSendMsg(), wParam and lParam should be internally converted to proper unsigned / signed integers. MsgBox(0, '', Cos("Whatever")) Edited August 23 by Andreik When the words fail... music speaks. Link to comment Share on other sites More sharing options...
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now