Jump to content
Sign in to follow this  
MichaelPig

Function _GUICtrlTab_FindTab() cannot find the target tab

Recommended Posts

MichaelPig

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)

Share this post


Link to post
Share on other sites
PsaltyDS

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

Share this post


Link to post
Share on other sites
Yoriz

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.

Share this post


Link to post
Share on other sites
PsaltyDS

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

Share this post


Link to post
Share on other sites
MichaelPig

Thank you very much for your help.

I'm a beginner in learning AutoIt, so not very clear about your code. I will look over the help file to get information about the functions.

Anyway, thank you again.

Share this post


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
Sign in to follow this  

×

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.