Как мне получить элемент из интерфейса IDispatch, который является «массивом»?

#c #com #ole #idispatch

#c #com #ole #idispatch

Вопрос:

Я программист на C, но я новичок в программировании на Windows и COM.

Для следующего кода C #:

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

Я знаю, как написать соответствующий OLE-код на C. Кратко резюмируя:

  1. Вызовите GetActiveObject, чтобы получить неизвестный интерфейс приложения;
  2. Вызовите IUnknown_QueryInterface, чтобы получить IDispatch приложения;
  3. Вызовите IDispatch_GetIDsOfNames и IDispatch_Invoke с помощью DISPATCH_PROPERTYGET, чтобы получить именованное свойство текущего IDispatch.
  4. Повторяйте шаги со 2 по шаг 4, пока мы не дойдем до второго самого внутреннего свойства (то есть TextRange в приведенном выше примере).
  5. Вызовите IDispatch_GetIDsOfNames и IDispatch_Invoke с помощью DISPATCH_PROPERTYPUT, чтобы установить значение самого внутреннего свойства (то есть шрифта в приведенном выше примере).

здесь возникает вопрос: что, если свойство является «массивом»? Например, учитывая следующий код C #:

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

Приведенный выше код C # выполняет итерацию каждого текстового фрейма из «массива» текстовых фреймов, я понятия не имею о соответствующем коде C для «итерации» такого свойства в C. Я искал в Интернете и ссылках на разработки Microsoft, но не смог получить никакой подсказки.

Как мне получить элементы из свойства «array» с помощью C?

Комментарии:

1. Это не массив. docs.microsoft.com/en-us/windows/win32/api/oaidl /…

2. Используете ли вы Visual Studio? С в порядке? Вы действительно хотите перечислять или сканировать каждый элемент по индексу, это нормально?

3. @SimonMourier Я использую MSYS Clang, я обычный программист Linux и временно работал над Windows. Проблема была решена с помощью xMRi

4. Вы можете взглянуть на библиотеку типов с помощью инструмента OleView из Windows SDK. Библиотека типов для illustrator находится по адресу C:Program FilesAdobe Adobe Illustrator 2021 Plug-ins ExtensionsScriptingSupport.aip (адаптируйте к вашему контексту). Он расскажет вам, что Document реализует тип. Вам не обязательно использовать _NewEnum , вы также можете использовать long Count() TextFrame* Item(VARIANT key) методы and, которые обычно немного проще из C / C и позволяют получить прямой доступ к элементу, используя его индекс.

5. @SimonMourier Благодарю вас за информацию об инструменте и альтернативном решении. Этот инструмент, который вы рекомендовали, также может помочь в будущем развитии.

Ответ №1:

Текстовый фрейм может не быть массивом. Я полагаю, что это счетчик. Но проверьте возвращаемый тип в отладчике.

Или вам нужно показать нам файл типа lib или idl для используемого вами интерфейса.

В случае, если это итератор, объект TextFrames имеет свойство _NewEnum. Это имеет интерфейс IEnumVARIANT … обычно onNext вызывается до тех пор, пока onNext не вернет S_FALSE .

ИТАК, что здесь происходит, так это то, что ForEach asks вызывает свойство _NewEnum объекта TextFrames. Он может вызывать OnReset или OnClose, а затем вызывать onNext для каждого члена…

Если это массив, вы получаете ВАРИАНТ, содержащий SAFEARRAY.

Комментарии:

1. Спасибо за ваше информативное руководство. У меня есть ВАРИАНТ, vt которого равен VT_DISPATCH, поэтому он выглядит как перечислитель, как вы и предлагали. Но есть еще один шаг для решения проблемы. Я вызвал IDispatch_GetIDsOfNames(textFramesVar.pdispVal, amp;IID_NULL, (LPOLESTR[1]){L»_NewEnum»}, 1, LOCALE_USER_DEFAULT, amp;dispId); GetIDsOfNames просто не удалось (и использование GetIDsOfNames для получения идентификатора _NewEnum звучит неправильно для моего инстинкта). Является ли получение SDK, запрос интерфейса и затем вызов Get__NewEnum единственным способом получить свойство _NewEnum? Спасибо.

2. DISPID_NEWENUM — это константа… и исправлено для всех счетчиков.

3. Ссылка: docs.microsoft.com/en-us/previous-versions/windows/desktop/…

4. @xMRi Отлично, это работает! Спасибо за помощь.