Jump to content

Function _GUICtrlTab_FindTab() cannot find the target tab


Recommended Posts

Hello,

I'll appreciate if somebody know anything about this problem.

I want to get a tab's index in the driver property window. I use the _GUICtrlTab_FindTab(), but it return -1.

Below is my script. Could anybody tell me what the problem is? And how to get the index? Thanks a lot.

#include <GuiTab.au3>

#include <GuiConstantsEx.au3>

#include <GuiTreeView.au3>

Global $sDriverName = "Floppy disk drive"

Send("#r")

WinWaitActive("Run")

WinActivate("Run")

Send("devmgmt.msc")

Sleep(1000)

Send("{enter}")

WinWaitActive("Device Manager")

WinActivate("Device Manager")

Sleep(2000)

$hTreeView = ControlGetHandle("Device Manager", "", "[CLASS:SysTreeView32; INSTANCE:1]")

$hItem = _GUICtrlTreeView_FindItem( $hTreeView, $sDriverName)

_GUICtrlTreeView_EnsureVisible($hTreeView, $hItem)

_GUICtrlTreeView_SetSelected ($hTreeView, $hItem)

_GUICtrlTreeView_ClickItem($hTreeView, $hItem, "left", False, 2)

$DriverPropertyWinTitle = $sDriverName & " Properties"

WinWaitActive($DriverPropertyWinTitle)

WinActivate($DriverPropertyWinTitle)

$DriverPropertyWinTitle = $sDriverName & " Properties"

WinWaitActive($DriverPropertyWinTitle)

WinActivate($DriverPropertyWinTitle)

$DriverTabHandle = ControlGetHandle($DriverPropertyWinTitle, "", "[CLASS:SysTabControl32; INSTANCE:1]")

$DriverTabIndex = _GUICtrlTab_FindTab($DriverTabHandle, "Driver", True)

MsgBox(0, "title", $DriverTabIndex)

Link to post
Share on other sites

OK, first the smart answer: Don't do this -- use DevCon.exe instead to do whatever you are doing.

Next, the less smart answer: An AutoIt bug in _GuiCtrlTab_GetItem(), which was called by _GuiCtrlTab_GetItemText(), after being called by _GUICtrlTab_FindTab(). Direct memory voodoo is being done which I don't fully understand, but this seems to fix it:

Func _GUICtrlTab_GetItem($hWnd, $iIndex)
    If $Debug_TAB Then __UDF_ValidateClassName($hWnd, $__TABCONSTANT_ClassName)
    If Not IsHWnd($hWnd) Then $hWnd = GUICtrlGetHandle($hWnd)
    Local $fUnicode = _GUICtrlTab_GetUnicodeFormat($hWnd)

    Local $iBuffer = 4096
    Local $tItem = DllStructCreate($tagTCITEM)
    Local $pItem = DllStructGetPtr($tItem)
    DllStructSetData($tItem, "Mask", $TCIF_ALLDATA)
    DllStructSetData($tItem, "TextMax", $iBuffer)
    DllStructSetData($tItem, "StateMask", BitOR($TCIS_HIGHLIGHTED, $TCIS_BUTTONPRESSED))
    Local $iItem = DllStructGetSize($tItem)
    Local $tBuffer
    If $fUnicode Then
        $tBuffer = DllStructCreate("wchar Text[" & $iBuffer & "]")
        $iBuffer *= 2
    Else
        $tBuffer = DllStructCreate("char Text[" & $iBuffer & "]")
    EndIf
    Local $pBuffer = DllStructGetPtr($tBuffer)
    Local $tMemMap
    Local $pMemory = _MemInit($hWnd, $iItem + $iBuffer, $tMemMap)


    ; .................................................................
    ; Start Bug patch..................................................

    ;Local $pText = $pMemory + $iItem
    Local $pText = $pMemory + $iItem + 4 ; add room for 32-bit pointer
    If @AutoItX64 Then $pText += 4 ; more room for 64-bit pointer

    ; End Bug patch....................................................
    ; .................................................................


    DllStructSetData($tItem, "Text", $pText)
    _MemWrite($tMemMap, $pItem, $pMemory, $iItem)
    Local $iRet
    If $fUnicode Then
        $iRet = _SendMessage($hWnd, $TCM_GETITEMW, $iIndex, $pMemory)
    Else
        $iRet = _SendMessage($hWnd, $TCM_GETITEMA, $iIndex, $pMemory)
    EndIf
    _MemRead($tMemMap, $pMemory, $pItem, $iItem)
    _MemRead($tMemMap, $pText, $pBuffer, $iBuffer)
    _MemFree($tMemMap)
    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

I am informed by trancexx that this is not the correct solution, but her explanation went too far over my head to read the tail numbers.

:P

Edit: Here is a demo of the fix using the DevMgmt.mmc and the floppy controller properties dialog (tested under 32-bit Vista):

#include <GuiTab.au3>
#include <GuiConstantsEx.au3>
#include <GuiTreeView.au3>
#include <Array.au3>

HotKeySet("{ESC}", "_Quit")

Global $sDriverName = "Standard floppy disk controller"

ShellExecute("DevMgmt.msc")
While 1
    Sleep(100)

    $hDevMgmt = WinGetHandle("[CLASS:MMCMainFrame; TITLE:Device Manager]", "")
    If IsHWnd($hDevMgmt) Then ExitLoop

    $hDevMgmt = WinGetHandle("[CLASS:#32770; TITLE:Device Manager]", "")
    If IsHWnd($hDevMgmt) And StringInStr(ControlGetText($hDevMgmt, "", "[CLASS:Static; INSTANCE:3]"), "You do not have sufficient") Then
        ControlSend($hDevMgmt, "", "", "{ENTER}")
        ContinueLoop
    EndIf
WEnd

$hTreeView = ControlGetHandle("Device Manager", "", "[CLASS:SysTreeView32; INSTANCE:1]")

$hItem = _GUICtrlTreeView_FindItem($hTreeView, $sDriverName)
_GUICtrlTreeView_EnsureVisible($hTreeView, $hItem)
_GUICtrlTreeView_SetSelected($hTreeView, $hItem)
_GUICtrlTreeView_ClickItem($hTreeView, $hItem, "left", False, 2)
ControlSend($hDevMgmt, "", "", "!a") ; Action
ControlSend($hDevMgmt, "", "", "r") ; Properties

While 1
    $hFDProp = WinGetHandle("[CLASS:#32770; TITLE:" & $sDriverName & " Properties]", "")
    If IsHWnd($hFDProp) Then ExitLoop
WEnd

$hTab = ControlGetHandle($hFDProp, "", "[CLASS:SysTabControl32; INSTANCE:1]")

$iDriverTab = __GUICtrlTab_FindTab($hTab, "Driver", True)
ConsoleWrite("$iDriverTab = " & $iDriverTab & @LF)

Func __GUICtrlTab_FindTab($hWnd, $sText, $fInStr = False, $iStart = 0)
    Local $sTab

    For $iI = $iStart To _GUICtrlTab_GetItemCount($hWnd)
        $sTab = __GUICtrlTab_GetItemText($hWnd, $iI)
        ConsoleWrite("Debug _GUICtrlTab_GetItemText:  " & $iI & ":  $sTab = " & $sTab & @LF)
        Switch $fInStr
            Case False
                If $sTab = $sText Then Return $iI
            Case True
                If StringInStr($sTab, $sText) Then Return $iI
        EndSwitch
    Next
    Return -1
EndFunc   ;==>_GUICtrlTab_FindTab

Func __GUICtrlTab_GetItemText($hWnd, $iIndex)
    Local $aItem = __GUICtrlTab_GetItem($hWnd, $iIndex)
    _ArrayDisplay($aItem, $iIndex)
    Return $aItem[1]
EndFunc   ;==>_GUICtrlTab_GetItemText

Func __GUICtrlTab_GetItem($hWnd, $iIndex)
    If $Debug_TAB Then __UDF_ValidateClassName($hWnd, $__TABCONSTANT_ClassName)
    If Not IsHWnd($hWnd) Then $hWnd = GUICtrlGetHandle($hWnd)
    Local $fUnicode = _GUICtrlTab_GetUnicodeFormat($hWnd)

    Local $iBuffer = 4096
    Local $tItem = DllStructCreate($tagTCITEM)
    Local $pItem = DllStructGetPtr($tItem)
    DllStructSetData($tItem, "Mask", $TCIF_ALLDATA)
    DllStructSetData($tItem, "TextMax", $iBuffer)
    DllStructSetData($tItem, "StateMask", BitOR($TCIS_HIGHLIGHTED, $TCIS_BUTTONPRESSED))
    Local $iItem = DllStructGetSize($tItem)
    Local $tBuffer
    If $fUnicode Then
        $tBuffer = DllStructCreate("wchar Text[" & $iBuffer & "]")
        $iBuffer *= 2
    Else
        $tBuffer = DllStructCreate("char Text[" & $iBuffer & "]")
    EndIf
    Local $pBuffer = DllStructGetPtr($tBuffer)
    Local $tMemMap
    Local $pMemory = _MemInit($hWnd, $iItem + $iBuffer, $tMemMap)


    ; Start Bug patch..................................................
    ;Local $pText = $pMemory + $iItem
    Local $pText = $pMemory + $iItem + 4 ; add room for 32-bit pointer
    If @AutoItX64 Then $pText += 4 ; more room for 64-bit pointer
    ; End Bug patch....................................................


    DllStructSetData($tItem, "Text", $pText)
    _MemWrite($tMemMap, $pItem, $pMemory, $iItem)
    Local $iRet
    If $fUnicode Then
        $iRet = _SendMessage($hWnd, $TCM_GETITEMW, $iIndex, $pMemory)
    Else
        $iRet = _SendMessage($hWnd, $TCM_GETITEMA, $iIndex, $pMemory)
    EndIf
    _MemRead($tMemMap, $pMemory, $pItem, $iItem)
    _MemRead($tMemMap, $pText, $pBuffer, $iBuffer)
    _MemFree($tMemMap)
    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

Func _Quit()
    Exit
EndFunc   ;==>_Quit

Note the modified version of __GUICtrlTab_FindTab() (with two underscores), which will call a modified __GuiCtrlTab_GetItemText(), and finally calls the patched version of __GuiCtrlTab_GetItem().

:mellow:

Edited by PsaltyDS
Valuater's AutoIt 1-2-3, Class... Is now in Session!For those who want somebody to write the script for them: RentACoder"Any technology distinguishable from magic is insufficiently advanced." -- Geek's corollary to Clarke's law
Link to post
Share on other sites

I had looked at this and also couldnt figure out why it didnt work but it was beyond me, but i can help with some of the rest of your script.

You can use ShellExecute rather then your run method.

;~ Send("#r")
;~ WinWaitActive("Run")
;~ WinActivate("Run")
;~ Send("devmgmt.msc")
;~ Sleep(1000)
;~ Send("{enter}")
ShellExecute("devmgmt.msc")

and you unessesarily have this block of code twice.

$DriverPropertyWinTitle = $sDriverName & " Properties"
WinWaitActive($DriverPropertyWinTitle)
WinActivate($DriverPropertyWinTitle)
GDIPlusDispose - A modified version of GDIPlus that auto disposes of its own objects before shutdown of the Dll using the same function Syntax as the original.EzMySql UDF - Use MySql Databases with autoit with syntax similar to SQLite UDF.
Link to post
Share on other sites

I changed the OP's script a lot in my demo posted above. On Vista, you might get a warning dialog about not having perms to make changes before the actual window comes up, so you see this for opening it:

ShellExecute("DevMgmt.msc")
While 1
    Sleep(100)

    $hDevMgmt = WinGetHandle("[CLASS:MMCMainFrame; TITLE:Device Manager]", "")
    If IsHWnd($hDevMgmt) Then ExitLoop

    $hDevMgmt = WinGetHandle("[CLASS:#32770; TITLE:Device Manager]", "")
    If IsHWnd($hDevMgmt) And StringInStr(ControlGetText($hDevMgmt, "", "[CLASS:Static; INSTANCE:3]"), "You do not have sufficient") Then
        ControlSend($hDevMgmt, "", "", "{ENTER}")
        ContinueLoop
    EndIf
WEnd

:mellow:

Valuater's AutoIt 1-2-3, Class... Is now in Session!For those who want somebody to write the script for them: RentACoder"Any technology distinguishable from magic is insufficiently advanced." -- Geek's corollary to Clarke's law
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
  • Recently Browsing   0 members

    No registered users viewing this page.

×
×
  • Create New...