Студопедия

КАТЕГОРИИ:

АвтоАвтоматизацияАрхитектураАстрономияАудитБиологияБухгалтерияВоенное делоГенетикаГеографияГеологияГосударствоДомЖурналистика и СМИИзобретательствоИностранные языкиИнформатикаИскусствоИсторияКомпьютерыКулинарияКультураЛексикологияЛитератураЛогикаМаркетингМатематикаМашиностроениеМедицинаМенеджментМеталлы и СваркаМеханикаМузыкаНаселениеОбразованиеОхрана безопасности жизниОхрана ТрудаПедагогикаПолитикаПравоПриборостроениеПрограммированиеПроизводствоПромышленностьПсихологияРадиоРегилияСвязьСоциологияСпортСтандартизацияСтроительствоТехнологииТорговляТуризмФизикаФизиологияФилософияФинансыХимияХозяйствоЦеннообразованиеЧерчениеЭкологияЭконометрикаЭкономикаЭлектроникаЮриспунденкция

Class CApplication : public COleDispatchDriver




{

public:

// …

LPDISPATCH get_Documents()

{

LPDISPATCH result;

InvokeHelper(0x6, DISPATCH_PROPERTYGET, VT_DISPATCH, (void*)&result, NULL);

return result;

}

void Quit(VARIANT * SaveChanges, VARIANT * OriginalFormat, VARIANT * RouteDocument)

{

static BYTE parms[] = VTS_PVARIANT VTS_PVARIANT VTS_PVARIANT ;

InvokeHelper(0x451, DISPATCH_METHOD, VT_EMPTY, NULL, parms,

              SaveChanges, OriginalFormat, RouteDocument);

}

 

Объявления этих методов содержатся в файле CApplication.h. Вспомогательная функция InvokeHelper(), реализация которой содержится в файле OleDisp2.cpp, подготавливает параметры для вызова функции IDispatch::Invoke(), вызывает ее и возвращает результат. Мы бы могли не добавлять в наш проект класс-оболочку CApplication, а после получения интерфейса pDisp с помощью функции QueryInterface() непосредственно вызывать метод IDispatch::Invoke(), предварительно подготовив его параметры. Но это стоило бы очень больших усилий, так как подготовка параметров является очень непростой задачей. Чтобы убедиться в этом, посмотрите на объявление метода IDispatch::Invoke():

   virtual /* [local] */ HRESULT STDMETHODCALLTYPE Invoke(

       /* [in] */ DISPID dispIdMember,

       /* [in] */ REFIID riid,

       /* [in] */ LCID lcid,

       /* [in] */ WORD wFlags,

       /* [out][in] */ DISPPARAMS *pDispParams,

       /* [out] */ VARIANT *pVarResult,

      /* [out] */ EXCEPINFO *pExcepInfo,

       /* [out] */ UINT *puArgErr) = 0;

 

Главную трудность представляет собой параметр pDispParams, посредством которого конкретному методу с номером dispIdMember передаются входные параметры и, после его выполнения, возвращается результат. При желании можно в режиме трассировки посмотреть на код метода COleDispatchDriver::InvokeHelper(), чтобы не хотелось этого делать «вручную». С другой стороны, можно воспользоваться функцией InvokeHelper(), для того, чтобы «облегчить себе жизнь». Вот ее прототип:

virtual void AFX_CDECL InvokeHelper(

DISPID dwDispID,

WORD wFlags,

VARTYPE vtRet,

void* pvRet,

const BYTE* pbParamInfo,

...

);

 

Параметры:

dwDispID номер (ID) свойства или метода, который должен быть вызван;
wFlags флаги, описывающие контекст вызова метода (например, DISPATCH_PROPERTYGET);
vtRet указывает на тип возвращаемого методом значения;
pvRet адрес переменной, в которую будет помещено возвращаемое методом значение (например, значение свойства). Тип этой переменной должен соответствовать vtRet;
pbParamInfo указатель на строку с завершающим нулем (null-terminated string), которая описывает типы параметров метода
список параметров переменной длины, тип и количество которых должны соответствовать указанным в pbParamInfo.

 

 

Замечание. Если в процессе отладки программы Вы запустите какой-либо сервер и выйдете из программы, не завершив его, то останется запущенным процесс сервера, который Вы можете не заметить, если окно сервера показано не будет. Так как такая ситуация может привести к ошибкам при последующем запуске сервера, то о ней надо помнить и при необходимости вручную завершить процесс сервера с помощью менеджера задач путем уничтожения процесса.

 

Функция COleDispatchDriver::InvokeHelper() на самом деле вызывает функцию COleDispatchDriver::InvokeHelperV(), которая подготавливает параметры для вызова «настоящего» метода IDispatch::Invoke() и делает его.

Если обнаруживается, что сервер Word в данное время не запущен, то это можно сделать с помощью функции COleDispatchDriver::CreateDispatch(), которая инициирует создание СОМ объекта, идентифицируемого переданным ей параметром clsid, и прикрепление к нему интерфейса нашего объекта m_app. Если функция COleDispatchDriver::CreateDispatch() выполнится успешно, то процесс WinWord.exe будет запущен, но окно приложения Word отображаться не будет и приложения Word Вы не увидите ни в списке приложений менеджера задач, ни в строке панели задач (но в списке процессов менеджера задач он будет присутствовать). Можно работать с приложением Word и в таком состоянии, а если нужно сделать его видимым, то вызовите метод put_Visible(true) сервера Word, что и сделано в приведенном выше тексте программы.

Завершить работу сервера Word может пользователь (если окно Word мы сделали видимым) или наша программа с помощью метода Quit(). Если первый параметр этого метода имеет значение true, то перед завершением Word будет выполнено автоматическое сохранение открытых в редакторе документов.

 

Так как многие методы серверов имеют тип VARIANT, который введен, в частности, для совместимости с Visual Basic, то необходимо ознакомиться с этим типом по подразделу конспекта. Вместо типа VARIANT в программе можно было использовать класс CComVariant, производный от tagVARIANT и являющийся классом-оболочкой для типа VARIANT. Так как этот класс имеет, в частности, несколько конструкторов, то его использование существенно упрощает текст программы:

CComVariant SaveChanges(VARIANT_TRUE),DocumentFormat(1,VT_I4),

                   Empty(VT_EMPTY);

 

Вот текст функции COleDispatchDriver::CreateDispatch(), обеспечивающей запуск сервера и получение диспетчерского интерфейса IDispatch:

 

BOOL COleDispatchDriver::CreateDispatch(REFCLSID clsid,

                                   COleException* pError)

{

ASSERT(m_lpDispatch == NULL);

m_bAutoRelease = TRUE; /* good default is to auto-release

 create an instance of the object */

LPUNKNOWN lpUnknown = NULL;

SCODE sc = CoCreateInstance(clsid, NULL, CLSCTX_ALL | CLSCTX_REMOTE_SERVER,

                     IID_IUnknown, (LPLP)&lpUnknown);

if (sc == E_INVALIDARG)

{

// may not support CLSCTX_REMOTE_SERVER, so try without

sc = CoCreateInstance(clsid, NULL, CLSCTX_ALL & ~CLSCTX_REMOTE_SERVER,

           IID_IUnknown, (LPLP)&lpUnknown);

}

if (FAILED(sc)) goto Failed;

 

// make sure it is running

sc = OleRun(lpUnknown);

if (FAILED(sc)) goto Failed;

 

// query for IDispatch interface

m_lpDispatch = QUERYINTERFACE(lpUnknown, IDispatch);

if (m_lpDispatch == NULL) goto Failed;

 

lpUnknown->Release();

ASSERT(m_lpDispatch != NULL);

return TRUE;

 

Failed:

RELEASE(lpUnknown);

if (pError != NULL) pError->m_sc = sc;

return FALSE;

}

 

Как найти информацию по объектам, предоставляемым серверами MS Office?

Во-первых, это документация MSDN. Путь к нужному разделу справки в MSDN для MVS-2005 показан на рис. 2. В справочной системе описаны как объектные модели приложений MS Office, так и приведены примеры использования методов классов на языке VBA.

Во-вторых, можно использовать такой сервис приложений MS Office, как запись макросов. Например, чтобы воспользоваться этим средством в MS Word, надо проделать такие операции:

1. Запустить на выполнение MS Word и включить запись макроса – Сервис/Макрос/Начать запись. В появившемся диалоговом окне можно изменить имя макроса и сферу его применения

2. Выполнить «вручную» те операции, которые необходимо запрограммировать. При этом возможно с помощью кнопок панели управления макроса приостановить или отменить его запись

3. После завершения всех операций остановить запись и открыть текст макроса, например, с помощью команды Сервис/Макрос/Редактор Visual Basic. Сгенерированный текст макроса можно использовать как шаблон для записи текста программы.

 

 

Рис. 2. Путь к разделу справки по программированию доступа к сервисам MSWord










Последнее изменение этой страницы: 2018-04-12; просмотров: 420.

stydopedya.ru не претендует на авторское право материалов, которые вылажены, но предоставляет бесплатный доступ к ним. В случае нарушения авторского права или персональных данных напишите сюда...