ccomoleidispatch

How do I get a member from an IDispatch interface which is an "array"?


I am a C programmer, but I am new to Windows & COM programming.

For the following C# code:

//Change the font of the selected text in the running PowerPoint.
Application app = Marshal.GetActiveObject("Powerpoint.Application");
app.ActiveWindow.Selection.TextRange.Font = ...;

I know how to write the corresponding OLE code in C. To recap briefly:

  1. Call GetActiveObject to get the IUnknown interface of the application;
  2. Call IUnknown_QueryInterface to get the IDispatch of the application;
  3. Call IDispatch_GetIDsOfNames and IDispatch_Invoke with DISPATCH_PROPERTYGET to get the named property of the current IDispatch.
  4. Repeat Step 2 to Step 4, until we reach the second innermost property(that is TextRange in the above example).
  5. Call IDispatch_GetIDsOfNames and IDispatch_Invoke with DISPATCH_PROPERTYPUT to set the value of innermost property(that is Font in the above example).

here comes the question: What if a property is an "array"? For example, given the following C# code:

Application app = Marshal.GetActiveObject("Illustrator.Application");
foreach (object textFrame in app.ActiveDocument.TextFrames)
    ...;

The above C# code iterates every text frame from the TextFrames "array", I have no idea of the corresponding C code for "iterating" such a property in C. I have searched through the Internet and Microsoft development references, but failed to get any clue.

How do I get members from an "array" property using C?


Solution

  • Textframe may not be an array. I suppose it is an enumerator. But check the returned type in the debugger.

    Or you need to show us the type lib or idl file for the interface you are using.

    In if it is an iterator the TextFrames object has a property _NewEnum. This has an interface IEnumVARIANT... usually OnNext is called until OnNext returns S_FALSE.

    SO what is happening here is that ForEach asks calls the _NewEnum property of the TextFrames object. It may call OnReset or OnClose and than calls OnNext for each member...

    If it is an array you get a VARIANT containing a SAFEARRAY.