Trying to find the name of a child via AccessibleChildren Lib "oleacc"

casperharkin

New Member
Joined
Mar 1, 2023
Messages
1
Office Version
  1. 2016
Platform
  1. Windows
Hi all, first time poster here. Hoping someone will be able to help me.

I am looking to get the zoom percentage figure from the status bar of a notepad window. The text between “Ln 1, Col 1” and “Windows (CRLF)” on the bottom right of the window.

Here is my attempt at doing what I want in VBA;


VBA Code:
    Option Explicit
    
        Declare PtrSafe Function AccessibleObjectFromWindow Lib "OLEACC.DLL" (ByVal hwnd As LongPtr, ByVal dwId As Long, ByVal riid As LongPtr, ppvObject As Any) As Long
        Declare PtrSafe Function AccessibleChildren Lib "oleacc" (ByVal paccContainer As IAccessible, ByVal iChildStart As Long, ByVal cChildren As Long, ByRef rgvarChildren As Any, ByRef pcObtained As Long) As Long
        Declare PtrSafe Function IIDFromString Lib "ole32.dll" (ByVal lpsz As LongPtr, ByVal lpiid As LongPtr) As LongPtr
        Declare PtrSafe Function FindWindowEx Lib "User32" Alias "FindWindowExA" (ByVal hWnd1 As LongPtr, ByVal hWnd2 As LongPtr, ByVal lpsz1 As String, ByVal lpsz2 As String) As LongPtr
        Declare PtrSafe Function FindWindow Lib "User32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
    
        Const S_OK = &H0
        Const OBJID_SELF = &H0&
        Const CHILDID_SELF = &H0&
        Const ID_ACCESSIBLE As String = "{00020400-0000-0000-C000-000000000046}"
    
    
    
    Sub Test()
    ' This will only work with notepad open.
    
        Dim tGUID(0 To 3) As Long
        Dim oIAc As IAccessible
        Dim vAcc As Variant, vAccChild As Variant
        Dim i As Long
            
        Dim hWndParentNotepad As Long
        Dim hWndstatusbar As Long
            
        'Getting the hWnds of the windows / controls
        hWndParentNotepad = FindWindow("Notepad", vbNullString)
        hWndstatusbar = FindWindowEx(hWndParentNotepad, ByVal 0&, "msctls_statusbar32", vbNullString)

        If IIDFromString(StrPtr(ID_ACCESSIBLE), VarPtr(tGUID(0))) = S_OK Then
            If AccessibleObjectFromWindow(hWndstatusbar, OBJID_SELF, VarPtr(tGUID(0)), oIAc) = S_OK Then
                
                Set vAcc = oIAc
                AccessibleChildren vAcc, 3, 1, vAcc, 1
                
                ' I can see the Control I care about and the number of children.
                Debug.Print "Control: " & vAcc.accName(CHILDID_SELF) & " has " & vAcc.accChildCount & " Children. "
                
                ' Control/window "Status Bar" should have the below five children.
                    ' 1st Child has the Name " "
                    ' 2nd Child has the Name " Ln 1, Col 1"
                    ' 3rd Child has the Name " 100%"
                    ' 4th Child has the Name " Windows (CRLF)"
                    ' 5th Child has the Name " UTF-8"
                
                ' Now I want the Name of the third child of the Status Bar; The Zoom Percentage
                ' but I cant seem to work out how to access it, can anyone help me out?
                    AccessibleChildren vAcc, 3, 1, vAccChild, 1
                    Debug.Print vAccChild.accName(CHILDID_SELF)

            End If
        End If
    End Sub
 

Attachments

  • Example of What I am Looking to Get.png
    Example of What I am Looking to Get.png
    14.6 KB · Views: 38

Excel Facts

What do {} around a formula in the formula bar mean?
{Formula} means the formula was entered using Ctrl+Shift+Enter signifying an old-style array formula.
AccessibleChildren vAcc, 3, 1, vAccChild, 1

The required child argument is zero-based, so for the 3rd child try changing the 3 above to 2.


If that doesn't work try this code which uses UIAutomation. You must set a reference to UIAutomationClient.

VBA Code:
Option Explicit

Private Declare PtrSafe Function FindWindow Lib "User32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As LongPtr

Public Sub Notepad_Zoom()

    Dim NotepadHwnd As LongPtr
    Dim zoom As String
          
    NotepadHwnd = FindWindow("Notepad", vbNullString)
  
    If NotepadHwnd <> 0 Then
        zoom = UIAuto_Get_Notepad_Zoom(NotepadHwnd)
        Debug.Print zoom
    End If
    
End Sub


Private Function UIAuto_Get_Notepad_Zoom(NotepadHwnd As LongPtr) As String
   
    Dim UIAuto As IUIAutomation
    Dim NotepadMain As IUIAutomationElement
    Dim ControlTypeCond As IUIAutomationCondition
    Dim StatusBar As IUIAutomationElement
    Dim StatusBarChildren As IUIAutomationElementArray
    
    'Create UIAutomation object
    
    Set UIAuto = New CUIAutomation
    
    'Get the main Notepad control
    
    Set NotepadMain = UIAuto.ElementFromHandle(ByVal NotepadHwnd)
    
    'Get the status bar control
    
    Set ControlTypeCond = UIAuto.CreatePropertyCondition(UIA_ControlTypePropertyId, UIA_StatusBarControlTypeId)
    Set StatusBar = NotepadMain.FindFirst(TreeScope_Descendants, ControlTypeCond)
    
    'Get all text controls within the Status Bar

    Set ControlTypeCond = UIAuto.CreatePropertyCondition(UIA_ControlTypePropertyId, UIA_TextControlTypeId)
    Set StatusBarChildren = StatusBar.FindAll(TreeScope_Subtree, ControlTypeCond)
    
    'Return the 3rd text control to caller
    
    UIAuto_Get_Notepad_Zoom = StatusBarChildren.GetElement(2).CurrentName
    
End Function
 
Upvote 0
Solution
Don't pass CHILDID_SELF to the AccName Method... Pass the child position( 3&) as follows:
VBA Code:
Sub Test()
' This will only work with notepad open.

    Dim tGUID(0 To 3) As Long
    Dim oIAc As IAccessible
    Dim vAcc As Variant, vAccChild As Variant
    Dim i As Long
        
    Dim hWndParentNotepad As LongPtr
    Dim hWndstatusbar As LongPtr
        
    'Getting the hWnds of the windows / controls
    hWndParentNotepad = FindWindow("Notepad", vbNullString)
    hWndstatusbar = FindWindowEx(hWndParentNotepad, ByVal 0&, "msctls_statusbar32", vbNullString)

    If IIDFromString(StrPtr(ID_ACCESSIBLE), VarPtr(tGUID(0))) = S_OK Then
        If AccessibleObjectFromWindow(hWndstatusbar, OBJID_SELF, VarPtr(tGUID(0)), oIAc) = S_OK Then
             AccessibleChildren oIAc, 3, 1, vAcc, 1
              MsgBox "Notepad current zoom is: " & vAcc.accName(3&)
        End If
    End If    
End Sub

If you use OBJID_CLIENT when calling AccessibleObjectFromWindow isntead of using OBJID_SELF then you can get away without even using the confusing AccessibleChildren api as follows:
VBA Code:
Sub Test2()
' This will only work with notepad open.

    Dim tGUID(0 To 3) As Long
    Dim oIAc As IAccessible
    Dim vAcc As Variant, vAccChild As Variant
    Dim i As Long
        
    Dim hWndParentNotepad As LongPtr
    Dim hWndstatusbar As LongPtr
        
    'Getting the hWnds of the windows / controls
    hWndParentNotepad = FindWindow("Notepad", vbNullString)
    hWndstatusbar = FindWindowEx(hWndParentNotepad, ByVal 0&, "msctls_statusbar32", vbNullString)

    If IIDFromString(StrPtr(ID_ACCESSIBLE), VarPtr(tGUID(0))) = S_OK Then
        Const OBJID_CLIENT = &HFFFFFFFC
        If AccessibleObjectFromWindow(hWndstatusbar, OBJID_CLIENT, VarPtr(tGUID(0)), oIAc) = S_OK Then
           MsgBox "Notepad current zoom is: " & oIAc.accName(3&)
        End If
    End If
    
End Sub
 
Upvote 1

Forum statistics

Threads
1,223,929
Messages
6,175,461
Members
452,645
Latest member
Tante

We've detected that you are using an adblocker.

We have a great community of people providing Excel help here, but the hosting costs are enormous. You can help keep this site running by allowing ads on MrExcel.com.
Allow Ads at MrExcel

Which adblocker are you using?

Disable AdBlock

Follow these easy steps to disable AdBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the icon in the browser’s toolbar.
2)Click on the "Pause on this site" option.
Go back

Disable AdBlock Plus

Follow these easy steps to disable AdBlock Plus

1)Click on the icon in the browser’s toolbar.
2)Click on the toggle to disable it for "mrexcel.com".
Go back

Disable uBlock Origin

Follow these easy steps to disable uBlock Origin

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back

Disable uBlock

Follow these easy steps to disable uBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back
Back
Top