Finding the right arguments for Windows API

Edgar_

Board Regular
Joined
Mar 11, 2024
Messages
72
Office Version
  1. 2021
  2. 2016
Platform
  1. Windows
I've been trying to control AutoCAD instances with functions from the Windows API and I realized I do not understand how to use the AccessibleObjectFromWindow function. After trying the code in this source, I was able to grab a few objects, but they're from Excel:
VBA Code:
Sub InspectInstances()
    Dim guid&(0 To 3), acc As Object, hwnd, hwnd2, hwnd3
    guid(0) = &H20400
    guid(1) = &H0
    guid(2) = &HC0
    guid(3) = &H46000000
   
    Dim col As Collection
    Set col = New Collection
    Do
        hwnd = FindWindowExA(0, hwnd, "XLMAIN", vbNullString)
        If hwnd = 0 Then Exit Do
        hwnd2 = FindWindowExA(hwnd, 0, "XLDESK", vbNullString)
        hwnd3 = FindWindowExA(hwnd2, 0, "EXCEL7", vbNullString)
        Debug.Print hwnd, hwnd2, hwnd3
        If AccessibleObjectFromWindow(hwnd3, &HFFFFFFF0, guid(0), acc) = 0 Then
            col.Add acc.Application
        End If
    Loop
    Stop
End Sub
After inspecting the sample code, it is clear that this is not the typical VBA experience because, as is the case with other Windows API functions, a lot of prior knowledge of the Windows environment is necessary. And that's where I'm stumbling. The AccessibleObjectFromWindow function is declared as follows:
Rich (BB code):
Private Declare Function AccessibleObjectFromWindow Lib "oleacc" ( _
    ByVal hwnd As Long, _
    ByVal dwId As Long, _
    riid As Any, _
    ppvObject As Object _
) As Long
After reading the docs, two of those parameters are easy to guess: hwnd and ppvObject, one is the window handle and the other is the object that will receive the automation object "extracted" from the window. So far, it's good. But dwId and riid are a puzzle for me. The sample code spoilered above shows that &HFFFFFFF0 works as the argument for the dwId parameter, but then comes the riid parameter, which requires an array. Not only that, but the argument utilized in the sample code is just the first item of that array (guid(0)). If I make modifications to any of these in the sample code, I no longer get the object. I realize that the GUI Id utilized in the sample code derives from the IUnknown interface, whatever that means, and &HFFFFFFF0 is some sort of default? No idea...

As for the other function, FindWindowExA, I don't see much of a problem with it (yet). It just requires window handles and class names. I can use the Windows SDK's Inspector tool, Spy++ or the OLE Viewer to find the class names for the objects I want to extract. So, after evaluating the class names that Excel utilizes, I was able to confirm (at least) that part of the puzzle that makes the sample code work: XLMAIN is the Excel application, XLDESK is a child XLMAIN and holds Excel documents, while EXCEL7 classes are the documents themselves, where the automation objects were.

So, the next step was evident for me, I had to try the sample code but with the class names that AutoCAD provides. I found out the application's class name was AfxMDIFrame100u, the child that holds documents was called MDIClient, and the documents had dynamic class names that look like this "Afx: ... ". The structure seemed similar, but I could not make the sample code work for AutoCAD by simply replacing the class names. So, no, I got no automation object from them.

It's somewhat relevant to say that I can simply do this: GetObject(,"AutoCAD.Application") to get access to the automation objects of several AutoCAD drawing documents, but I want all instances, not just one of them. Because in my industry, we typically have a lot of drawings open all the time.

The following questions arise:
1. How can I find the dwId and riid I need?
2. Is the fact that I don't know those two arguments the reason I didn't get the automation object?
3. How do I know which windows can grant an automation object?
 
Last edited:

Excel Facts

Quick Sum
Select a range of cells. The total appears in bottom right of Excel screen. Right-click total to add Max, Min, Count, Average.
I won't claim to know the answer to your questions, but I would simply note that Jaafar Tribak (the likely author of the code you're referencing above) recently wrote and published another method of getting all the instances of certain office programs. It may be relevant to what you're doing. Referencing all Running Instances Of Excel, Word and Access
 
Upvote 0
I won't claim to know the answer to your questions, but I would simply note that Jaafar Tribak (the likely author of the code you're referencing above) recently wrote and published another method of getting all the instances of certain office programs. It may be relevant to what you're doing. Referencing all Running Instances Of Excel, Word and Access
I'm aware of him, he already provided me with tons of help, he's a legend!

Thanks, Dan.
 
Upvote 0

Forum statistics

Threads
1,221,310
Messages
6,159,173
Members
451,543
Latest member
cesymcox

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