こんにちは。
ExcelのユーザーフォームのIAccessibleオブジェクトを
再帰呼び出しに依って、列挙させようとしているのですが。
AccExplorer32.exeで順番を確認して
子IDを指定して、accChildメソッドを呼び出したところ、
エラーになります。
何かカン違いしてるのでしょうか?
Private Const NAVDIR_NEXT = 5&
Private Const NAVDIR_FIRSTCHILD = 7&
Private Const CHILDID_SELF = 0&
Private Sub UserForm_Initialize()
Dim acc As IAccessible
Set acc = Me
Set acc = acc.accParent
Set acc = acc.accChild(4&) ←ここで実行時エラー
End Sub
---
実行時エラー '5':
プロシージャの呼び出し、または引数が不正です。
---
> Set acc = acc.accChild(4&) ←ここで実行時エラー
この 4 という ChildID は、どのようにして得たものですか?
また、accChild 以外の方法(accNavigate メソッド や AccessibleChildren API)で辿ることはできますか?
=================================
Set acc = Me
Set acc = acc.accParent
count = acc.accChildCount
If count > 0 Then
ReDim list(count - 1) As Variant
Call AccessibleChildren(acc, 0&, ByVal count, list(0), count)
If IsObject( list(n) ) Then
Set acc = list( n ) 'このようにしてアクセスできるか?
End If
End If
魔界の仮面弁士さん、こんにちは。
ご回答ありがとうございます。
> この 4 という ChildID は、どのようにして得たものですか?
Accessible Explorerを見ながら1,2,,,と数えていたのですが
それがマズかったのかも。
> また、accChild 以外の方法(accNavigate メソッド や AccessibleChildren API)で辿ることはできますか?
accNavigateだと、
Private Const CHILDID_SELF = 0&
Private Const NAVDIR_FIRSTCHILD = 7&
Private Sub CommandButton1_Click()
Dim Vnt As Variant
Dim acc As IAccessible
Set acc = Me
Set acc = acc.accParent
Vnt = acc.accNavigate(NAVDIR_FIRSTCHILD, CHILDID_SELF) ←ここで実行時エラー
End Sub
---
実行時エラー '438':
オブジェクトは、このプロパティまたはメソッドをサポートしていません。
---
になります。
> Set acc = list( n ) 'このようにしてアクセスできるか?
ばっちりでした。
理由は分かりませんが、accNavigate・accChildではアクセス出来ない
オブジェクトがある様に感じます。
AccessibleChildrenがオールマイティなので構いませんが。
取り合えず、列挙出来てるのではないかと思うので(多分)
もう少し、見やすく出力できるように改善して行きたいと思います。
ありがとうございました。
---
Option Explicit
Private Declare Function AccessibleChildren Lib "oleacc" ( _
ByVal paccContainer As IAccessible, _
ByVal iChildStart As Long, _
ByVal cChildren As Long, _
rgvarChildren As Any, _
pcObtained As Long) As Long
Private Const CHILDID_SELF = 0&
Private Const S_OK = 0&
Private Sub CommandButton1_Click()
Dim acc As IAccessible
Set acc = Me
hog acc.accParent
Unload Me
End Sub
' 子孫オブジェクトを列挙
Private Sub hog(ByVal acc As IAccessible)
Dim i As Long
Dim count As Long
count = acc.accChildCount
If count > 0 Then
ReDim List(count - 1) As Variant
If AccessibleChildren(acc, 0, count, List(0), count) = S_OK Then
If IsObject(List(i)) Then
For i = LBound(List) To UBound(List)
With List(i)
On Error Resume Next
Debug.Print "ChildCount: " & .accChildCount
Debug.Print "Value: " & .accValue(CHILDID_SELF)
Debug.Print "Name: " & .accName(CHILDID_SELF)
Debug.Print "Description: " & .accDescription(CHILDID_SELF) & vbCrLf
On Error GoTo 0
End With
hog List(i) '再帰
Next
End If
End If
End If
End Sub
MSAA に関する資料は、本当に少ないですよね。SDK の "VB Sample" の項にあるのは、
"Advanced Visual Basic 6.0, Second Edition" の紹介文だけだし…。
> Accessible Explorerを見ながら1,2,,,と数えていたのですが
たしかに 1 からの連番で振られる事が多いですが、連番であるとは限りません。
(そもそも、指定すべき Child ID 自体が無い場合もありますが)
SDK の『単純要素』の説明には、以下のように書かれています。
》 IAccessible オブジェクトを共有している要素を区別するために、
》 サーバーは各単純要素に、一意の正の子 ID を割り当てます。
》 この割り当ては、インターフェイスのインスタンスごとに行われるので、
》 ID はその範囲内では一意である必要があります。
》 ID には 1 からの通し番号を割り当てている実装が多く見受けられます。
> 理由は分かりませんが、accNavigate・
論理的ナビゲーションの場合、非表示項目はスキップされる可能性が高いです。
(SDK では、EnumChildWindows API を併用する方法が提示されています)
> accChildではアクセス出来ないオブジェクトがある様に感じます。
Child ID が間違っているならば、E_INVALIDARG になりますね。
SDK によると、子が単純要素である場合は、失敗すると書かれていますので、
この場合はおそらく、エラーになるか Nothing を返すかのいずれかなのでしょう。
》 child ID を使って IAccessible::get_accChild を呼び出して、
》 IDispatch インターフェイス ポインタがあるかどうか調べます。
(中略)
》 get_accChild への呼び出しが失敗すれば、単純要素です。
> AccessibleChildrenがオールマイティなので構いませんが。
親子関係になっていない場合(空間的/論理的なナビゲーションでしか
アクセスできない項目)に対しては無効かも?
魔界の仮面弁士さん、ご回答ありがとうございます。
> Child ID が間違っているならば、E_INVALIDARG になりますね。
HRESULT型の戻り値をVBAで得る方法は大変そうなので
C++で確認してみましたが、ご推察頂きましたとおり、
E_INVALIDARG(0x80070057)が返ってきました。
Child IDを得てみると連番になってはいるのですが
-1 〜 -7 となっていて、
accChildで子オブジェクトを取得出来るので
単純要素では無い様でした。
> SDK の『単純要素』の説明には、以下のように書かれています。
日本語版のSDKの存在を今更ながら知りました。
http://www.microsoft.com/japan/msdn/accessibility/msaa/
> > 理由は分かりませんが、accNavigate・
> 論理的ナビゲーションの場合、非表示項目はスキップされる可能性が高いです。
> (SDK では、EnumChildWindows API を併用する方法が提示されています)
> > AccessibleChildrenがオールマイティなので構いませんが。
> 親子関係になっていない場合(空間的/論理的なナビゲーションでしか
> アクセスできない項目)に対しては無効かも?
いろいろと考慮しなくてはいけないのですね。
勉強になります。
疑問が残っている箇所をご配慮頂いて、
解決後にも関わらず、書き込みを頂きまして、
ありがとうございました。
ツイート | ![]() |