Using the IAccessible interface to traverse the Directui window control problem?

Source: Internet
Author: User
Tags integer
Some time ago, to do a program, you need to complete a small function, that is, mouse monitoring, when the left click on a file selected, get the file name.
Toss for a long time, finally in WindowsXP under the perfect realization. The idea of implementation is:
1, under the mouse hook, get the left mouse button clickup event.
2, using Findpointwindow, get the mouse position window handle.
3, using SendMessage, to the window (SYSLISTVIEW32) to send information, to obtain the selected file number and file name.
The program runs normally under WindowsXP, and the file name can be removed correctly. The desktop (also SysListView32) on Windows7 and Server2008 also works fine.
However, Windows7 and Server2008 's File browser window Directui, unable to use SendMessage to obtain the appropriate information.

For Directui, use the IAccessible interface to traverse and get the selected file within the window of the specified handle.
The getcurrentfilename of the program, the entry is the handle to the specified window.
It is strange, however, that if the program gets a handle parameter from the form on the program itself, it can execute normally, and find the selected file (such as getting the handle value from a textbox). However, if you use the mouse hook and findpointwindow to get the window handle value, automatically call Getcurrentfilename, you cannot find the selected file.
By debugging, you can see that the accessibleobjectfromwindow sentence does not perform the same in both cases.
But I don't know where the reason is. Do not know if you are familiar with the IAccessible interface, to help analyze it.
The procedure is as follows:

#Region "Use IAccessible to read selected file names (common to SysListView32 and Directui two controls)"
"<summary>
"' reads the selected file name from the Windows System window, two controls need to be considered.
The first is the SYSLISTVIEW32,WINDOWSXP desktop and File browser window, Windows7, Server2008 's desktop is the kind of control
The SyslistView32 control itself has a role value of 33 "list", each file has a role value of 34 "list item", ObjectType is simple Element
The second type is the Directui,windows7, Server2008 file browser window is this kind of control
The Directui control itself is more complex, the File browser window is at a deeper level directui, the File browser window role value is 33 "list", each file role value is 34 "list item"
"But pay special attention to the objecttype of the file here is container.
Both controls can be accessed using the IAccessible Automation interface, and the layers are traversed in depth. However, it is important to note that IAccessible cannot enter ObjectType as a simple element layer.
That is, using IAccessible can not use Accessiblechildren into the SYSLISTVIEW32 sub-layer to take the traversal control, this will be an error. This may be due to the IAccessible interface working principle is not very clear.
'''
Note: Both controls can be researched and viewed using the tool accexplore.
'''
Private Declare Function accessibleobjectfromwindow Lib "Oleacc" (_
ByVal Hwnd as Int32, _
ByVal DwId as Int32, _
ByRef riid as Guid, _
<marshalas (Unmanagedtype.iunknown) > ByRef ppvobject as Object) as Int32
"<summary>
The Accessibleobjectfromwindow is used to obtain a window COM object with the specified handle as an HWND by invoking the Iacessible interface, placing the object in Ppvobject for user access
"' Accessibleobjectfromwindow if the correct COM object is obtained, the return value is 0. If the return value is not 0, an error occurred during the acquisition of the COM object.
Special note that Accessibleobjectfromwindow can only return the HWND handle to the top-level window of the window. This is most noticeable with Windows 7.
"</summary>
Public Declare Function accessiblechildren Lib "Oleacc" (_
ByVal Pacccontainer as IAccessible, _
ByVal Ichildstart as Integer, _
ByVal Cchildren as Integer, _
<[out] () > ByVal rgvarchildren () as Object, _
ByRef pcobtained as Integer) as UInt32
"<summary>
The "Accessiblechildren" is used to obtain the current object, Pacccontainer, as a child object, stored in the Cchildren set
"' Common variable strcurrentfilename is used to return the obtained file name
"</summary>
Public Strcurrentfilename as String
Public Sub Getcurrentfilename (ByVal hwndcurrent as Int32)
Try
Dim iacurrent as Accessibility.iaccessible = Nothing
Dim ID as Int32 = 0
Dim Iid_iacce as GUID = New guid ("618736e0-3c3d-11cf-810c-00aa00389b71")

' Call Accessibleobjectfromwindow, get a handle hwndcurrent the top-level window where the mouse is pointing to the current window, and put iacurrent for visitors to use
Dim Aaval as Int32 = Accessibleobjectfromwindow (hwndcurrent, ID, Iid_iacce, iacurrent)

' Iacurrent = DirectCast (iacurrent.accparent, accessibility.iaccessible) ' does not run this statement to get the number and name of the child correctly based on the handle.
Dim _childcount as Integer = Iacurrent.accchildcount
Dim _children As Object () = New Object (_childcount) {}
Dim _out as Integer
' Call the Accessiblechildren function to get the first-level subkey of the current top-level window (with particular attention not necessarily to the window that the hwndcurrent points to), put in _children
Accessiblechildren (iacurrent, 0, _childcount, _children, _out)
' Traverse the first level of the child
For each _child as accessibility.iaccessible in _children
' In the traversal process, will appear to take the empty items, if you take the empty items, the following program will be error, so you need to exclude the empty items
If _child IsNot Nothing Then

' First determine the role value of the child, 33 is the list, the file is 34 "list item", we need to find 33 "list"
Dim _accrole as String = _child.accrole (0) ' takes the role of the child currently traversed to
' If the control is SysListView32, then:
' 1, cannot use accessibility.iaccessible to enter SYSLISTVIEW32 's child
' 2, you can use _child.accname (i), _chile.accstate (i), traverse the subkey of the "33" list
' 3, you can use _child.accselection to return the selected subkey in the ' 33 ' list, but the return value is different from the expected value.
If _accrole = "" and Strlistviewclass = "SysListView32" Then
' After the list is found, determine if the current list has children selected.
PDMMainForm.LFind33.Text = "Find list 33, name" & _child.accname (0)
' If a subkey is selected, _child.accselection returns the selected value (the value must be greater than 0), otherwise it returns an empty
Dim _accselected as String = _child.accselection
If _accselected > 0 Then
Dim I as Integer
i = CInt (_accselected)
Strcurrentfilename = _child.accname (i)
PDMMainForm.Lfindfile.Text = "Find selected file, name" & Strcurrentfilename

Exit Sub
End If
End If
' Determines whether the current subkey _child has the next level of children (_child.accchildcount>0) and, if so, traverses
Dim _acccount as String = _child.accchildcount ' takes the number of subkeys currently traversed to the subkey
If _child.accchildcount > 0 Then
Enumchild (_child, _child.accchildcount)
End If
End If
Next
Catch
' If the selected file name is not properly obtained, the try statement is masked and debugged
End Try
End Sub
Sub Enumchild (ByVal objparent as accessibility.iaccessible, ByVal _childcount as Integer)
' Traverse all child controls below level Two and level two to find child controls with role 34
Dim _accchildren As Object () = New Object (_childcount) {}
Dim _out as Integer
Try
Accessiblechildren (objparent, 0, _childcount, _accchildren, _out)
Catch
End Try

' Traverse the nth level control
Dim istep as Integer = 0
Try
' During traversal, if _accchildren is a simple Element, the following statement will give an error and use a try statement to avoid
For each _child as accessibility.iaccessible in _accchildren
Istep = 1
' In the traversal process, will appear to take the empty items, if you take the empty items, the following program will be error, so you need to exclude the empty items
If _child IsNot Nothing Then
Istep = 2
' First determine the role value of the child, 33 is the list, the file is 34 "list item", we need to find 33 "list"
Dim _accrole as String = _child.accrole (0) ' takes the role of the child currently traversed to
Istep = 3
If _accrole = "Then"
PDMMainForm.LFind33.Text = "Find list item 34, name is" & _child.accname (0)
Dim _accstate as Object = _child.accstate (0)
Const System_mouseon as UInt32 = 2 ' object is selection mask, reference oleacc.h
Dim Imouseon as UInt32 = _accstate and System_mouseon
If Imouseon = 2 Then
Strcurrentfilename = _child.accname (0)
PDMMainForm.Lfindfile.Text = "Find selected file, name" & Strcurrentfilename
End If
With Pdmmainform.cb33list
. Items.Add (_child.accname (0) & "," & _accstate & "," & Imouseon)
End with
End If

Dim _acccount as String = _child.accchildcount ' takes the number of subkeys currently traversed to the subkey
If _acccount > 0 Then
Enumchild (_child, _acccount)
End If
End If

Next
Catch
End Try
End Sub

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.