trancexx Posted July 26, 2009 Share Posted July 26, 2009 So, here's the thing. You create ActiveX control. To have full functionality handle to that control is required.I'm not very good with this stuff, so I don't know if it's been done before. If it is... aahh well.I find it to be very useful and actually kind of fundamental. Function WindowFromAccessibleObject from oleacc.dll is used to do the job.What's really interesting is that I'm building the code on undocumented AutoIt's feature. On "idispatch" type. Very interesting thing and I must say it offers some new (to me) possibilities.I have made some other successful calls past few days with it and looks kind of cool now.Anyway, this is the function:;#FUNCTION# ;=============================================================================== ; ; Name...........: _GetObjectWinHandle ; Description ...: Retrieves the window handle of/for the specified object ; Syntax.........: _GetObjectWinHandle($oObject) ; Parameters ....: $oObject - object ; Return values .: Success - Returns window handle of the object ; Failure - Returns 0 sets @error: ; |1 - WindowFromAccessibleObject function or call to it failed ; Remarks........: Function uses undocumented AutoIt's type "idispatch". ; Author ........: trancexx ; ;========================================================================================== 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 ; And this could be an example of usage:expandcollapse popup#include <WinAPI.au3> #include <GUIConstantsEx.au3> #include <WindowsConstants.au3> Opt("WinWaitDelay", 0) Opt("GUIOnEventMode", 1) ; Make a GUI Global $hGui = GUICreate("ActiveX", 800, 500) ; Create object Global $oIEObject = ObjCreate("Shell.Explorer.2") ; Check if it's created If Not IsObj($oIEObject) Then MsgBox(262144 + 48, "Error!", "Could not create object. That's bad!") Exit EndIf ; Create ActiveY control Global $hActiveX = GUICtrlCreateObj($oIEObject, 0, 0, 800, 400) ; Hide it for now GUICtrlSetState($hActiveX, $GUI_HIDE) ; Some page Global $sURL = "www.yahoo.com" ; Navigate to that page $oIEObject.navigate($sURL) ; Exit function GUISetOnEvent($GUI_EVENT_CLOSE, "_Quit") ; Wait cursor GUISetCursor(15) ; Show GUI GUISetState() ; Get that handle Global $hObjWinHandle = _GetObjectWinHandle($oIEObject) ; Write it ConsoleWrite("! $oIEObject win handle: " & $hObjWinHandle & @CRLF) ; Change style (got to do something with the handle now that I have it) Global Const $GWL_STYLE = -16 _WinAPI_SetWindowLong($hObjWinHandle, $GWL_STYLE, BitOR($WS_OVERLAPPEDWINDOW, $WS_CHILD)) ; Change title too WinSetTitle($hObjWinHandle, 0, "My embedded browser") ; Show it GUICtrlSetState($hActiveX, $GUI_SHOW) ; Needed to check state Global $iNotLoaded = 1 ; Will get another handle, declare variable for it Global $hObjDocWinHandle ; for other handle ; Loop till end While 1 If $iNotLoaded Then ; some strange way of checking if loaded If IsObj($oIEObject.document) Then $hObjDocWinHandle = _GetObjectWinHandle($oIEObject.document) ConsoleWrite("! $oIEObject.document win handle: " & $hObjDocWinHandle & @CRLF) ; this is what you normally get with AutoIt Window Info tool GUISetCursor(-1) $iNotLoaded = 0 EndIf EndIf Sleep(100) WEnd ; 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 _Quit() Exit EndFunc ;==>_Quit ; EndI lack Obj() knowledge so the example is rather plain, maybe even pointless. Nevertheless I see great potential of this function. That's why I fail to see why isn't there something like it already. But I guess there is always a possibility that I overlooked it. ♡♡♡ . eMyvnE Link to comment Share on other sites More sharing options...
Authenticity Posted July 27, 2009 Share Posted July 27, 2009 ..and the opposite: expandcollapse popup; http://social.msdn.microsoft.com/Forums/en-US/ieextensiondevelopment/thread/6c926f83-3eca-47ef-882f-c7f8816b9000/ ; Most of this is from there so I'd like to thank Asmdev for his/her straightforward code snippet. #include <IE.au3> #include <StructureConstants.au3> ; Very important. If a function is called without a dll reference it'll get freed ; so the objects methods will not be accessible. At least in the case of oleacc.dll. Global $hdll = DllOpen('oleacc.dll') Global Const $tagVARIANT = 'int[4];' Global Const $OBJID_CLIENT = 0xFFFFFFFC Global Const $ROLE_SYSTEM_PAGETABLIST = 60 Global Const $CHILDID_SELF = 0 Global Const $VT_DISPATCH = 9 Global Const $VT_I4 = 3 Global Const $navOpenInNewTab = 2048 Global $tVAR = DllStructCreate($tagVARIANT) DllStructSetData($tVAR, 1, $VT_I4, 1) DllStructSetData($tVAR, 1, $CHILDID_SELF, 2) Global $tIID_IAccessible = DllStructCreate($tagGUID) DllStructSetData($tIID_IAccessible, 1, 0x618736e0) DllStructSetData($tIID_IAccessible, 2, 0x3c3d) DllStructSetData($tIID_IAccessible, 3, 0x11cf) DllStructSetData($tIID_IAccessible, 4, '0x810c00aa00389b71') Global $oIE = _IECreate('http://www.google.com') Global $hIE = _IEPropertyGet($oIE, 'hwnd') ; This is the control handle we will *interface* with. Global $hTab = ControlGetHandle($hIE, '', '[CLASS:DirectUIHWND]') ; Open in new tabs. $oIE.Navigate('http://www.yahoo.com', $navOpenInNewTab) $oIE.Navigate('http://www.tenouk.com', $navOpenInNewTab) ; Give it a little time to load Sleep(5000) ; Get accessible object interface from a window handle Global $pResult = _AccessibleObjectFromWindow($hTab, $OBJID_CLIENT, $tIID_IAccessible, $hdll) ; Get number of contained children. Global $iChildren = _get_accChildCount($pResult) ; Retrieve IDispatch interface address or child ID of children. Global $tTabs = _AccessibleChildren($pResult, 0, $iChildren, $hdll) ; Enumerating the child objects and proceeding only if the current child is of PageControl object. For $i = 1 To $iChildren ; If VARIANT.pdispVal has information then proceed. ; if (vTabs[i].vt == VT_DISPATCH) If BitAND(DllStructGetData($tTabs, $i, 1), 0xFFFF) = $VT_DISPATCH Then ; Get an object interface. Local $pObjTabs = _QueryInterface(DllStructGetData($tTabs, $i, 3), $tIID_IAccessible) ; Retrieve information that describes the role of the object. Local $tResTab = _get_accRole($pObjTabs, $tVAR) ; If it's role is to tab-list then proceed ; if (vTab.lVal == $ROLE_SYSTEM_PAGETABLIST) If DllStructGetData($tResTab, 1, 3) = $ROLE_SYSTEM_PAGETABLIST Then ; So it's a tab-list control which in part is a container. ; Get child count. $iChildren = _get_accChildCount($pObjTabs) ; Retrieve IDispatch interface address or child ID of children. $tTab = _AccessibleChildren($pObjTabs, 0, $iChildren, $hdll) For $j = 1 To $iChildren ; Get an object interface. Local $pAccTab = _QueryInterface(DllStructGetData($tTab, $j, 3), $tIID_IAccessible) ; Get an object name. ; Much like getting an internet explorer object's current title property. ConsoleWrite(_get_accName($pAccTab, $tVAR) & @LF) Next EndIf EndIf Next DllClose($hdll) Exit ; ######################################################################################################## Func _AccessibleObjectFromWindow($hWnd, $iObjId, $tRefIID, $hOleacc = 'oleacc.dll') Local $aResult $aResult = DllCall($hOleacc, 'int', 'AccessibleObjectFromWindow', 'hwnd', $hWnd, 'uint', $iObjId, 'ptr', DllStructGetPtr($tRefIID), 'int*', 0) If @error Then Return SetError(@error, @extended, 0) Return SetError($aResult[0], 0, $aResult[4]) EndFunc ; ######################################################################################################## Func _AccessibleChildren($paccContainer, $iChildStart, $iChildren, $hOleacc = 'oleacc.dll') Local $tVARIANT, $pVARIANT Local $sStruct = '' Local $aResult For $i = 1 To $iChildren $sStruct &= $tagVARIANT Next $tVARIANT = DllStructCreate($sStruct) $pVARIANT = DllStructGetPtr($tVARIANT) $aResult = DllCall($hOleacc, 'int', 'AccessibleChildren', 'ptr', $paccContainer, 'int', $iChildStart, 'int', $iChildren, 'ptr', $pVARIANT, 'int*', 0) If @error Then Return SetError(@error, @extended, 0) Return SetError(0, $aResult[5], $tVARIANT) EndFunc ; ######################################################################################################## Func _get_accChildCount($pObj) Local $tCall, $pCall, $xCall Local $tBuff $tBuff = DllStructCreate('int') $xCall = '0x8D05' & SwapEndian(DllStructGetPtr($tBuff)) & _ ; lea eax, dword ptr [tBuff] '50' & _ ; push eax 'B8' & SwapEndian($pObj) & _ ; mov eax, pObj '50' & _ ; push eax 'A1' & SwapEndian($pObj) & _ ; mov eax, dword ptr [pObj] 'FF5020' & _ ; call dword ptr [eax + 20] 'C3' ; ret $tCall = DllStructCreate('byte[' & BinaryLen($xCall) & ']') $pCall = DllStructGetPtr($tCall) DllStructSetData($tCall, 1, $xCall) DllCall("user32.dll", "none", "CallWindowProc", "ptr", $pCall, "int", 0, "int", 0, "int", 0, "int", 0) Return DllStructGetData($tBuff, 1) EndFunc ; ######################################################################################################## Func _get_accRole($pObj, $tQueryVAR) Local $tCall, $pCall, $xCall Local $tVarRole $tVarRole = DllStructCreate('int[4]') $xCall = '0x8D05' & SwapEndian(DllStructGetPtr($tVarRole)) & _ ; lea eax, dword ptr [tVarRole] '50' & _ ; push eax 'A1' & SwapEndian(DllStructGetPtr($tQueryVAR, 1)+12) & _ ; mov eax, dword ptr [tQueryVAR + C] '50' & _ ; push eax 'A1' & SwapEndian(DllStructGetPtr($tQueryVAR, 1)+8) & _ ; mov eax, dword ptr [tQueryVAR + 8] '50' & _ ; push eax 'A1' & SwapEndian(DllStructGetPtr($tQueryVAR, 1)+4) & _ ; mov eax, dword ptr [tQueryVAR + 4] '50' & _ ; push eax 'A1' & SwapEndian(DllStructGetPtr($tQueryVAR, 1)) & _ ; mov eax, dword ptr [tQueryVAR] '50' & _ ; push eax 'B8' & SwapEndian($pObj) & _ ; mov eax, pObj '50' & _ ; push eax 'A1' & SwapEndian($pObj) & _ ; mov eax, dword ptr [pObj] 'FF5034' & _ ; call dword ptr [eax + 34] 'C3' ; ret $tCall = DllStructCreate('byte[' & BinaryLen($xCall) & ']') $pCall = DllStructGetPtr($tCall) DllStructSetData($tCall, 1, $xCall) DllCall("user32.dll", "none", "CallWindowProc", "ptr", $pCall, "int", 0, "int", 0, "int", 0, "int", 0) Return $tVarRole EndFunc ; ######################################################################################################## Func _get_accName($pObj, $tQueryVAR) Local $tCall, $pCall, $xCall Local $tBSTR, $tBuffer $tBSTR = DllStructCreate('int') $xCall = '0x8D05' & SwapEndian(DllStructGetPtr($tBSTR)) & _ ; lea eax, dword ptr [tBSTR] '50' & _ ; push eax 'A1' & SwapEndian(DllStructGetPtr($tQueryVAR, 1)+12) & _ ; mov eax, dword ptr [tQueryVAR + C] '50' & _ ; push eax 'A1' & SwapEndian(DllStructGetPtr($tQueryVAR, 1)+8) & _ ; mov eax, dword ptr [tQueryVAR + 8] '50' & _ ; push eax 'A1' & SwapEndian(DllStructGetPtr($tQueryVAR, 1)+4) & _ ; mov eax, dword ptr [tQueryVAR + 4] '50' & _ ; push eax 'A1' & SwapEndian(DllStructGetPtr($tQueryVAR, 1)) & _ ; mov eax, dword ptr [tQueryVar] '50' & _ ; push eax 'B8' & SwapEndian($pObj) & _ ; mov eax, pObj '50' & _ ; push eax 'A1' & SwapEndian($pObj) & _ ; mov eax, dword ptr [pObj] 'FF5028' & _ ; call dword ptr [eax + 28] 'C3' ; ret $tCall = DllStructCreate('byte[' & BinaryLen($xCall) & ']') $pCall = DllStructGetPtr($tCall) DllStructSetData($tCall, 1, $xCall) DllCall("user32.dll", "none", "CallWindowProc", "ptr", $pCall, "int", 0, "int", 0, "int", 0, "int", 0) $tBuffer = DllStructCreate('wchar[256]', DllStructGetData($tBSTR, 1)) Return DllStructGetData($tBuffer, 1) EndFunc ; ######################################################################################################## Func _QueryInterface($pObj, $tRefIID) Local $tCall, $pCall, $xCall Local $tBuff $tBuff = DllStructCreate('int') $xCall = '0x8D05' & SwapEndian(DllStructGetPtr($tBuff)) & _ ; lea eax, dword ptr [tBuff] '50' & _ ; push eax '68' & SwapEndian(DllStructGetPtr($tRefIID)) & _ ; push [tRefIID] 'B8' & SwapEndian($pObj) & _ ; mov eax, pObj '50' & _ ; push eax 'A1' & SwapEndian($pObj) & _ ; mov eax, dword ptr [pObj] 'FF10' & _ ; call dword ptr [eax] 'C3' ; ret $tCall = DllStructCreate('byte[' & BinaryLen($xCall) & ']') $pCall = DllStructGetPtr($tCall) DllStructSetData($tCall, 1, $xCall) DllCall("user32.dll", "none", "CallWindowProc", "ptr", $pCall, "int", 0, "int", 0, "int", 0, "int", 0) Return DllStructGetData($tBuff, 1) EndFunc ; ######################################################################################################## Func SwapEndian($hex) Return StringFormat('%.8s', Hex(Binary($hex))) ;Return Hex(Binary($hex)) EndFunc ;==>SwapEndian ; ######################################################################################################## Link to comment Share on other sites More sharing options...
trancexx Posted July 27, 2009 Author Share Posted July 27, 2009 (edited) That's massive!... I said that I did some other calls with "idispatch" , check this:expandcollapse popup#include <WinAPI.au3> #include <GUIConstantsEx.au3> #include <WindowsConstants.au3> Opt("WinWaitDelay", 0) Opt("GUIOnEventMode", 1) Opt("MustDeclareVars", 1) Global $oMyError = ObjEvent("AutoIt.Error", "_ErrFunc") Global $hOLEACC = DllOpen("oleacc.dll") ; Make a GUI Global $hGui = GUICreate("ActiveX", 800, 500) ; Create object Global $oIEObject = ObjCreate("Shell.Explorer.2") ; Check if it's created If Not IsObj($oIEObject) Then MsgBox(262144 + 48, "Error!", "Could not create object. That's bad!") Exit EndIf ; Create ActiveY control Global $hActiveX = GUICtrlCreateObj($oIEObject, 0, 0, 800, 400) ; Hide it for now GUICtrlSetState($hActiveX, $GUI_HIDE) ; Some page Global $sURL = "www.yahoo.com" ; Navigate to that page $oIEObject.navigate($sURL) ; Exit function GUISetOnEvent($GUI_EVENT_CLOSE, "_Quit") ; Wait cursor GUISetCursor(15) ; Show GUI GUISetState() ; Get that handle Global $hObjWinHandle = _GetObjectWinHandle($oIEObject) ; Write it ConsoleWrite("! $oIEObject win handle: " & $hObjWinHandle & @CRLF) ; New function Global $oAccessibleObject = _AccessibleObjectFromWindow($hObjWinHandle) ; Gained: If IsObj($oAccessibleObject) Then ; ConsoleWrite("accChild: " & $oAccessibleObject.accChild($Param) & @CRLF) ;<- ConsoleWrite("accChildCount: " & $oAccessibleObject.accChildCount & @CRLF) ConsoleWrite("accDefaultAction: " & $oAccessibleObject.accDefaultAction & @CRLF) ConsoleWrite("accDescription: " & $oAccessibleObject.accDescription & @CRLF) ConsoleWrite("accFocus: " & $oAccessibleObject.accFocus & @CRLF) ConsoleWrite("accHelp: " & $oAccessibleObject.accHelp & @CRLF) ; ConsoleWrite("accHelpTopic: " & $oAccessibleObject.accHelpTopic($Param) & @CRLF) ;<- ConsoleWrite("accKeyboardShortcut: " & $oAccessibleObject.accKeyboardShortcut & @CRLF) ConsoleWrite("accName: " & $oAccessibleObject.accName & @CRLF) ConsoleWrite("accParent: " & $oAccessibleObject.accParent & @CRLF) ConsoleWrite("accRole: " & $oAccessibleObject.accRole & @CRLF) ConsoleWrite("accSelection: " & $oAccessibleObject.accSelection & @CRLF) ConsoleWrite("accState: " & $oAccessibleObject.accState & @CRLF) ConsoleWrite("accValue: " & $oAccessibleObject.accValue & @CRLF) EndIf ConsoleWrite(@CRLF) #cs ; Change style (got to do something with the handle now that I have it) Global Const $GWL_STYLE = -16 _WinAPI_SetWindowLong($hObjWinHandle, $GWL_STYLE, BitOR($WS_OVERLAPPEDWINDOW, $WS_CHILD)) #ce ; Change title WinSetTitle($hObjWinHandle, 0, "My embedded browser") ; Show it GUICtrlSetState($hActiveX, $GUI_SHOW) ; Needed to check state Global $iNotLoaded = 1 ; Will get another handle, declare variable for it Global $hObjDocWinHandle ; for other handle ; New objects Global $oIEObjectDocument Global $oAccessibleObjectDoc ; For moving (nothing smart) Global $iX Global $iUp ; Loop till end While 1 If $iNotLoaded Then $oIEObjectDocument = $oIEObject.document If IsObj($oIEObjectDocument) Then ;Wait till fully loaded While 1 If $oIEObjectdocument.readyState = "complete" Or $oIEObjectdocument.readyState = 4 Then ExitLoop Sleep(100) WEnd $hObjDocWinHandle = _GetObjectWinHandle($oIEObjectDocument) ConsoleWrite("! $oIEObject.document win handle: " & $hObjDocWinHandle & @CRLF) ; this is what you normally get with AutoIt Window Info tool $oAccessibleObjectDoc = _AccessibleObjectFromWindow($hObjDocWinHandle) If IsObj($oAccessibleObjectDoc) Then ; ConsoleWrite("accChild: " & $oAccessibleObject.accChild($Param) & @CRLF) ;<- limitation ConsoleWrite("accChildCount: " & $oAccessibleObjectDoc.accChildCount & @CRLF) ConsoleWrite("accDefaultAction: " & $oAccessibleObjectDoc.accDefaultAction & @CRLF) ConsoleWrite("accDescription: " & $oAccessibleObjectDoc.accDescription & @CRLF) ConsoleWrite("accFocus: " & $oAccessibleObjectDoc.accFocus & @CRLF) ConsoleWrite("accHelp: " & $oAccessibleObjectDoc.accHelp & @CRLF) ; ConsoleWrite("accHelpTopic: " & $oAccessibleObjectDoc.accHelpTopic($Param) & @CRLF) ;<- limitation ConsoleWrite("accKeyboardShortcut: " & $oAccessibleObjectDoc.accKeyboardShortcut & @CRLF) ConsoleWrite("accName: " & $oAccessibleObjectDoc.accName & @CRLF) ConsoleWrite("accParent: " & $oAccessibleObjectDoc.accParent & @CRLF) ConsoleWrite("accRole: " & $oAccessibleObjectDoc.accRole & @CRLF) ConsoleWrite("accSelection: " & $oAccessibleObjectDoc.accSelection & @CRLF) ConsoleWrite("accState: " & $oAccessibleObjectDoc.accState & @CRLF) ConsoleWrite("accValue: " & $oAccessibleObjectDoc.accValue & @CRLF) EndIf ; Restore cursot GUISetCursor(-1) $iNotLoaded = 0 EndIf Else WinMove($hObjWinHandle, 0, $iX, 0) If $iX > 100 Then $iUp = -1 ElseIf $iX <= 0 Then $iUp = 1 EndIf $iX += $iUp EndIf Sleep(30) WEnd ; 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 _ErrFunc() ConsoleWrite("--- COM Error, number = " & Ptr($oMyError.number) & ", description: " & $oMyError.windescription) EndFunc ;==>_ErrFunc Func _Quit() Exit EndFunc ;==>_Quit ;We had the same findings about loading oleacc.dll. That's great!I run first post example on Vista, and was not pleased with what I find. That is to say that I made a mistake with not waiting for page to fully load. That must be done before processing that object.It's fixed here.edit:Call to CoInitialize would be smart to add at the beginning of the script, or maybe:DllCall("ole32.dll", "int", "CoInitializeEx", "ptr", 0, "dword", 2) ;COINIT_APARTMENTTHREADEDI added error checking for AccessibleObjectFromWindow function Edited July 27, 2009 by trancexx mLipok 1 ♡♡♡ . eMyvnE Link to comment Share on other sites More sharing options...
VAG Posted July 28, 2009 Share Posted July 28, 2009 I am working on a project to control WPF in Vista, using AutoIT Window Info has no help to me. Is there any help of getting object winhandle using oleacc.dll on WPF application through this? Link to comment Share on other sites More sharing options...
trancexx Posted July 28, 2009 Author Share Posted July 28, 2009 I am working on a project to control WPF in Vista, using AutoIT Window Info has no help to me. Is there any help of getting object winhandle using oleacc.dll on WPF application through this? You have object? ♡♡♡ . eMyvnE 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