How to iterate over multiple Word instances (with AccessibleObjectFromWindow)

半腔热情 提交于 2019-11-29 12:03:09

I can verify you code.

Here is a diagram on the windows handles for Word and which handles respond to Accessibility interface querying (in yellow with TypeName shown in comment) and which one can be cast to Word.Application (in light green)

Original article is here (Disclaimer that's my blog)

Your question set me off to find a generic case and so there in that blog post one can find code to also reach a PowerPoint instance (as well as Excel of course). Thanks for the challenge.

After getting more intimate with Spy++ as @Comintern suggested, I traced this:

This is the actual Window order; all windows below the OpusApp are its children

But to understand why it is functioning now, we have to right click every _Ww[A_Z] below:

For _WwF:

For its children _WwB:

And finally to the goal!!!!! _WwG:

With this approach, it is obvious that we must add another layer to the code:

  Function GetWordapp(hWinWord As Long, wordApp As Object) As Boolean
        Dim hWinDesk As Long, hWin7 As Long, hFinalWindow As Long
        Dim obj As Object
        Dim iid As GUID

        Call IIDFromString(StrPtr(IID_IDispatch), iid)
        hWinDesk = FindWindowEx(hWinWord, 0&, "_WwF", vbNullString)
        hWin7 = FindWindowEx(hWinDesk, 0&, "_WwB", vbNullString)
        hFinalWindow = FindWindowEx(hWin7, 0&, "_WwG", vbNullString)
        If AccessibleObjectFromWindow(hFinalWindow, OBJID_NATIVEOM, iid, obj) = S_OK Then
            Set wordApp = obj.Application
            GetWordapp = True
        End If
    End Function

What I don't understand, but don't mind now, is why duplicate results for 2 different instances: Debug.print results:

   Instance_1 1972934 
                  x - fatores reumaticos.docx
                  FormGerenciadorCentralPacientes.docm
    Instance_2 11010524 
                  x - fatores reumaticos.docx
                  FormGerenciadorCentralPacientes.docm
    Instance_3 4857668 

But to solve that, I'll adapt the marvel solution by @PGS62; resuming:

Private Function GetWordInstances() As Collection
    Dim AlreadyThere As Boolean
    Dim wd As Application
    Set GetWordInstances = New Collection
    ...code...
    For Each wd In GetWordInstances 
                If wd Is WordApp.Application Then
                    AlreadyThere = True
                    Exit For
                End If
            Next
            If Not AlreadyThere Then
                GetWordInstances.Add WordApp.Application
            End If
      ...code...
End Function

And, voilá, iteration for all Word instances for the masses without have to close and reopen!!!

Thanks, community, for all ideas in other threads, and @Comintern for the crucial advise.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!