Jack George
New Member
- Joined
- Jul 8, 2023
- Messages
- 14
- Office Version
- 2019
- Platform
- Windows
I know we can get IAccessible of an object by first declaring a variable of type IAccessible and set it to the object we want the interface from, but that requires a reference to a TypeLib in VBE menu -> Tools ->References.
Wondering if we can do that without reference and with API only. Ideally we don't want to have to reference TypeLib for IUnknown either.
The following is what I've got so far (didn't get to sleep last night just for this):
Code in UserForm module with a textbox named "TextBox1" on it
WARNING: The above code will crash Excel for sure...DO NOT run it directly.
Don't know what have I done wrong, or is there any better way to get the IAccessible without "type" other than "Object".
Any help would be appreciated.
Regards
Wondering if we can do that without reference and with API only. Ideally we don't want to have to reference TypeLib for IUnknown either.
The following is what I've got so far (didn't get to sleep last night just for this):
Code in UserForm module with a textbox named "TextBox1" on it
VBA Code:
Option Explicit
#If Win64 Then
Private Const PTR_SIZE As LongLong = 8
#Else
Private Const PTR_SIZE As Long = 4
Private Enum LongPtr
[_]
End Enum
#End If
Private Type GUID
Data1 As Long
Data2 As Integer
Data3 As Integer
Data4(0 To 7) As Byte
End Type
Private Declare PtrSafe Function DispCallFunc Lib "oleAut32.dll" ( _
ByVal pvInstance As LongPtr, _
ByVal offsetinVft As LongPtr, _
ByVal CallConv As Long, _
ByVal retTYP As Integer, _
ByVal paCNT As Long, _
ByVal paTypes As LongPtr, _
ByVal paValues As LongPtr, _
ByVal retVAR As LongPtr _
) As Long
Private Declare PtrSafe Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" ( _
Destination As Any, _
Source As Any, _
ByVal Length As LongPtr _
)
Private Sub UserForm_Initialize()
Dim DispCallFuncResult As Long
Dim result As Long
'IID_IAccessible: {618736E0-3C3D-11CF-810C-00AA00389B71}
'DEFINE_GUID(IID_IAccessible, 0x618736e0, 0x3c3d, 0x11cf, 0x81, 0x0c, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71);
Dim acc_guid As GUID
With acc_guid
.Data1 = &H618736E0
.Data2 = &H3C3D
.Data3 = &H11CF
.Data4(0) = &H81
.Data4(1) = &HC
.Data4(2) = &H0
.Data4(3) = &HAA
.Data4(4) = &H0
.Data4(5) = &H38
.Data4(6) = &H9B
.Data4(7) = &H71
End With
Dim pacc As LongPtr
Dim varTypes(0 To 1) As Integer
varTypes(0) = 29 ' VT_USERDEFINED
varTypes(1) = VarType(pacc)
Dim varPointers(0 To 1) As LongPtr
varPointers(0) = VarPtr(acc_guid.Data1)
varPointers(1) = VarPtr(pacc)
' Get IAccessible of TextBox1 with call to IUnknown::QueryInterface(REFIID,void**)
DispCallFuncResult = DispCallFunc(ObjPtr(TextBox1), 0, 4, 3, 2, VarPtr(varTypes(0)), VarPtr(varPointers(0)), VarPtr(result))
Debug.Print result, DispCallFuncResult
Dim acc As Object
If pacc <> 0 Then
CopyMemory acc, ByVal pacc, PTR_SIZE
End If
Dim racc As IAccessible ' test only. our acc should equal to racc
Set racc = TextBox1
Debug.Print "accValue: " & racc.accValue(0&)
Debug.Assert acc Is racc
Debug.Print acc.accValue(0&)
End Sub
WARNING: The above code will crash Excel for sure...DO NOT run it directly.
Don't know what have I done wrong, or is there any better way to get the IAccessible without "type" other than "Object".
Any help would be appreciated.
Regards