Jump to content

_GuiCtrlTab_GetItem() fails to retrieve item text since Autoit version 3.3.16.0


 Share

Recommended Posts

Hello,

Sorry for my English, I use an automatic translator.
_GuiCtrlTab_GetItem() doesn't seem to return any text since Autoit version 3.3.16.0. It seems to be due to the GuiTab.au3.
If I use the GuiTab.au3 from version 3.3.14.5 (everything else 3.3.16.0) it works.
_GUICtrlTab_FindTab therefore does not work either.

Here is an example script to display the name of the first tab or to find the "Details" tab of the file explorer "File Properties Window".
(Window name ($wnd_title) and tab name ($Tab_Text) must be corrected to match the language of Windows.)

To test simply start the script (compiled in the same bit version as Windows for me 64bit) right click on a file and select properties.

With the new GuiTab.au3 the tab control handle is displayed, "<empty text>" for name tab 0 , number of tabs and -1 for not found.

With the old GuiTab.au3 the tab control handle is displayed, the name of tab 0 , number of tabs and number of the tab "Details" .

Can someone tell me where my mistake is, or confirm the behavior?

 I found bug #1664, but it's much older. The behavior is the same as far as I understand it.

  Many Thanks,
Nop27

;#include <GuiTab_old.au3> (From Autoit 3.3.14.5) <- works
#include <GuiTab.au3> <- works not

$wnd_title = "Eigenschaften von" ;must be corrected to match the language of Windows
$Tab_Text = "Details"           ;must be corrected to match the language of Windows

WinWaitActive ( $wnd_title)

;get handle  Tab-Control
$control_id            = "[CLASS:SysTabControl32; INSTANCE:1]"
$tab_control_handle    = ControlGetHandle ( $wnd_title,"",$control_id)
MSGBox(0,'tab_control_handle',$tab_control_handle )
if ( $tab_control_handle = 0 ) Then
    exit
EndIf

MSGBox(0,'Tab Index 0 Text:',_GUICtrlTab_GetItemText ( $tab_control_handle, 0 ))

MSGBox(0,'No Tabs:',_GUICtrlTab_GetItemCount($tab_control_handle))

$tab_pos = _GUICtrlTab_FindTab ( $tab_control_handle,$Tab_Text,True)
MSGBox(0,'Tab Index Found:',$tab_pos )

 

Link to comment
Share on other sites

Link to comment
Share on other sites

I tested with AutioIt 3.3.14.5. and ran the following slightly modified script: 

#include <GuiTab.au3>

$wnd_title = "Eigenschaften von" ;must be corrected to match the language of Windows
$Tab_Text = "Details"           ;must be corrected to match the language of Windows

WinWaitActive($wnd_title)

; Get handle Tab-Control
$control_id = "[CLASS:SysTabControl32; INSTANCE:1]"
$tab_control_handle = ControlGetHandle($wnd_title, "", $control_id)
ConsoleWrite("tab_control_handle: " & $tab_control_handle & @CRLF)
If $tab_control_handle = 0 Then Exit

ConsoleWrite("Tab Index 0 Text: " & _GUICtrlTab_GetItemText($tab_control_handle, 0) & @CRLF)
ConsoleWrite("No Tabs: " & _GUICtrlTab_GetItemCount($tab_control_handle) & @CRLF)
$tab_pos = _GUICtrlTab_FindTab($tab_control_handle, $Tab_Text, True)
ConsoleWrite("Tab Index Found: " & $tab_pos & @CRLF)

and got the following result:

tab_control_handle: 0x000E0900
Tab Index 0 Text: ?�
No Tabs: 4
Tab Index Found: -1

 

Edited by water

My UDFs and Tutorials:

Spoiler

UDFs:
Active Directory (NEW 2024-07-28 - Version 1.6.3.0) - Download - General Help & Support - Example Scripts - Wiki
ExcelChart (2017-07-21 - Version 0.4.0.1) - Download - General Help & Support - Example Scripts
OutlookEX (2021-11-16 - Version 1.7.0.0) - Download - General Help & Support - Example Scripts - Wiki
OutlookEX_GUI (2021-04-13 - Version 1.4.0.0) - Download
Outlook Tools (2019-07-22 - Version 0.6.0.0) - Download - General Help & Support - Wiki
PowerPoint (2021-08-31 - Version 1.5.0.0) - Download - General Help & Support - Example Scripts - Wiki
Task Scheduler (2022-07-28 - Version 1.6.0.1) - Download - General Help & Support - Wiki

Standard UDFs:
Excel - Example Scripts - Wiki
Word - Wiki

Tutorials:
ADO - Wiki
WebDriver - Wiki

 

Link to comment
Share on other sites

AutoIt 3.3.15.0 returns the following result: 

tab_control_handle: 0x000E0900
Tab Index 0 Text: ?�
No Tabs: 4
Tab Index Found: -1

 

My UDFs and Tutorials:

Spoiler

UDFs:
Active Directory (NEW 2024-07-28 - Version 1.6.3.0) - Download - General Help & Support - Example Scripts - Wiki
ExcelChart (2017-07-21 - Version 0.4.0.1) - Download - General Help & Support - Example Scripts
OutlookEX (2021-11-16 - Version 1.7.0.0) - Download - General Help & Support - Example Scripts - Wiki
OutlookEX_GUI (2021-04-13 - Version 1.4.0.0) - Download
Outlook Tools (2019-07-22 - Version 0.6.0.0) - Download - General Help & Support - Wiki
PowerPoint (2021-08-31 - Version 1.5.0.0) - Download - General Help & Support - Example Scripts - Wiki
Task Scheduler (2022-07-28 - Version 1.6.0.1) - Download - General Help & Support - Wiki

Standard UDFs:
Excel - Example Scripts - Wiki
Word - Wiki

Tutorials:
ADO - Wiki
WebDriver - Wiki

 

Link to comment
Share on other sites

I confirm it doesn't work anymore. To have it work again, 2 lines from 3.3.14.5 have to be present in 3.3.16.0+ . Maybe this could help @jpm

GuiTab.au3 (3.3.14.5)

Func _GUICtrlTab_GetItem($hWnd, $iIndex)
    ...
    Local $tagTCITEMEx = $tagTCITEM & ";ptr Filler" ; strange the Filler is erased by TCM_GETITEM : MS Bug!!!
    Local $tItem = DllStructCreate($tagTCITEMEx)
    ...
EndFunc

Correct output with 3.3.14.5

1951943408_GuiTab3.3_14.5.png.d846346e10765de4602b9ff0b8dd5a00.png

Below is GuiTab.au3 (3.3.16.0 , 3.3.16.1-rc1 , 3.3.16.1-rc2)

Func _GUICtrlTab_GetItem($hWnd, $iIndex)
    ...
;~  Local $tagTCITEMEx = $tagTCITEM & ";ptr Filler" ; strange the Filler is erased by TCM_GETITEM : MS Bug!!!
    Local $tItem = DllStructCreate($tagTCITEM)
    ...
EndFunc

Wrong output with 3.3.16.0+

1022370797_GuiTab3.3_16.0.png.0e838c4c45c1efd2419ab9f7b48bc2f4.png

It will work again after replacing the 2 lines in 3.3.16.0+ with the 2 lines from 3.3.14.5
The precedent test was done after replacing 2 lines in OP's code, to match Windows locale :

;~ $wnd_title = "Eigenschaften von" ;must be corrected to match the language of Windows
;~ $Tab_Text = "Details"            ;must be corrected to match the language of Windows

$wnd_title = "Propriétés de 296.au3"
$Tab_Text = "Général"

Hope it helps :)

Link to comment
Share on other sites

  • Moderators

Hi all,

Can someone please open a Trac ticket so this get fixed officially.

M23

Public_Domain.png.2d871819fcb9957cf44f4514551a2935.png Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind

Open spoiler to see my UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Link to comment
Share on other sites

I guess the "nervous remark" found in _GuiCtrlTab_GetItem() was written by GaryFrost in 2011, it appeared for the 1st time in AutoIt 3.3.8.0 (23rd December, 2011) (Release)

Local $tagTCITEMEx = $tagTCITEM & ";ptr Filler" ; strange the Filler is erased by TCM_GETITEM : MS Bug!!!
Local $tItem = DllStructCreate($tagTCITEMEx)

Links exploring this issue :

2008 - GaryFrost & Siao :
https://www.autoitscript.com/forum/topic/61862-bug-when-getting-text-of-tab-items/

2010 - PsaltyDS :
https://www.autoitscript.com/forum/topic/115365-function-_guictrltab_findtab-cannot-find-the-target-tab/

2010 - PsaltyDS :
https://www.autoitscript.com/trac/autoit/ticket/1664

All this probably happened because of this strange remark from MS in this link :
https://docs.microsoft.com/en-us/windows/win32/controls/tcm-getitem

If the TCIF_TEXT flag is set in the mask member of the TCITEM structure, the control may change the pszText member of the structure to point to the new text instead of filling the buffer with the requested text. The control may set the pszText member to NULL to indicate that no text is associated with the item.

So it seems that we can't easily get rid of $tagTCITEMEx, as it would require to rewrite functions. For example it's possible to use only $tagTCITEM in _GUICtrlTab_GetItem() ...if we're only interested in retrieving the text of a tab :

Local $tItem = DllStructCreate($tagTCITEM)

#cs reminder : Global Constansts defined in TabConstants.au3
Global Const $TCIF_TEXT = 0x00000001
Global Const $TCIF_IMAGE = 0x00000002
Global Const $TCIF_RTLREADING = 0x00000004
Global Const $TCIF_PARAM = 0x00000008
Global Const $TCIF_STATE = 0x00000010
Global Const $TCIF_ALLDATA = 0x0000001B
#ce

; DllStructSetData($tItem, "Mask", $TCIF_ALLDATA) ; original code => issue (0x1B = 0x10 + 0x08 +0x02 + 0x01)
; DllStructSetData($tItem, "Mask", 0x01) ; ok
; DllStructSetData($tItem, "Mask", 0x01 + 0x02) ; ok
; DllStructSetData($tItem, "Mask", 0x01 + 0x02 + 0x08) ; BAD when 0x08 for _GUICtrlTab_GetItemText()
DllStructSetData($tItem, "Mask", 0x01 + 0x02 + 0x10) ; ok (retrieves the text of the tab)

But it won't solve all situations, as GaryFrost wrote in his thread :

"Then come up with a fix that works in all situations, and show that it works."

As @Melba23 suggested, I'm gonna open a trac ticket, but it will mainly link to this thread.

Bravo to OP @Nop72 , good explanations for the bug report, especially it was his 1st post :)

Link to comment
Share on other sites

5 hours ago, jpm said:

can you check it is OK for you?

Certainly ! Glad to have you back after a week (I was afraid of health problems)
I did try your suggestion a couple of days ago (after comparing with 3.3.14.5 code) but it didn't work.
To make sure, I just re-tried it again now and it still doesn't work, tab text isn't retrieved. Let's resume :

Not working #1 (actual 3.3.16.0+) :

Local $tItem = DllStructCreate($tagTCITEM)    

DllStructSetData($tItem, "Mask", $TCIF_ALLDATA)    
DllStructSetData($tItem, "StateMask", BitOR($TCIS_HIGHLIGHTED, $TCIS_BUTTONPRESSED))

Not working #2 (your suggestion in precedent post) :

Local $iBuffer = 4096
Local $tItem = DllStructCreate($tagTCITEM)

DllStructSetData($tItem, "Mask", $TCIF_ALLDATA)    
DllStructSetData($tItem, "TextMax", $iBuffer)
DllStructSetData($tItem, "StateMask", BitOR($TCIS_HIGHLIGHTED, $TCIS_BUTTONPRESSED))

Working #1 :

Local $tagTCITEMEx = $tagTCITEM & ";ptr Filler" ; strange the Filler is erased by TCM_GETITEM : MS Bug!!!
Local $tItem = DllStructCreate($tagTCITEMEx)

DllStructSetData($tItem, "Mask", $TCIF_ALLDATA)
DllStructSetData($tItem, "StateMask", BitOR($TCIS_HIGHLIGHTED, $TCIS_BUTTONPRESSED))

Working #2 (3.3.14.5) :

Local $iBuffer = 4096
Local $tagTCITEMEx = $tagTCITEM & ";ptr Filler" ; strange the Filler is erased by TCM_GETITEM : MS Bug!!!
Local $tItem = DllStructCreate($tagTCITEMEx)

DllStructSetData($tItem, "Mask", $TCIF_ALLDATA)
DllStructSetData($tItem, "TextMax", $iBuffer)
DllStructSetData($tItem, "StateMask", BitOR($TCIS_HIGHLIGHTED, $TCIS_BUTTONPRESSED))

 

Link to comment
Share on other sites

2 hours ago, jpm said:

Ok, can you post a non working script?

Yes. It's OP's script with 2 lines changed to adapt to windows locale (as OP indicated). Same bad result no matter the script is compiled or not :

; Run the script from AutoIt 3.3.16.0+ after modifying 2 lines $wnd_title and $Tab_Text

#include <GuiTab.au3> 

;~ $wnd_title = "Eigenschaften von" ; must be corrected to match the language of Windows
;~ $Tab_Text = "Details"            ; must be corrected to match the language of Windows

$wnd_title = "Propriétés de Bloc-notes"
$Tab_Text = "Compatibilité"

WinWaitActive ($wnd_title)

;get handle  Tab-Control
$control_id            = "[CLASS:SysTabControl32; INSTANCE:1]"
$tab_control_handle    = ControlGetHandle ( $wnd_title,"",$control_id)

MSGBox(0,'tab_control_handle',$tab_control_handle )
If ( $tab_control_handle = 0 ) Then
    Exit
EndIf

MSGBox(0,'Tab Index 0 Text:',_GUICtrlTab_GetItemText ( $tab_control_handle, 0 ))

MSGBox(0,'No Tabs:',_GUICtrlTab_GetItemCount($tab_control_handle))

$tab_pos = _GUICtrlTab_FindTab ( $tab_control_handle,$Tab_Text,True)
MSGBox(0,'Tab Index Found:',$tab_pos )

420032928_GuiTab3.3_16.0withtagTCITEM.png.270f8dca191bfe0191ec808d92e5c2a5.png

We'll certainly need a couple of testers to confirm your suggestion that it may be related to x64 or not.
Before testing, the 2 lines to be changed in the test script are these ones :

$wnd_title = "Propriétés de Bloc-notes"
$Tab_Text = "Compatibilité"

Here I tested a shortcut placed on desktop, pointing to NotePad ("Bloc-notes") so testers should adapt $wnd_title to the properties windows they're gonna test (it can be any file in Explorer, on desktop etc...) just right click on its icon and choose Property in its context menu.

Same for line $Tab_Text : here I choosed the text of the last tab ("Compatibilité")

The non working script above uses an altered _GUICtrlTab_GetItem() function, found in the include file GuiTab.au3 (please make a copy of this file before modifying it +++)

Here is the non-working function (at least for me) :

Func _GUICtrlTab_GetItem($hWnd, $iIndex)
    If Not IsHWnd($hWnd) Then $hWnd = GUICtrlGetHandle($hWnd)

    ;********************************
    Local $iBuffer = 4096
        
    Local $tItem = DllStructCreate($tagTCITEM)

;~  Local $tagTCITEMEx = $tagTCITEM & ";ptr Filler" ; strange the Filler is erased by TCM_GETITEM : MS Bug!!!
;~  Local $tItem = DllStructCreate($tagTCITEMEx)

    DllStructSetData($tItem, "Mask", $TCIF_ALLDATA)
    DllStructSetData($tItem, "TextMax", $iBuffer)
    DllStructSetData($tItem, "StateMask", BitOR($TCIS_HIGHLIGHTED, $TCIS_BUTTONPRESSED))
    ;********************************

    Local $tBuffer, $iMsg
    If _GUICtrlTab_GetUnicodeFormat($hWnd) Then
        $tBuffer = $__g_tTabBuffer
        $iMsg = $TCM_GETITEMW
    Else
        $tBuffer = $__g_tTabBufferANSI
        $iMsg = $TCM_GETITEMA
    EndIf
    Local $iRet = __GUICtrl_SendMsg($hWnd, $iMsg, $iIndex, $tItem, $tBuffer, True, 4, True)

    Local $aItem[4]
    $aItem[0] = DllStructGetData($tItem, "State")
    $aItem[1] = DllStructGetData($tBuffer, "Text")
    $aItem[2] = DllStructGetData($tItem, "Image")
    $aItem[3] = DllStructGetData($tItem, "Param")

    Return SetError($iRet = 0, 0, $aItem)
EndFunc   ;==>_GUICtrlTab_GetItem

To have a correct result, I need to change this in the function :

;~  Local $tItem = DllStructCreate($tagTCITEM)

    Local $tagTCITEMEx = $tagTCITEM & ";ptr Filler" ; strange the Filler is erased by TCM_GETITEM : MS Bug!!!
    Local $tItem = DllStructCreate($tagTCITEMEx)

Correct result :

762186524_GuiTab3.3_16.0withtagTCITEMEx.png.7f03fce4a0518dd36f8408c358ea33d7.png

Message box on the right : "Tab Index found = 2" means that the tab text "Compatibilité" has been found in Tab 2 (as first tab = 0)

@Nine (who already tested b4 Jpm suggestion of adding "TextMax") and testers who got a x64 computer, could you please confirm what is your result when you run the script with AutoIt 3.3.16.0+, depending on the code used in _GUICtrlTab_GetItem() ?

Thanks !

Edited by pixelsearch
typo
Link to comment
Share on other sites

Thanks,

the question now is I never get Tab Index 0 Text = Général

and the Tab Index is not found (-1)

On my computer I do not have a compatibilité Tab 

On which version de Windows are you running?

Link to comment
Share on other sites

Hi,

I need to admit that I cannot fix it

The x64 works only if launch by Scite.

perhaps the pb comes from a X86 process trying to retrieve info from a X64 process.

This does not explain why the  script launch directly by AutoIt3_x64.exe it does work as launch by Scite in X64 mode

With the propose regression fix we will behave as the fix introduced In 2010 #1664 ticket

Perhaps more experience developper can find a solution.

Cheers

Link to comment
Share on other sites

Issue is related to the filler field from $tagTCITEM ";ptr Filler". It was removed 😋. it seems to be when you  call $TCM_GETITEM it clears extra ptr size in the allocated remote structure so it gets broken.

It you want to read from x86 to a x64 process you need to force $tagTCITEM  as x64 in the remote allocate stuff.

 

Saludos

Edited by Danyfirex
Link to comment
Share on other sites

 

Quote

It you want to read from x86 to a x64 process you need to force $tagTCITEM  as x64 in the remote allocate stuff.

 

This is what I meant.

 

Func _GUICtrlTab_GetItem($hWnd, $iIndex)
    If Not IsHWnd($hWnd) Then $hWnd = GUICtrlGetHandle($hWnd)

    Local $tagTCITEMEx = $tagTCITEM & ";ptr Filler" ; strange the Filler is erased by TCM_GETITEM : MS Bug!!!
    If Not _WinAPI_InProcess($hWnd, $__g_hGUICtrl_LastWnd) Then
        ;x86 read remote x64
        If (Not @AutoItX64) And (Not _WinAPI_IsWow64Process(DllCall("user32.dll", "dword", "GetWindowThreadProcessId", "hwnd", $hWnd, "dword*", 0)[2])) Then
            $tagTCITEMEx = StringReplace($tagTCITEMEx, "ptr", "INT64")
        EndIf

        ;x64 read remote x86
        If (@AutoItX64) And (_WinAPI_IsWow64Process(DllCall("user32.dll", "dword", "GetWindowThreadProcessId", "hwnd", $hWnd, "dword*", 0)[2])) Then
            $tagTCITEMEx = StringReplace($tagTCITEMEx, "ptr", "ULONG")
        EndIf
    EndIf

    Local $tItem = DllStructCreate($tagTCITEMEx)
    DllStructSetData($tItem, "Mask", $TCIF_ALLDATA)
    DllStructSetData($tItem, "StateMask", BitOR($TCIS_HIGHLIGHTED, $TCIS_BUTTONPRESSED))
    Local $tBuffer, $iMsg
    If _GUICtrlTab_GetUnicodeFormat($hWnd) Then
        $tBuffer = $__g_tTabBuffer
        $iMsg = $TCM_GETITEMW
    Else
        $tBuffer = $__g_tTabBufferANSI
        $iMsg = $TCM_GETITEMA
    EndIf
    Local $iRet = __GUICtrl_SendMsg($hWnd, $iMsg, $iIndex, $tItem, $tBuffer, True, 4, True)

    Local $aItem[4]
    $aItem[0] = DllStructGetData($tItem, "State")
    $aItem[1] = DllStructGetData($tBuffer, "Text")
    $aItem[2] = DllStructGetData($tItem, "Image")
    $aItem[3] = DllStructGetData($tItem, "Param")

    Return SetError($iRet = 0, 0, $aItem)
EndFunc   ;==>_GUICtrlTab_GetItem

It's a little ugly, it's just to make you see what I meant.

Saludos

Link to comment
Share on other sites

many thanks

I wonder now how many other $tag for other UDF will need to be adapted too perhaps just the one which return a buffer and perhaps those they pass a buffer too

for the filler it looks like the buffer must be align to a 16 byte boundary

Cheers

Link to comment
Share on other sites

My advice about x86 to x64 and vice versa is just the way to handle but it doesn't mean that it has to be all like that. I think the best way is to compile the required x64-x86 version. My solution is more in case someone strictly needs it.

 

Saludos

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