Jump to content
junkew

IUIAutomation MS framework automate chrome, FF, IE, ....

Recommended Posts

Hi junknew.

Thanks for your help.

Is possible to set the font size off a WindowsForms10.RichEdit20W.app.0.13965fa_r26_ad1 to this format (16, Calibri), using your UDF? I´m already try use the function _GUICtrlRichEdit_SetFont, but the program with the richedit always hangs. Regards.

Quote

_GUICtrlRichEdit_SetSel($hRichEdit, 0, -1)
_GUICtrlRichEdit_SetFont($hRichEdit,16,"Calibri")
_GUICtrlRichEdit_Deselect($hRichEdit) ; deselect all

 

Share this post


Link to post
Share on other sites

It should be possible with the textrange pattern.

See https://msdn.microsoft.com/en-us/library/windows/desktop/ee872119(v=vs.85).aspx

I do not have an example of it. For sure you cannot mix in general the autoit functions with the functions of this udf.

Edited by junkew

Share this post


Link to post
Share on other sites
7 hours ago, junkew said:

It should be possible with the textrange pattern.

See https://msdn.microsoft.com/en-us/library/windows/desktop/ee872119(v=vs.85).aspx

I do not have an example of it. For sure you cannot mix in general the autoit functions with the functions of this udf.

Hi.

Thanks a lot for your help.  I try to use this function code, but no sucess. I will try to use another autoit functions.

Quote

_UIA_getPropertyValue($oUIElement, $UIA_FontSizeAttributeId)

 

Share this post


Link to post
Share on other sites
  1. Check with simplespy if textrange pattern is true. Post full output of simplespy can help.
  2. If true get the textrange patternobject
  3. Use the functions of the textrange object.

Not sure if i ever validated the interfaces for the textpattern interface.

Share this post


Link to post
Share on other sites
On 3/1/2018 at 10:35 AM, junkew said:
  1. Check with simplespy if textrange pattern is true. Post full output of simplespy can help.
  2. If true get the textrange patternobject
  3. Use the functions of the textrange object.

Not sure if i ever validated the interfaces for the textpattern interface.

Hi.

Here is the output of simplespy. It´s say "UIA_IsTextPatternAvailable:= <False>". So, i cannot format the size of text. It´s right? Regards.

Quote

*** Detailed properties of the highlighted element ***
UIA_class:= <WindowsForms10.RichEdit20W.app.0.13965fa_r26_ad1>
UIA_regexpclass:= <WindowsForms10.RichEdit20W.app.0.13965fa_r26_ad1>
UIA_iaccessiblevalue:= <test>
UIA_iaccessiblechildId:= <0>
UIA_id:= <edit1>
UIA_handle:= <66452>
UIA_RuntimeId:= <42;66452>
UIA_BoundingRectangle:= <125;204;964;120>
UIA_ProcessId:= <5352>
UIA_ControlType:= <50004>
UIA_LocalizedControlType:= <Edit>
UIA_HasKeyboardFocus:= <True>
UIA_IsKeyboardFocusable:= <True>
UIA_IsEnabled:= <True>
UIA_AutomationId:= <edit1>
UIA_ClassName:= <WindowsForms10.RichEdit20W.app.0.13965fa_r26_ad1>
UIA_Culture:= <0>
UIA_IsControlElement:= <True>
UIA_IsContentElement:= <True>
UIA_IsPassword:= <False>
UIA_NativeWindowHandle:= <66452>
UIA_IsOffscreen:= <False>
UIA_Orientation:= <0>
UIA_FrameworkId:= <WinForm>
UIA_IsRequiredForForm:= <False>
UIA_IsDockPatternAvailable:= <False>
UIA_IsExpandCollapsePatternAvailable:= <False>
UIA_IsGridItemPatternAvailable:= <False>
UIA_IsGridPatternAvailable:= <False>
UIA_IsInvokePatternAvailable:= <False>
UIA_IsMultipleViewPatternAvailable:= <False>
UIA_IsRangeValuePatternAvailable:= <False>
UIA_IsScrollPatternAvailable:= <True>
UIA_IsScrollItemPatternAvailable:= <False>
UIA_IsSelectionItemPatternAvailable:= <False>
UIA_IsSelectionPatternAvailable:= <False>
UIA_IsTablePatternAvailable:= <False>
UIA_IsTableItemPatternAvailable:= <False>
UIA_IsTextPatternAvailable:= <False>
UIA_IsTogglePatternAvailable:= <False>
UIA_IsTransformPatternAvailable:= <False>
UIA_IsValuePatternAvailable:= <True>
UIA_IsWindowPatternAvailable:= <False>
UIA_ValueValue:= <test>
UIA_ValueIsReadOnly:= <False>
UIA_RangeValueValue:= <0>
UIA_RangeValueIsReadOnly:= <True>
UIA_RangeValueMinimum:= <0>
UIA_RangeValueMaximum:= <0>
UIA_RangeValueLargeChange:= <0>
UIA_RangeValueSmallChange:= <0>
UIA_ScrollHorizontalScrollPercent:= <0>
UIA_ScrollHorizontalViewSize:= <100>
UIA_ScrollVerticalScrollPercent:= <0>
UIA_ScrollVerticalViewSize:= <91.6030534351145>
UIA_ScrollHorizontallyScrollable:= <False>
UIA_ScrollVerticallyScrollable:= <True>
UIA_SelectionCanSelectMultiple:= <False>
UIA_SelectionIsSelectionRequired:= <False>
UIA_GridRowCount:= <0>
UIA_GridColumnCount:= <0>
UIA_GridItemRow:= <0>
UIA_GridItemColumn:= <0>
UIA_GridItemRowSpan:= <1>
UIA_GridItemColumnSpan:= <1>
UIA_DockDockPosition:= <5>
UIA_ExpandCollapseExpandCollapseState:= <3>
UIA_MultipleViewCurrentView:= <0>
UIA_WindowCanMaximize:= <False>
UIA_WindowCanMinimize:= <False>
UIA_WindowWindowVisualState:= <0>
UIA_WindowWindowInteractionState:= <0>
UIA_WindowIsModal:= <False>
UIA_WindowIsTopmost:= <False>
UIA_SelectionItemIsSelected:= <False>
UIA_TableRowOrColumnMajor:= <2>
UIA_ToggleToggleState:= <2>
UIA_TransformCanMove:= <False>
UIA_TransformCanResize:= <False>
UIA_TransformCanRotate:= <False>
UIA_IsLegacyIAccessiblePatternAvailable:= <True>
UIA_LegacyIAccessibleChildId:= <0>
UIA_LegacyIAccessibleValue:= <test>
UIA_LegacyIAccessibleRole:= <42>
UIA_LegacyIAccessibleState:= <1048580>
UIA_IsDataValidForForm:= <False>
UIA_ProviderDescription:= <[pid:5404,hwnd:0x10394 Main:Nested [pid:5352,hwnd:0x10394 Main(parent link):Microsoft: MSAA Proxy (unmanaged:uiautomationcore.dll)]; Nonclient:Microsoft: Non-Client Proxy (unmanaged:uiautomationcore.dll); Hwnd(parent link):Microsoft: HWND Proxy (unmanaged:uiautomationcore.dll)]>
UIA_IsItemContainerPatternAvailable:= <False>
UIA_IsVirtualizedItemPatternAvailable:= <False>
UIA_IsSynchronizedInputPatternAvailable:= <False>

 

 

Share this post


Link to post
Share on other sites

I am not an expert in the MS rich edit controls but I know you can manipulate them with sendmessage EM_SETPARAFORMAT / EM_GETPARAFORMAT message and a lot of other messages by dealing with wparam and lparam

https://msdn.microsoft.com/en-us/library/windows/desktop/bb774182(v=vs.85).aspx

But you are right you cannot do it with UIA as there is no textpattern

 

I would expect  _GUICtrlRichEdit_SetFont($hRichEdit,16,"Calibri")  to use sendmessage/postmessage under the hood but not fully sure.
Maybe your $hRichEdit handle is not the control handle.

Share this post


Link to post
Share on other sites
8 hours ago, junkew said:

I am not an expert in the MS rich edit controls but I know you can manipulate them with sendmessage EM_SETPARAFORMAT / EM_GETPARAFORMAT message and a lot of other messages by dealing with wparam and lparam

https://msdn.microsoft.com/en-us/library/windows/desktop/bb774182(v=vs.85).aspx

But you are right you cannot do it with UIA as there is no textpattern

 

I would expect  _GUICtrlRichEdit_SetFont($hRichEdit,16,"Calibri")  to use sendmessage/postmessage under the hood but not fully sure.
Maybe your $hRichEdit handle is not the control handle.

Hi.

Thanks for your help. I try to work in autoit, but everytimes i can put a thing working, another breaks. I think it´s because the program where are the controls that i want to format. When i use the function _GUICtrlRichEdit_SetFont, it sometimes format the font, but if i use the function again, the program hangs. Regards.

Share this post


Link to post
Share on other sites

I kept on searching for ways to make the search faster when there are 6000 results, and your needed object is like 5000th, but couldnt find any. So I just wrote a function to search from the rear and thought it might be useful to someone else(like me) as well, so I will post it here. Bare in mind that Im not a programmer of any kind and my code sucks a lot, but hey, you guys know your stuff so you might tweak it for your own use. The code is pretty dirty as well ^^; 
This crappy function can only search filter ControlTypeId, Name and IndexRelative(int) and will give the object found in $oReverseSearch

Func ReverseSearch($oElementStart, $TreeScope, $ControlType = "", $Name = "", $IndexRelative = "") ;Object, TreeScope, ControlTypeId, Name, IndexRelative(Int)
   local $oCondition, $pTrueCondition
   local $pElements, $iLength

   $UIA_oUIAutomation.CreateTrueCondition($pTrueCondition)
   $oCondition = ObjCreateInterface($pTrueCondition, $sIID_IUIAutomationCondition, $dtagIUIAutomationCondition)
   $oElementStart.FindAll($TreeScope, $oCondition, $pElements)

   local $oAutomationElementArray = ObjCreateInterface($pElements, $sIID_IUIAutomationElementArray, $dtagIUIAutomationElementArray)

   $oAutomationElementArray.Length($iLength)
   For $i = 0 To $iLength - 1; its zero based
      local $Match1 = 0
      local $Match2 = 0
      local $iReverse = $iLength - 1 - $i ;Reversing the order of the search

      $oAutomationElementArray.GetElement($iReverse, $UIA_pUIElement)

      local $oUIElement = ObjCreateInterface($UIA_pUIElement, $sIID_IUIAutomationElement, $dtagIUIAutomationElement)
      local $FoundControlTypePropertyId = _UIA_getPropertyValue($oUIElement, $UIA_ControlTypePropertyId)
      local $FoundNamePropertyId = _UIA_getPropertyValue($oUIElement, $UIA_NamePropertyId)

      If $ControlType <> "" Then
         If $FoundControlTypePropertyId = $ControlType Then
            $Match1 = 1
         EndIf
      Else
         $Match1 = 1
      EndIf
      If $Name <> "" Then
         If $FoundNamePropertyId = $Name Then
            $Match2 = 1
         EndIf
      Else
         $Match2 = 1
      EndIf

      If $Match1 = 1 And $Match2 = 1 Then
         If $IndexRelative <> "" And IsInt($IndexRelative) Then
            $iReverse = $iReverse + $IndexRelative
            $oAutomationElementArray.GetElement($iReverse, $UIA_pUIElement)
            local $oUIElement = ObjCreateInterface($UIA_pUIElement, $sIID_IUIAutomationElement, $dtagIUIAutomationElement)
            local $FoundControlTypePropertyId = _UIA_getPropertyValue($oUIElement, $UIA_ControlTypePropertyId)
            local $FoundNamePropertyId = _UIA_getPropertyValue($oUIElement, $UIA_NamePropertyId)
         EndIf
         $oReverseSearch = $oUIElement
         ConsoleWrite("Object found!" & @CRLF)
         ConsoleWrite("Name: <" & $FoundNamePropertyId & "> ")
         ConsoleWrite("ControlType: <" & $FoundControlTypePropertyId & "> ")
         If $IndexRelative <> "" And IsInt($IndexRelative) Then
            ConsoleWrite("IndexRelative: <" & $IndexRelative & "> ")
         EndIf
         ConsoleWrite("Reversed Position: <" & $iReverse & ">" & @CRLF)
         ExitLoop
      EndIf
   Next
EndFunc

If someone can improve on this please do and let me know ^^

Share this post


Link to post
Share on other sites

Findall with a true condition is slow. If you can make a condition which filters only controltypids of interest its much faster. And just using treewalkers can improve speed also a lot. See examples.zip

Share this post


Link to post
Share on other sites

Good Day junkew,

Thank you for your amazing work. I see that you include  a "getvalue" command. However, is there a way to get a "Name" value somehow?

 

my code

#include "UIAWrappers.au3"
AutoItSetOption("MustDeclareVars", 1)

Local $oP4=_UIA_getObjectByFindAll($UIA_oDesktop, "Title:=GOLDCORP - Gold Ore Mining", $treescope_children)
_UIA_Action($oP4,"setfocus")
Local $oP3=_UIA_getObjectByFindAll($oP4, "Title:=;controltype:=Tab", $treescope_children)
_UIA_Action($oP3,"setfocus")
Local $oP2=_UIA_getObjectByFindAll($oP3, "Title:=;controltype:=Pane", $treescope_children)
_UIA_Action($oP2,"setfocus")
Local $oP2=_UIA_getObjectByFindAll($oP3, "Title:=;controltype:=Pane", $treescope_children)
_UIA_Action($oP2,"setfocus")

Local $oP1=_UIA_getObjectByFindAll($oP2, "Title:=;controltype:=Text;instance:= 4", $treescope_children)
_UIA_Action($oP1,"setfocus")


local $oUIElement=_UIA_getObjectByFindAll($oP1, "controltype:=Text", $treescope_subtree)

Local $string = _UIA_action($oUIElement,"!!! GET NAME !!!")                 <--------------------------- Thats what i need :(
MsgBox($MB_OK,"", $string)

 

Capture.PNG

Share this post


Link to post
Share on other sites

Hey junkew,

great work on this - its really the solution I'm looking for, but I am having a bit of trouble getting my head around items.

looking at example 04 under vr 64, I get the following result when i run it. 

Share this post


Link to post
Share on other sites

@toto22 see first post. getvalue should work. Advice to do first ac5ion highlight to see you find the right object to interact with.

@MrCheese try simplespy on your object andvask for help in support forum. Examples frequently fail due to os language setting.

Share this post


Link to post
Share on other sites

Hi Junkew, to add to my post earlier. I am in example 4, adjusting the script to suit.

I'm getting this error:

Menuitem is NOT there"C:\Users\60080462\Google Drive\Work stuff\Macros\EXAMPLES_V0_64\ex4_calculator.au3" (119) : ==> Variable must be of type "Object".:
$oInvokeP.Invoke
$oInvokeP^ ERROR

 

the line above refers to: $oInvokeP=_UIA_getpattern($oButton,$UIA_InvokePatternID)

and $oButton is last used here:

local $sText="((Copy.*)|(Kopi.*))"    ;Copy
    $oButton=_UIA_getObjectByFindAll($oCalc,"name:=" & $sText, $treescope_subtree)
    if isobj($oButton) Then
        consolewrite("Menuitem is there")
    Else
        consolewrite("Menuitem is NOT there")
    EndIf
    sleep(2000)

 

so this implies that the script isn't able to find "Copy" or "Kopi". What is this part of the script attempting to do, and what do I need to change in order for it to continue?

One big question, what detail am I looking for when I am looking in simplyspy to extract the details of the field/box/button that I am currently mouseover, in order to select and enter in detail that I wish to enter in?

What is the command to read back text that has been entered into a field (or that is prepopulated)?

 

Ultimately, I need to develop a script that can:

* click buttons
* wait for the webpage to refresh before proceeding

*enter text into fields

* read text from fields.

 

Relating to your point about asking on the forum, would you suggest separate threads for each issue, or should I include example discussions in this thread since its related to the examples you posted?

 

Thanks

 

 

 

Share this post


Link to post
Share on other sites

is it possible that some webpages cannot be automated using this framework?

 

I have a number of fields on screen, but when I click them and run simplyspy attached are my outputs - it doesn't appear to be able to focus on it.

 

 

Output.txt

pagevisual.JPG

Share this post


Link to post
Share on other sites

Within chrome you should put accessibility to true. Then with simplespy you should see your element highlight. If it highlights you can access it. As it looks html page normally its accessible.

The error you see is due to object not found with the regular expression that you try. First automate calc.exe or google.com before you start on other pages,

 

Share this post


Link to post
Share on other sites

Okay, first of all I would like to commend junkew for this great tool.  

I have run into a little snag that I can't seem to figure out. Below is a snippet of my code. The script works great up until this point of getting me into our customer's data page. The purpose of this piece is to grab data from what is displayed so we can analyze it before making changes and to also save the "before" data before we update in case we ever have to roll back the data. The part that is giving me an issue is the "getValue" in the code that reads from the text control. SimplySpy identified the control properly and shows the information in it correctly. But, when I write the data to the console it will show me something random.  For this piece of code, it actually shows me code from the script. Which I don't even understand how it's coming up with that. I can read the contents of the edit controls fine, it's just the text controls that are giving me a problem. I need to be able to read them to make sure I'm on the right product before attempting to make any changes.

Any help and/or suggestions from anyone would be greatly appreciated as I can't seem to get past this issue.

 

$oChrome = _UIA_getFirstObjectOfElement($UIA_oDesktop, "class:=Chrome_WidgetWin_1", $treescope_children)
   $oDocument = _UIA_getFirstObjectOfElement($oChrome, "controltype:=" & $UIA_DocumentControlTypeId, $treescope_subtree)

   Local $oRVTest = _UIA_getObjectByFindAll($oDocument, "controltype:=" & $UIA_TextControlTypeId & ";Index:=2", $treescope_subtree)
   Local $sRVTest = _UIA_Action($oRVTest, "getValue")
   ConsoleWrite($sRVTest & @CRLF)

;   $oPartID = _UIA_getObjectByFindAll($oDocument, "controltype:=" & $UIA_TextControlTypeId & ";Index:=3", $treescope_subtree)
;   $sPartID = _UIA_Action("$oPartID", "getValue")
;   ConsoleWrite($sPartID & @CRLF)

   Local $oDescription = _UIA_getObjectByFindAll($oDocument, "controltype:=" & $UIA_EditControlTypeId & ";Index:=1", $treescope_subtree)
   Local $sDescription = _UIA_Action($oDescription, "getValue")
   ConsoleWrite($sDescription & @CRLF)

   Local $oBin = _UIA_getObjectByFindAll($oDocument, "controltype:=" & $UIA_EditControlTypeId & ";Index:=2", $treescope_subtree)
   Local $sBin = _UIA_Action($oBin, "getValue")
   ConsoleWrite($sBin & @CRLF)

 

Share this post


Link to post
Share on other sites

Try 

chrome://accessibility

And check the tree of your page as thats basically all you can see from chrome.

Its hard to help when page is not reachable so post morecdetails of output simplespy gives.

 

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

  • Similar Content

    • By bobmcrae
      I am experimenting with UIAWrappers.au3 from junkew to complete an application which presents absolutely no control information using AutoIT Window Info.  While I am able to complete the form successfully, I am not happy with the speed.  As a benchmark, the simple Send method occurs in far less than 1-second, but the UIAutomation approach takes 3-seconds.  I am wondering whether performance gains may be achieved by specifying the controls more precisely; but I am unsure how to do that.  I was able to speed things up a bit by setting $UIA_DefaultWaitTime=0.  The controls of interest are 5-levels deep, as show in the simplespy output below.  It seems I do get faster response by specifying the target/top-level window, as show in the code below.  Any ideas?
      #include "UIAWrappers.au3" _UIA_setVar("Global.Debug", False) _UIA_setVar("Global.Debug.File", False) _UIA_setVar("Global.Highlight", False) _UIA_setVar("DPN","Title:=NC-stat DPNCheck Communicator;controltype:=UIA_WindowControlTypeId;class:=Window") _UIA_action('DPN','setFocus') _UIA_setVar("DPN.firstName","AutomationId:=txtFirstName") _UIA_setVar("DPN.lastName", "AutomationId:=txtLastName") _UIA_Action('DPN.lastName','setvalue','last name') _UIA_setVar("DPN.ID", "AutomationId:=txtSubjectId") _UIA_setVar("DPN.DOB", "AutomationId:=PART_TextBox") _UIA_setVar("DPN.Ft", "AutomationId:=txtSubjectHeight") _UIA_setVar("DPN.In", "AutomationId:=txtSubjectHeight2") _UIA_Action('DPN.firstName','setvalue','first name') _UIA_Action('DPN.ID','setvalue','ID012345') _UIA_Action('DPN.DOB','setvalue','1/31/1932') _UIA_Action('DPN.Ft','setvalue','6') _UIA_Action('DPN.In','setvalue','1') SimpleSpy output:
      ;~ *** Standard code *** #include "UIAWrappers.au3" AutoItSetOption("MustDeclareVars", 1) Local $oP4=_UIA_getObjectByFindAll($UIA_oDesktop, "Title:=NC-stat DPNCheck Communicator;controltype:=UIA_WindowControlTypeId;class:=Window", $treescope_children) _UIA_Action($oP4,"setfocus") Local $oP3=_UIA_getObjectByFindAll($oP4, "Title:=;controltype:=UIA_PaneControlTypeId;class:=Frame", $treescope_children) Local $oP2=_UIA_getObjectByFindAll($oP3, "Title:=;controltype:=UIA_TabControlTypeId;class:=TabControl", $treescope_children) Local $oP1=_UIA_getObjectByFindAll($oP2, "Title:=Patient;controltype:=UIA_TabItemControlTypeId;class:=TabItem", $treescope_children) Local $oP0=_UIA_getObjectByFindAll($oP1, "Title:=;controltype:=UIA_PaneControlTypeId;class:=Frame", $treescope_children) ;~ First find the object in the parent before you can do something ;~$oUIElement=_UIA_getObjectByFindAll(".mainwindow", "title:=;ControlType:=UIA_EditControlTypeId", $treescope_subtree) Local $oUIElement=_UIA_getObjectByFindAll($oP0, "title:=;ControlType:=UIA_EditControlTypeId", $treescope_subtree) _UIA_action($oUIElement,"click")  
    • By jackchen
      OK,I've made my "Chrome_KeepLastTab.au3" work.This script adds some features to Chrome browser:
      1. Double click on a tab to close the tab.
      2. Keep last tab:This script monitors your mouse clicks and hotkeys,if you are about to close the last tab within Chrome(click close button on the last tab, middle click/double click on the last tab or press Ctrl + w or Ctrl + {F4}), a new tab will be open and then the old tab be closed.
      #include <WindowsConstants.au3> #include <WinAPI.au3> #include "CUIAutomation2.au3" #AutoIt3Wrapper_UseX64=Y ;Should be used for stuff like tagpoint having right struct etc. when running on a 64 bits os ConsoleWrite("@OSArch: " & @OSArch & ", @AutoItX64: " & @AutoItX64 & @CRLF) Global $DoubleClickTime = 500 Global $UIA_oUIAutomation ; The main library core CUI automation reference Global $hMouseEvent, $hMouseHook Global $aMouseEvent[2] Global $KeepLastTab = True ; settings from ini file If $KeepLastTab Then ;The main object with acces to the windows automation api 3.0 $UIA_oUIAutomation = ObjCreateInterface($sCLSID_CUIAutomation, $sIID_IUIAutomation, $dtagIUIAutomation) If IsObj($UIA_oUIAutomation) Then HotKeySet("^w", "Hotkey_Event") ; Ctrl + w to close tab HotKeySet("^{F4}", "Hotkey_Event") ; Ctrl + {F4} to close tab $DoubleClickTime = DllCall("user32.dll", "uint", "GetDoubleClickTime")[0] OnAutoItExitRegister("UnhookMouse") ; Register mouse events callback $hMouseEvent = DllCallbackRegister("Mouse_Event", "int", "int;ptr;ptr") $hMouseHook = _WinAPI_SetWindowsHookEx($WH_MOUSE_LL, DllCallbackGetPtr($hMouseEvent), _WinAPI_GetModuleHandle(0)) EndIf EndIf While 1 Sleep(100) WEnd ToolTip("") ; https://www.autoitscript.com/forum/topic/103362-monitoring-mouse-events/ Func Mouse_Event($nCode, $wParam, $lParam) Local $info, $mouseData, $time, $timeDiff If $nCode < 0 Then Return _WinAPI_CallNextHookEx($hMouseHook, $nCode, $wParam, $lParam) ; Continue processing EndIf $tPoint = _WinAPI_GetMousePos() $hWnd = _WinAPI_WindowFromPoint($tPoint) ; if mouse is on the widget window(class: Chrome_RenderWidgetHostHWND), ; use $hWnd = _WinAPI_GetParent($hWnd) to get the parent Chrome window If Not StringInStr(_WinAPI_GetClassName($hWnd), "Chrome_WidgetWin_") Then ; Chrome_WidgetWin_1: Chrome window ; Chrome_WidgetWin_2: Chrome menu ; ignore non Chrome window Return _WinAPI_CallNextHookEx($hMouseHook, $nCode, $wParam, $lParam) EndIf ToolTip($hWnd & " - " & _WinAPI_GetClassName($hWnd)) ;$tagPOINT = "struct;long X;long Y;endstruct" Local Const $MSLLHOOKSTRUCT = $tagPOINT & ";dword mouseData;dword flags;dword time;ulong_ptr dwExtraInfo" $info = DllStructCreate($MSLLHOOKSTRUCT, $lParam) $mouseData = DllStructGetData($info, 3) $time = DllStructGetData($info, 5) $timeDiff = $time - $aMouseEvent[1] Local $block Switch $wParam Case $WM_LBUTTONUP $aMouseEvent[1] = $time If $aMouseEvent[0] = "LClick" And ($timeDiff) < $DoubleClickTime Then $aMouseEvent[0] = "LDClick" Else $aMouseEvent[0] = "LClick" EndIf $block = KeepLastTab($hWnd, $aMouseEvent[0]) Case $WM_MBUTTONUP $aMouseEvent[1] = $time If $aMouseEvent[0] = "MClick" And ($timeDiff) < $DoubleClickTime Then $aMouseEvent[0] = "MDClick" Else $aMouseEvent[0] = "MClick" $block = KeepLastTab($hWnd, $aMouseEvent[0]) EndIf EndSwitch If Not $block Then _WinAPI_CallNextHookEx($hMouseHook, $nCode, $wParam, $lParam) ; Continue processing EndIf EndFunc ;==>Mouse_Event Func UnhookMouse() _WinAPI_UnhookWindowsHookEx($hMouseHook) $hMouseHook = 0 DllCallbackFree($hMouseEvent) $hMouseEvent = 0 EndFunc ;==>UnhookMouse Func Hotkey_Event() Local $block Local $hWnd = WinGetHandle(WinGetTitle("[ACTIVE]")) If StringInStr(_WinAPI_GetClassName($hWnd), "Chrome_WidgetWin_1") Then ; Chrome_WidgetWin_1, Chrome window $block = KeepLastTab($hWnd, "Hotkey") EndIf If Not $block Then HotKeySet("^w") Send(@HotKeyPressed) HotKeySet("^w", "Hotkey_Event") EndIf EndFunc Func KeepLastTab($hWnd, $action = "LClick") ; Possible $action value: LClick, LDClick, MClick, Hotkey ConsoleWrite(@CRLF & $action & " on a Chrome window: " & $hWnd & @CRLF) Local $aMousePos = MouseGetPos() Local $pChrome, $oChrome $UIA_oUIAutomation.ElementFromHandle($hWnd, $pChrome) ; Window $oChrome = ObjCreateInterface($pChrome, $sIID_IUIAutomationElement, $dtagIUIAutomationElement) If Not IsObj($oChrome) Then ConsoleWrite("Failed to get Chrome object from hWnd." & @CRLF) Return EndIf ;$UIA_ControlTypePropertyId = 30003 $oChromeTabs = UIA_getFirstElement($oChrome, $UIA_ControlTypePropertyId, $UIA_TabControlTypeId, $treescope_subtree) If Not IsObj($oChromeTabs) Then ConsoleWrite("Failed to get Chrome tab bar object." & @CRLF) Return EndIf Local $t $oChromeTabs.GetCurrentPropertyValue($UIA_BoundingRectanglePropertyId, $t) If UBound($t) < 4 Then Return If $action <> "Hotkey" And ($aMousePos[0] < $t[0] Or $aMousePos[0] > $t[2]+$t[0] Or $aMousePos[1] < $t[1] Or $aMousePos[1] > $t[3]+$t[1]) Then ; Mouse not on tabs bar ConsoleWrite("Mouse is not on the tab bar. Ignore and return..." & @CRLF) Return EndIf Local $pTrueCondition, $pElements, $iLength, $oAutomationElementArray $UIA_oUIAutomation.CreateTrueCondition($pTrueCondition) $oCondition = ObjCreateInterface($pTrueCondition, $sIID_IUIAutomationCondition, $dtagIUIAutomationCondition) If Not IsObj($oCondition) Then Return $oChromeTabs.FindAll($treescope_children, $oCondition, $pElements) $oAutomationElementArray = ObjCreateInterface($pElements, $sIID_IUIAutomationElementArray, $dtagIUIAutomationElementArray) If Not IsObj($oAutomationElementArray) Then ConsoleWrite("Failed to find all Chrome tabs. " & @CRLF) Return EndIf $oAutomationElementArray.Length($iLength) Local $UIA_pUIElement, $oTab2 Local $iTabs = $iLength - 1 If $iTabs > 1 Then ; more than one tab If $action = "LDClick" Then ConsoleWrite("There are " & $iTabs & " tabs within Chrome window. " & @CRLF) For $i = 1 To $iTabs $oAutomationElementArray.GetElement($i, $UIA_pUIElement) $oTab2 = ObjCreateInterface($UIA_pUIElement, $sIID_IUIAutomationElement, $dtagIUIAutomationElement) If Not IsObj($oTab2) Then ContinueLoop $oTab2.GetCurrentPropertyValue($UIA_BoundingRectanglePropertyId, $t) If UBound($t) < 4 Then ContinueLoop If $aMousePos[0] >= $t[0] And $aMousePos[0] <= $t[2]+$t[0] And $aMousePos[1] >= $t[1] And $aMousePos[1] <= $t[3]+$t[1] Then ConsoleWrite("You double clicked on one of " & $iTabs & " tabs. Close the tab and return..." & @CRLF) HotKeySet("^w") Send("^w") HotKeySet("^w", "Hotkey_Event") Return True EndIf Next EndIf Return EndIf ConsoleWrite("There is ONLY one tab within Chrome window. " & @CRLF) $oAutomationElementArray.GetElement(1, $UIA_pUIElement) $oTab = ObjCreateInterface($UIA_pUIElement, $sIID_IUIAutomationElement, $dtagIUIAutomationElement) If Not IsObj($oTab) Then ConsoleWrite("Failed to get the last tab object." & @CRLF) Return EndIf Local $rtTab $oTab.GetCurrentPropertyValue($UIA_BoundingRectanglePropertyId, $rtTab) If UBound($rtTab) < 4 Then Return If $action <> "Hotkey" And ($aMousePos[0] < $rtTab[0] Or $aMousePos[0] > $rtTab[2]+$rtTab[0] Or $aMousePos[1] < $rtTab[1] Or $aMousePos[1] > $rtTab[3]+$rtTab[1]) Then ; Mouse not on the last tab ConsoleWrite("Mouse is not on the last tab. Ignore and return..." & @CRLF) Return EndIf If $action = "LClick" Then $oTabClose = UIA_getFirstElement($oTab, $UIA_ControlTypePropertyId, $UIA_ButtonControlTypeId, $treescope_subtree) If Not IsObj($oTabClose) Then ConsoleWrite("Failed to get the last tab close object." & @CRLF) Return EndIf $oTabClose.GetCurrentPropertyValue($UIA_BoundingRectanglePropertyId, $t) If UBound($t) < 4 Then Return If $aMousePos[0] < $t[0] Or $aMousePos[0] > $t[2]+$t[0] Or $aMousePos[1] < $t[1] Or $aMousePos[1] > $t[3]+$t[1] Then ; Mouse not on the tab close button Return EndIf EndIf ; open a new tab within chrome ConsoleWrite("The last tab is about to be closed, so we have to open a new tab to prevent Chrome window from closing." & @CRLF) Send("^t") ConsoleWrite("A new tab created!" & @CRLF) Sleep(100) ConsoleWrite("Close the old tab and return..." & @CRLF) ;~ Local $pPattern ;~ $oTabClose.GetCurrentPattern($UIA_InvokePatternId, $pPattern) ;~ $oPattern = ObjCreateInterface($pPattern, $sIID_IUIAutomationInvokePattern, $dtagIUIAutomationInvokePattern) ;~ If IsObj($oPattern) Then ;~ ConsoleWrite("Invoke to close the tab..." & @CRLF) ;~ $oTabClose.SetFocus() ;~ $oPattern.Invoke() ;~ EndIf _WinAPI_UnhookWindowsHookEx($hMouseHook) $aMousePos = MouseGetPos() If $aMousePos[0] >= $rtTab[0] And $aMousePos[0] <= $rtTab[2]+$rtTab[0] And $aMousePos[1] >= $rtTab[1] And $aMousePos[1] <= $rtTab[3]+$rtTab[1] Then MouseClick("middle", $aMousePos[0], $aMousePos[1], 1, 0) Else MouseClick("middle", $rtTab[0]+$rtTab[2]/2, $rtTab[1]+$rtTab[3]/2, 1, 0) ; close the tab MouseMove($aMousePos[0], $aMousePos[1], 0) ; move mouse back to previous position EndIf ;~ _WinAPI_Mouse_Event($MOUSEEVENTF_MIDDLEDOWN, $rtTab[0]+$rtTab[2]/2, $rtTab[1]+$rtTab[3]/2) ;~ Sleep(100) ;~ _WinAPI_Mouse_Event($MOUSEEVENTF_MIDDLEUP, $rtTab[0]+$rtTab[2]/2, $rtTab[1]+$rtTab[3]/2) $hMouseHook = _WinAPI_SetWindowsHookEx($WH_MOUSE_LL, DllCallbackGetPtr($hMouseEvent), _WinAPI_GetModuleHandle(0)) Return True ; to block mouse click/hot key EndFunc Func UIA_getFirstElement($obj, $propertyID, $tval, $treeScope) Local $pCondition, $oCondition $UIA_oUIAutomation.CreatePropertyCondition($propertyID, $tval, $pCondition) $oCondition = ObjCreateInterface($pCondition, $sIID_IUIAutomationPropertyCondition, $dtagIUIAutomationPropertyCondition) Local $UIA_oUIElement, $UIA_pUIElement $t = $obj.Findfirst($treeScope, $oCondition, $UIA_pUIElement) $UIA_oUIElement = ObjCreateInterface($UIA_pUIElement, $sIID_IUIAutomationElement, $dtagIUIAutomationElement) If IsObj($UIA_oUIElement) Then Return $UIA_oUIElement Return SetError(1, 0, "") EndFunc ;==>UIA_getFirstElement My question is related to #AutoIt3Wrapper_UseX64 when run this script on 64-bit Win 7.
      No mater I set #AutoIt3Wrapper_UseX64=Y or #AutoIt3Wrapper_UseX64=N, this script works very well on hotkey event, while mouse clicks sometimes works if #AutoIt3Wrapper_UseX64=N and sometimes works on Y. Can some one test this and finger out what's wrong?
      Info from SciTe if #AutoIt3Wrapper_UseX64=Y :
      @OSArch: X64, @AutoItX64: 1 Hotkey on a Chrome window: 0x0000000000140330 There is ONLY one tab within Chrome window. The last tab is about to be closed, so we have to open a new tab to prevent Chrome window from closing. A new tab created! Close the old tab and return... LClick on a Chrome window: 0x0000000000140330 There is ONLY one tab within Chrome window. The last tab is about to be closed, so we have to open a new tab to prevent Chrome window from closing. A new tab created! Close the old tab and return... Info if #AutoIt3Wrapper_UseX64=N or comment out this line:
      @OSArch: X64, @AutoItX64: 0 Hotkey on a Chrome window: 0x00140330 There is ONLY one tab within Chrome window. The last tab is about to be closed, so we have to open a new tab to prevent Chrome window from closing. A new tab created! Close the old tab and return... LClick on a Chrome window: 0x00140330 Failed to get Chrome tab bar object. Hotkey events and mouse click events share the same function KeepLastTab($hWnd, $action = "LClick"),Why this function triggered by hotkey works on both 32-bit and 64-bit while that triggered by mouse events failed on 32-bit autoit?
×
×
  • Create New...