找回密码
 加入
搜索
查看: 12523|回复: 11

[AU3基础] 如何获取ToolbarWindow32控件上某个按钮的状态

  [复制链接]
发表于 2010-4-7 19:11:01 | 显示全部楼层 |阅读模式
本帖最后由 xiehuahere 于 2010-4-7 19:12 编辑

AutoIt新手。看了CHM帮助,没有找到唉。论坛里也没有搜索到......求赐教

这个ToolbarWindow32控件不是我用脚本create的,而是某个已知软件上的。
我如何得知该控件上的某个按钮是不是 Enabled 状态?
有没有类似WinWaitActive之类的函数等待此按钮的激活状态呢?(QTP自动测试工具提供此方法)
谢谢了~
发表于 2010-4-7 20:54:57 | 显示全部楼层

这个会不会太难 AccExplorer32

本帖最后由 lainline 于 2010-4-8 10:57 编辑

控件本身
$htemp =ControlGetHandle("[CLASS:ToolbarWindow32]","","[CLASSNN:ToolbarWindow322")
$text =WinGetText($htemp,"")
ToolTip($htemp)
MsgBox(0,$text,"存在:"& BitAND(WinGetState($htemp,""),1))
MsgBox(0,$text,"可用:"& BitAND(WinGetState($htemp,""),4))
MsgBox(0,$text,"可见:"& BitAND(WinGetState($htemp,""),2))
MsgBox(0,$text,"激活:"& BitAND(WinGetState($htemp,""),8))
MsgBox(0,$text,"最小化:"& BitAND(WinGetState($htemp,""),16))
MsgBox(0,$text,"最大化:"& BitAND(WinGetState($htemp,""),32))

下面具体到按钮就有些难了

工具:

示例代码从英文站上找来的如果要看原文可以到英文站上搜索
#include <WinAPI.au3>
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <EditConstants.au3>
#include <StaticConstants.au3>
#include <Array.au3>

;~ opt("MustDeclareVars", 1)
Opt("GUIOnEventMode", 1)

Global $oMyError = ObjEvent("AutoIt.Error", "MyErrFunc")

Global Const $hOLE32 = DllOpen("ole32.dll")
Global Const $hOLEACC = DllOpen("oleacc.dll")
Global Const $hOleAut = DllOpen("oleaut.dll")

Global Const $VT_EMPTY = 0
Global Const $VT_NULL = 1
Global Const $VT_I2 = 2
Global Const $VT_I4 = 3
Global Const $VT_R4 = 4
Global Const $VT_R8 = 5
Global Const $VT_CY = 6
Global Const $VT_DATE = 7
Global Const $VT_BSTR = 8
Global Const $VT_DISPATCH = 9
Global Const $VT_ERROR = 10
Global Const $VT_BOOL = 11
Global Const $VT_VARIANT = 12
Global Const $VT_UNKNOWN = 13
Global Const $VT_DECIMAL = 14
Global Const $VT_I1 = 16
Global Const $VT_UI1 = 17
Global Const $VT_UI2 = 18
Global Const $VT_UI4 = 19
Global Const $VT_I8 = 20
Global Const $VT_UI8 = 21
Global Const $VT_INT = 22
Global Const $VT_UINT = 23
Global Const $VT_VOID = 24
Global Const $VT_HRESULT = 25
Global Const $VT_PTR = 26
Global Const $VT_SAFEARRAY = 27
Global Const $VT_CARRAY = 28
Global Const $VT_USERDEFINED = 29
Global Const $VT_LPSTR = 30
Global Const $VT_LPWSTR = 31
Global Const $VT_RECORD = 36
Global Const $VT_INT_PTR = 37
Global Const $VT_UINT_PTR = 38
Global Const $VT_FILETIME = 64
Global Const $VT_BLOB = 65
Global Const $VT_STREAM = 66
Global Const $VT_STORAGE = 67
Global Const $VT_STREAMED_OBJECT = 68
Global Const $VT_STORED_OBJECT = 69
Global Const $VT_BLOB_OBJECT = 70
Global Const $VT_CF = 71
Global Const $VT_CLSID = 72
Global Const $VT_VERSIONED_STREAM = 73
Global Const $VT_BSTR_BLOB = 0xfff
Global Const $VT_VECTOR = 0x1000
Global Const $VT_ARRAY = 0x2000
Global Const $VT_BYREF = 0x4000
Global Const $VT_RESERVED = 0x8000
Global Const $VT_ILLEGAL = 0xffff
Global Const $VT_ILLEGALMASKED = 0xfff
Global Const $VT_TYPEMASK = 0xfff

;~ Global Const $tagGUID = "ulong;ushort;ushort;byte[8]"
Global Const $tagCLSID = $tagGUID
Global Const $tagUUID = $tagGUID
Global Const $CLSCTX_INPROC_SERVER = 0x1
Global Const $S_OK = 0
Global Const $DISP_E_UNKNOWNNAME = 2147614726
Global Const $DISPID_UNKNOWN = 4294967295
Global Const $DISP_E_MEMBERNOTFOUND = 2147614723
Global Const $tagVARIANT = "ushort vt;ushort r1;ushort r2;ushort r3;uint64 data"
Global Const $tagDISPPARAMS = "ptr rgvargs;ptr rgdispidNamedArgs;dword cArgs;dword cNamedArgs;"

Global Const $DISPATCH_METHOD = 0x1
Global Const $DISPATCH_PROPERTYGET = 0x2
Global Const $DISPATCH_PROPERTYPUT = 0x4
Global Const $DISPATCH_PROPERTYPUTREF = 0x8

Global Const $tagLOOKUP_TABLE_ENTRY = "ptr name;ptr value;dword flags;"
Global Const $LOOKUP_TABLE_ENTRY_SIZE = DllStructGetSize(DllStructCreate($tagLOOKUP_TABLE_ENTRY))
Global Const $LOOKUP_TABLE_METHOD = 1
Global Const $LOOKUP_TABLE_PROPERTY = 2
Global Const $LOOKUP_TABLE_PUBLIC = 0
Global Const $LOOKUP_TABLE_PRIVATE = 4

Global Const $tagOBJECT_INFO = "dword refcount;ptr release;"

Global Const $hOLEOUT = DllOpen("oleaut32.dll")

Global Const $SizeOfPtr = DllStructGetSize(DllStructCreate("ptr"))
Global $myEdit

GUICreate("MSAA Spy")
$myEdit = GUICtrlCreateEdit("First line" & @CRLF, 10, 10, 400, 300, $ES_AUTOVSCROLL + $WS_VSCROLL)
GUISetOnEvent(-3, "_Quit")
GUISetState()

Global $aMousePos, $aCall, $oIAccesible
Global $tInfo
global $oChild

Global Const $__Au3Obj_tagVARIANT = "ushort vt;ushort r1;ushort r2;ushort r3;ptr data; ptr"
Global $tVar = DllStructCreate($__Au3Obj_tagVARIANT)
Global $pVar = DllStructGetPtr($tVar)
__Au3Obj_VariantInit($pVar)

While 1

    $aMousePos = MouseGetPos()
    $aCall = DllCall($hOLEACC, "int", "AccessibleObjectFromPoint", _
            "int", $aMousePos[0], _
            "int", $aMousePos[1], _
            "ptr*", 0, _
            "ptr", $pVar)
;~             "ptr", $pVar)

    If @error Or $aCall[0]<>0 Then 
        ConsoleWrite("!DLLCall-Error or error on receiving IAccesible" & @CRLF)
        Sleep(500)
        ContinueLoop
    EndIf
    $oIAccesible = __Au3Obj_ConvertPtrToIDispatch($aCall[3]) ; create IDispatch when no error occured

    If IsObj($oIAccesible) Then
    ; ConsoleWrite("accChild: " & $oAccessibleObject.accChild($Param) & @CRLF) ;<-

    GUICtrlSetData($myedit, "")
;~  $oChild=$oIAccesible.accchild
    
    $x=int(2+$oChild)-2
    dim $array[16] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
    if COMVariantToValue($pVar)<15 then
        $oChild=$array[COMVariantToValue($pVar)]
    Else
        $oChild=0
    endif
    $tInfo=$x & @CRLF
    $tInfo = $tinfo & "accChildCount: " & $oIAccesible.accChildCount($oChild)& @CRLF
    $tInfo = $tinfo & "accDefaultAction: " & $oIAccesible.accDefaultAction($oChild) & @CRLF
    $tInfo = $tinfo & "accDescription: " & $oIAccesible.accDescription($oChild) & @CRLF
    $tInfo = $tinfo & "accFocus: " & $oIAccesible.accFocus($oChild) & @CRLF
    $tInfo = $tinfo & "accHelp: " & $oIAccesible.accHelp($oChild) & @CRLF
;~     $tInfo = $tinfo & "accHelpTopic: " & $oIAccesible.accHelpTopic($Param) & @CRLF
    $tInfo = $tinfo & "accKeyboardShortcut: " & $oIAccesible.accKeyboardShortcut & @CRLF
    $tInfo = $tinfo & "accName: " & $oIAccesible.accName($oChild) & @CRLF
;~  $tInfo = $tinfo & "accName: " & $oIAccesible.accName(number($oChild)) & @CRLF
;~  $tInfo = $tinfo & "accName: " & $oIAccesible.accName(int($oChild)) & @CRLF
      
    $tInfo = $tinfo & "accParent: " & $oIAccesible.accParent($oChild) & @CRLF
    dim $sText
    
    ;- Get the textual description of the role
    local $aRoleCall = DllCall($hOLEACC, "int", "GetRoleText", "DWORD", $oIAccesible.accRole($oChild), "str", $sText, "int", 255)
    
    $tInfo = $tinfo & "accRole: " & $oIAccesible.accRole($oChild) & ":" & $aRoleCall[2] & @CRLF
    $tInfo = $tinfo & "accSelection: " & $oIAccesible.accSelection($oChild) & @CRLF
    $tInfo = $tinfo & "accState: " & $oIAccesible.accState($oChild) & @CRLF
    $tInfo = $tinfo & "accValue: " & $oIAccesible.accValue($oChild) & @CRLF
    
    dim $pX,$pY,$cX,$cY
;~  $oIAccesible.accLocation($px,$py,$cx,$cy,$oChild)
    $oIAccesible.accLocation($px,$py,$cx,$cy,$pVar)
    
    $tInfo = $tinfo & "accLocation: " & $px & $py & $cx & $cy & @CRLF
    GUICtrlSetData($myedit, $tInfo)
    
    Else
        ConsoleWrite("! NOT OBJECT" & @CRLF)
    EndIf

;~ Do not forget to clean the return result
    __Au3Obj_VariantClear($aCall[4])
    $oIAccesible = 0 ; free Object
    Sleep(500)

WEnd

Func MyErrFunc()
    ConsoleWrite("!COM Error!   " & "Number is: " & Hex($oMyError.number, 8) & "  description is: " & $oMyError.windescription & @CRLF)
EndFunc   ;==>MyErrFunc

; FUNCTIONS:

Func _GetObjectWinHandle($oObject)

    Local $aCall = DllCall("oleacc.dll", "int", "WindowFromAccessibleObject", _
            "idispatch", $oObject, _
            "hwnd*", 0)

    If @error Or $aCall[0] Then
        Return SetError(1, 0, 0)
    EndIf

    Return $aCall[2]

EndFunc   ;==>_GetObjectWinHandle

Func _AccessibleObjectFromWindow($hWnd)

    Local $sIID_IAccessible = "{618736E0-3C3D-11CF-810C-00AA00389B71}"
    Local $tGUID = _WinAPI_GUIDFromString($sIID_IAccessible)
    Local $pGUID = DllStructGetPtr($tGUID)

    Local $aCall = DllCall($hOLEACC, "int", "AccessibleObjectFromWindow", _
            "hwnd", $hWnd, _
            "dword", 0, _ ; OBJID_WINDOW
            "ptr", $pGUID, _
            "idispatch*", 0)

    If @error Or $aCall[0] Then
        Return SetError(1, 0, 0)
    EndIf

    Return $aCall[4]

EndFunc   ;==>_AccessibleObjectFromWindow
Func _AccessibleObjectFromPoint($x,$y)
    Local $tPoint=DllStructCreate($tagPOINT)
    dllstructsetdata($tPoint,1,$x)
    dllstructsetdata($tPoint,2,$y)
;~ STDAPI AccessibleObjectFromWindow(  __in   HWND hwnd,  __in   DWORD dwObjectID,  __in   REFIID riid,  __out  void **ppvObject);
;~ STDAPI AccessibleObjectFromPoint(  __in   POINT ptScreen,  __out  IAccessible **ppacc,  __out  VARIANT *pvarChild);
;~     local $aCall = DllCall($hOLEACC, "int", "AccessibleObjectFromPoint", "ptr", DllStructGetPtr($tPOINT), "idispatch*", 0, "ptr", 0)
;~     local $aCall = DllCall($hOLEACC, "int", "AccessibleObjectFromPoint", "long", DllStructGetPtr($tPOINT), "idispatch", 0, "ptr", 0)
    local $aCall = DllCall($hOLEACC, "int", "AccessibleObjectFromPoint", "int", $x, "int", $y, "idispatch*", 0, "ptr", 0)
    If @error Or $aCall[0] Then
        Return SetError(1, 0, 0)
    EndIf

    Return ConvertPtrToIDispatch($aCall[3])

EndFunc   ;==>_AccessibleObjectFromWindow
; In the end we still want the autoit object. This function converts a raw pointer to an autoit object
Func ConvertPtrToIDispatch($pIDispatch)
    ; This would have been 10000x easier if autoit had supported the idispatch* type in dllstructs...
    ; Fortunetely memcpy can copy the pointer into a idispatch*, lucky us.
    Local $aCall = DllCall("kernel32.dll", "none", "RtlMoveMemory", _
            "idispatch*", 0, _
            "ptr*", $pIDispatch, _
            "dword", 4)

    If @error Then
        Return SetError(1, 0, 0)
    EndIf

    Return $aCall[1]

EndFunc ;==>ConvertPtrToIDispatch

Func __Au3Obj_ConvertPtrToIDispatch($pIDispatch)
    ; Author: monoceres
    Local $iSize = 4+(4*@AutoItX64)
    Local $aCall = DllCall("kernel32.dll", "none", "RtlMoveMemory", "idispatch*", 0, "ptr*", $pIDispatch, "dword", $iSize)
    If @error Then Return SetError(1, 0, 0)
    Return $aCall[1]
EndFunc   ;==>__Au3Obj_ConvertPtrToIDispatch
Func __Au3Obj_VariantClear($pvarg)
    ; Author: Prog@ndy
    Local $aCall = DllCall($hOleAut, "long", "VariantClear", "ptr", $pvarg)
    If @error Then Return SetError(1, 0, 1)
    Return $aCall[0]
EndFunc   ;==>__Au3Obj_VariantClear
Func __Au3Obj_VariantInit($pvarg)
    ; Author: Prog@ndy
    Local $aCall = DllCall($hOleAut, "long", "VariantInit", "ptr", $pvarg)
    If @error Then Return SetError(1, 0, 1)
    Return $aCall[0]
EndFunc   ;==>__Au3Obj_VariantInit

Func VTType2AutoitType($iVT_Type)
    ConsoleWrite("! " & $iVT_Type & @CRLF)
    Switch $iVT_Type
        Case $VT_I1
            Return "byte"
        Case $VT_I2
            Return "short"
        Case $VT_I4
            Return "int"
        Case $VT_BSTR
            Return "wstr"
        Case $VT_R8
            Return "double"
        Case $VT_DISPATCH
            Return "idispatch"
    EndSwitch
EndFunc ;==>VTType2AutoitType
Func COMVariantToValue($pVariant)
    Local $hVariant = DllStructCreate($tagVARIANT, $pVariant)
    ; Translate the vt id to a autoit dllcall type
    $sType = VTType2AutoitType(DllStructGetData($hVariant, "vt"))


    If $sType = "wstr" Then
        $pString = DllStructCreate("ptr", DllStructGetPtr($hVariant, "data"))
        ; Getting random crashes when trusting autoit to automatically use right size.
        ; doing it myself instead (also, it should be a BSTR, but it's not. Is autoit not obeying the rules!?
        $iString_Size = wcslen(DllStructGetData($pString, 1))

        ; Sorry trancexx, doesn't seem to work on large strings (crashes like crazy when trying to use on 1 MB string)
        ;$tSub = DllStructCreate("dword", DllStructGetData($str_ptr, 1) - 4) ; <- move pointer back 4 bytes!

        $hData = DllStructCreate("wchar[" & $iString_Size & "]", DllStructGetData($pString, 1))

    ElseIf $sType = "idispatch" Then

        Return ConvertPtrToIDispatch(DllStructGetData(DllStructCreate("ptr", DllStructGetPtr($hVariant, "data")), 1))

    Else
        $hData = DllStructCreate($sType, DllStructGetPtr($hVariant, "data"))
    EndIf

    Return DllStructGetData($hData, 1)
EndFunc ;==>COMVariantToValue

; Find out length of string. I do not trust autoit to do this.
Func wcslen($pWString)
    $aCall = DllCall("ntdll.dll", "dword:cdecl", "wcslen", "ptr", $pWString)
    Return $aCall[0]
EndFunc ;==>wcslen



Func _Quit()

    Exit

EndFunc   ;==>_Quit
;

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?加入

×

评分

参与人数 2金钱 +30 贡献 +2 收起 理由
xiehuahere + 10 辛苦了
afan + 20 + 2

查看全部评分

 楼主| 发表于 2010-4-8 09:40:42 | 显示全部楼层
楼上的辛苦了。
就控件本身的那段代码,我看明白了。
具体到按钮,确实那个。。。非常复杂。QTP下面一个语句就完成的事情,到AutoIt中真是不可想象。把我给吓住了啊。没有简单一些的方法了吗?
谢谢帮忙,我再下去研究一下啊。
发表于 2010-4-8 15:39:11 | 显示全部楼层
thank you very much
发表于 2010-4-8 22:33:57 | 显示全部楼层
看了CHM帮助,没找到? - -|||
#include <GUIToolbar.au3>
_GUICtrlToolbar_GetButtonState($hWnd, $iCommandID)
 楼主| 发表于 2010-4-9 09:52:22 | 显示全部楼层
版主,你好!

这个函数我是看到了的,但我认为这是用在Toolbar是自己创建的前提下,才能得知它的句柄。
否则,每次软件打开的时候,句柄都不一样,第一个参数如何填写呢?
困惑。。。请指教啊
发表于 2010-4-9 10:42:06 | 显示全部楼层
本帖最后由 lainline 于 2010-4-9 10:43 编辑

控件类型和序号不会变的 用ControlGetHandle获取句柄
另外我正在搜集oleacc.dll的调用函数 准备做个库

还是觉得这个技术比较有用详见
http://www.vckbase.com/document/viewdoc/?id=883
 楼主| 发表于 2010-4-9 12:50:42 | 显示全部楼层
本帖最后由 xiehuahere 于 2010-4-9 13:29 编辑

谢谢,可为什么我获取出来的状态值始终是-1呢?
#include <GUIToolbar.au3>

WinActivate("TestWindow")
WinWaitActive("TestWindow")
ControlFocus("TestWindow", "", "ToolbarWindow321")

$hToolbar = ControlGetHandle("TestWindow", "", "ToolbarWindow321") ;TestWindow是我的窗口标题
$buttonStatus = _GUICtrlToolbar_GetButtonState($hToolbar, 3) ;Toolbar上的第3个按钮
MsgBox(0, "Button", $buttonStatus)
_GUICtrlToolbar_GetButtonState($hWnd, $iCommandID)
不知道其中的 $iCommandID 是什么意思,从哪里来的。汗......
发表于 2010-4-9 13:51:50 | 显示全部楼层
本帖最后由 lainline 于 2010-4-9 14:30 编辑

ControlGetHandle("TestWindow","","[CLASSNN:ToolbarWindow321]")



GUICtrlToolbar 好像不行大概是程序独立内存问题
 楼主| 发表于 2010-4-9 14:55:54 | 显示全部楼层
貌似不需要 [CLASSNN:ToolbarWindow321] 吧
帮助里的例子也没有这样用啊:$handle = ControlGetHandle("Untitled - Notepad", "", "Edit1")

我的$iCommandID也是从1开始的,我是Toolbar上的第3个按钮,可还是返回-1啊

已经Enable的效果:


鼠标放到按钮上的效果:

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?加入

×
发表于 2010-4-9 16:51:01 | 显示全部楼层
按钮经过OLE封装对外属性是私有的只能经过DLL调用
 楼主| 发表于 2010-4-9 17:28:03 | 显示全部楼层
好,知道了。谢谢。
您需要登录后才可以回帖 登录 | 加入

本版积分规则

QQ|手机版|小黑屋|AUTOIT CN ( 鲁ICP备19019924号-1 )谷歌 百度

GMT+8, 2024-5-20 12:03 , Processed in 0.086247 second(s), 29 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表