上篇写到了获取IE8浏览器URL的一般方法,那这篇就写下chrome的URL怎么获取。事实上,早期的chrome版本可以通过跟IE8差不多方式获取到URL信息。但是,现在chrome的控件都是DirectUI画出来的,所有就没有一般意义上hwnd可以取。网上搜索了下,大多数都倾向于使用MSAA(Microsoft Active Accessibility)这种途径来实现。感兴趣的同学可以搜索下MSAA,这是一个很有用的技术(因为不懂,我也就不多说了)。
基于MSAA思想,windows下的UI程序都可以提供一种可供遍历访问的接口。而界面上各个控件都处于类似于树的逻辑结构中,这使得第三方自动化控制成为了可能。而MSAA是以COM形式存在,使用时只需要在“引用”中添加即可,非常方便。
可能初次接触MSAA的同学还不能很好理解,关于UI结构的说明。但仔细思考下,本文这样的遍历和上篇根据hwnd的遍历其实原理上是差不多的。
实现代码如下:
1 '使用IAccessible接口之前,请先引用Accessibility(oleacc.dll) 2 '代码参考了很多网上代码,多数原作者无从考究,在此也就不列出了(请见谅) 3 '@Advanced Miscrosoft Visual Basci 6.0 4 'code by lichmama from cnblogs.com 5 Private Type UUID 6 Data1 As Long 7 Data2 As Integer 8 Data3 As Integer 9 Data4(7) As Byte 10 End Type 11 12 Private Declare Function AccessibleObjectFromWindow Lib "oleacc" (ByVal hwnd As Long, _ 13 ByVal dwObjectID As Long, _ 14 ByRef riid As UUID, _ 15 ByRef ppvObject As Any) As Long 16 17 Private Declare Function AccessibleChildren Lib "oleacc" (ByVal paccContainer As IAccessible, _ 18 ByVal iChildStart As Long, _ 19 ByVal cChildren As Long, _ 20 rgvarChildren As Variant, _ 21 pcObtained As Long) As Long 22 23 '其实这一部分对整个程序来说没什么作用,在此列出仅仅方便别人查阅 24 Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, _ 25 ByVal lpWindowName As String) As Long 26 27 Private Enum NVADIRConstants 28 NAVDIR_MIN = 0 29 NAVDIR_UP = 1 30 NAVDIR_DOWN = 2 31 NAVDIR_LEFT = 3 32 NAVDIR_RIGHT = 4 33 NAVDIR_NEXT = 5 34 NAVDIR_PREVIOUS = 6 35 NAVIDR_FIRSTCHILD = 7 36 NAVDIR_LASTCHILD = 8 37 NAVDIR_MAX = 9 38 End Enum 39 40 'IAccessible Object Types 41 Private Const CHILDID_SELF As Long = 0& 42 Private Const ROLE_SYSTEM_TITLEBAR As Long = &H1& 43 Private Const ROLE_SYSTEM_MENUBAR As Long = &H2& 44 Private Const ROLE_SYSTEM_SCROLLBAR As Long = &H3& 45 Private Const ROLE_SYSTEM_GRIP As Long = &H4& 46 Private Const ROLE_SYSTEM_SOUND As Long = &H5& 47 Private Const ROLE_SYSTEM_CURSOR As Long = &H6& 48 Private Const ROLE_SYSTEM_CARET As Long = &H7& 49 Private Const ROLE_SYSTEM_ALERT As Long = &H8& 50 Private Const ROLE_SYSTEM_WINDOW As Long = &H9& 51 Private Const ROLE_SYSTEM_CLIENT As Long = &HA& 52 Private Const ROLE_SYSTEM_MENUPOPUP As Long = &HB& 53 Private Const ROLE_SYSTEM_MENUITEM As Long = &HC& 54 Private Const ROLE_SYSTEM_TOOLTIP As Long = &HD& 55 Private Const ROLE_SYSTEM_APPLICATION As Long = &HE& 56 Private Const ROLE_SYSTEM_DOCUMENT As Long = &HF& 57 Private Const ROLE_SYSTEM_PANE As Long = &H10& 58 Private Const ROLE_SYSTEM_CHART As Long = &H11& 59 Private Const ROLE_SYSTEM_DIALOG As Long = &H12& 60 Private Const ROLE_SYSTEM_BORDER As Long = &H13& 61 Private Const ROLE_SYSTEM_GROUPING As Long = &H14& 62 Private Const ROLE_SYSTEM_SEPARATOR As Long = &H15& 63 Private Const ROLE_SYSTEM_TOOLBAR As Long = &H16& 64 Private Const ROLE_SYSTEM_STATUSBAR As Long = &H17& 65 Private Const ROLE_SYSTEM_TABLE As Long = &H18& 66 Private Const ROLE_SYSTEM_COLUMNHEADER As Long = &H19& 67 Private Const ROLE_SYSTEM_ROWHEADER As Long = &H1A& 68 Private Const ROLE_SYSTEM_COLUMN As Long = &H1B& 69 Private Const ROLE_SYSTEM_ROW As Long = &H1C& 70 Private Const ROLE_SYSTEM_CELL As Long = &H1D& 71 Private Const ROLE_SYSTEM_LINK As Long = &H1E& 72 Private Const ROLE_SYSTEM_HELPBALLOON As Long = &H1F& 73 Private Const ROLE_SYSTEM_CHARACTER As Long = &H20& 74 Private Const ROLE_SYSTEM_LIST As Long = &H21& 75 Private Const ROLE_SYSTEM_LISTITEM As Long = &H22& 76 Private Const ROLE_SYSTEM_OUTLINE As Long = &H23& 77 Private Const ROLE_SYSTEM_OUTLINEITEM As Long = &H24& 78 Private Const ROLE_SYSTEM_PAGETAB As Long = &H25& 79 Private Const ROLE_SYSTEM_PROPERTYPAGE As Long = &H26& 80 Private Const ROLE_SYSTEM_INDICATOR As Long = &H27& 81 Private Const ROLE_SYSTEM_GRAPHIC As Long = &H28& 82 Private Const ROLE_SYSTEM_STATICTEXT As Long = &H29& 83 Private Const ROLE_SYSTEM_TEXT As Long = &H2A& 84 Private Const ROLE_SYSTEM_PUSHBUTTON As Long = &H2B& 85 Private Const ROLE_SYSTEM_CHECKBUTTON As Long = &H2C& 86 Private Const ROLE_SYSTEM_RADIOBUTTON As Long = &H2D& 87 Private Const ROLE_SYSTEM_COMBOBOX As Long = &H2E& 88 Private Const ROLE_SYSTEM_DROPLIST As Long = &H2F& 89 Private Const ROLE_SYSTEM_PROGRESSBAR As Long = &H30& 90 Private Const ROLE_SYSTEM_DIAL As Long = &H31& 91 Private Const ROLE_SYSTEM_HOTKEYFIELD As Long = &H32& 92 Private Const ROLE_SYSTEM_SLIDER As Long = &H33& 93 Private Const ROLE_SYSTEM_SPINBUTTON As Long = &H34& 94 Private Const ROLE_SYSTEM_DIAGRAM As Long = &H35& 95 Private Const ROLE_SYSTEM_ANIMATION As Long = &H36& 96 Private Const ROLE_SYSTEM_EQUATION As Long = &H37& 97 Private Const ROLE_SYSTEM_BUTTONDROPDOWN As Long = &H38& 98 Private Const ROLE_SYSTEM_BUTTONMENU As Long = &H39& 99 Private Const ROLE_SYSTEM_BUTTONDROPDOWNGRID As Long = &H3A& 100 Private Const ROLE_SYSTEM_WHITESPACE As Long = &H3B& 101 Private Const ROLE_SYSTEM_PAGETABLIST As Long = &H3C& 102 Private Const ROLE_SYSTEM_CLOCK As Long = &H3D& 103 Private IID_IAccessible As UUID 104 Private Declare Function GetTickCount Lib "kernel32" () As Long 105 106 Private Sub Form_Initialize() 107 With IID_IAccessible 108 .Data1 = &H618736E0 109 .Data2 = &H3C3D 110 .Data3 = &H11CF 111 .Data4(0) = &H81 112 .Data4(1) = &HC 113 .Data4(2) = &H0 114 .Data4(3) = &HAA 115 .Data4(4) = &H0 116 .Data4(5) = &H38 117 .Data4(6) = &H9B 118 .Data4(7) = &H71 119 End With 120 End Sub 121 122 'using like: GetChromeUrl(FindWindow("Chrome_WidgetWin_1", vbNullString)) 123 Private Function GetChromeUrl(ByVal hwnd As Long) As String 124 Dim objAcc As IAccessible 125 126 Call AccessibleObjectFromWindow(hwnd, 0&, IID_IAccessible, objAcc) 127 If objAcc Is Nothing Then 128 Debug.Print "access failed" 129 Exit Function 130 End If 131 132 GetChromeUrl = ViewAcc(objAcc) 133 End Function 134 135 Private Function ViewAcc(ByVal objAcc As IAccessible) As String 136 On Error Resume Next 137 If objAcc.accName(CHILDID_SELF) = "地址和搜索栏" Then 138 ViewAcc = "http://" & objAcc.accValue(CHILDID_SELF) 139 Exit Function 140 ElseIf objAcc.accChildCount = 0 Then 141 Exit Function 142 End If 143 144 Dim kids() As Variant 145 Dim kidscount As Long 146 Dim realcount As Long 147 148 kidscount = objAcc.accChildCount 149 ReDim kids(kidscount - 1) As Variant 150 Call AccessibleChildren(objAcc, 0&, kidscount, kids(0), realcount) 151 For i = 0 To realcount - 1 152 If TypeName(kids(i)) = "IAccessible" Then 153 ViewAcc = ViewAcc(kids(i)) 154 If ViewAcc <> "" Then Exit For 155 End If 156 Next 157 End Function
运行下看看效果:
1 Private Sub Command1_Click() 2 For i = 1 To 10 3 o = GetTickCount() 4 Debug.Print GetChromeUrl(FindWindow("Chrome_WidgetWin_1", vbNullString)) 5 Debug.Print GetTickCount() - o & "ms" 6 Next 7 End Sub
看来这递归的效率有点低
http://www.cnblogs.com/lichmama/p/3824888.html 453ms http://www.cnblogs.com/lichmama/p/3824888.html 422ms http://www.cnblogs.com/lichmama/p/3824888.html 391ms http://www.cnblogs.com/lichmama/p/3824888.html 406ms http://www.cnblogs.com/lichmama/p/3824888.html 406ms http://www.cnblogs.com/lichmama/p/3824888.html 391ms http://www.cnblogs.com/lichmama/p/3824888.html 406ms http://www.cnblogs.com/lichmama/p/3824888.html 406ms http://www.cnblogs.com/lichmama/p/3824888.html 407ms http://www.cnblogs.com/lichmama/p/3824888.html 390ms