Студопедия

КАТЕГОРИИ:

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

Сценарий для версии MVS 2005




 

Проиллюстрируем эту технологию на примере получения доступа к серверу Microsoft Word. Последовательность действий следующая.

Шаг 1. Создание каркаса приложения.

Создадим с помощью мастера Win32 Console Application заготовку обычного консольного приложения с поддержкой MFC. Предполагается, что проекту присвоено имя UseWord.

Шаг 2. Инициализация OLE.

Любое клиентское приложение, будь оно консольным или оконным, которое хочет использовать какой-либо сервер СОМ, должно инициализировать службу СОМ с помощью функции CoInitialize(). Эту функцию надо вызвать всего один раз прежде чем использовать какие-либо другие функции СОМ, т.е. прежде чем пытаться устанавливать связь с сервером и вызывать его функции. По завершению работы приложения необходимо вызвать функцию CoUninitialize(), которая, как сказано в MSDN, «закрывает библиотеку СОМ в текущем апартаменте, выгружает все библиотеки DLL, загруженные апартаментом, освобождает все другие ресурсы апартамента и разрывает все RPC-соединения с апартаментом». Обеспечить вызов этих функций можно и с помощью описания класса OleInit, как это было сделано выше в подразделе «Доступ к серверу с помощью пользовательских интерфейсов».

С учетом этого файл реализации консольного приложения UseWord.cpp может иметь вид, приведенный в следующем листинге.

#include "stdafx.h"

#include "UseWord.h"

// …

 

CWinApp theApp;

 

using namespace std;

struct OleInit

{ OleInit()

{

 CoInitialize(NULL);

 TRACE("CoInitialize(NULL) executed\n");

}

~OleInit()

{

 CoUninitialize();

 TRACE("CoUninitialize() executed\n");

}

} Init;

 

int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])

{

int nRetCode = 0;

if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0))

{

     _tprintf(_T("Fatal Error: MFC initialization failed\n"));

     return nRetCode = 1;

}

 

return nRetCode;

}

 

Если такую программу запустить на выполнение в режиме отладки, то в окне Debug мы увидим сообщения «CoInitialize(NULL) executed» все в том же окне Debug. Рекомендую это проделать практически, следуя концепции быстрой разработки программ.

Шаг 3. Генерация классов-оболочек для интерфейсов сервера Word.

Для использования диспетчерских интерфейсов Word надо получить доступ к их объявлениям, хранящимся в библиотеке MSWord.olb. Этот файл должен находиться в каталоге …\\Program Files\Microsoft Office\Office. (В зависимости от версии Microsoft Word имя файла может отличаться от приведенного, например, Word9.olb. Сказанное относится и к имени каталога Office, которое может также включать номер версии, например, Office11.)

Для получения описаний интерфейсов и методов Word надо выполнить команду ProjectèAdd Class, в появившемся окне выбрать Categories==MFC и Templates==MFC Class From TypeLib. Нажимаем кнопку Add и в новом появившемся окне открываем список Available type libraries (доступные библиотеки типов). В этом списке перечислены все библиотеки типов, зарегистрированные в реестре. Выбираем в списке элемент Microsoft Word (рис.1), а в списке Interfaces выберем один интерфейс – _Application – и включим его в список Generated classes с помощью кнопки >.  (Ясное дело, что в «реальной» программе надо было бы генерировать классы для всех интерфейсов, которые нам понадобятся.) Обратите внимание на то, что в элементах Class и File мастер показывает имена классов и заголовочных файлов, которые он будет генерировать. Закончите работу по генерации объявлений классов нажатием кнопки Finish.

Замечание. Практически того же результата мы бы смогли добиться и другим путем, выбрав в окне радиокнопку Add Class from: File, а не Registry, которая выбрана по умолчанию. Далее в поле Location с помощью диалога по открытию файла мы должны были бы указать имя файла MSWORD.OLB.

 

 

Рис. 1. Выбор библиотеки типов и интерфейсов

 

В файл CApplication0.h мастер поместит сгенерированный класс-оболочку CApplication (IDispatch wrapper classes), который мы и будем использовать для вызова методов интерфейсов. Класс CApplication облегчает подключение к серверу или его запуск и обеспечивает вызов методов сервера с помощью вспомогательных функций.

Рекомендую ознакомиться с содержимым этого файла.

 

Внимание. Обязательно закомментируйте директиву #import в начале файла CApplication0.h.

Шаг 4. Запуск сервера Word.

Теперь модифицируем файл UseWord.cpp, добавив в него код запуска Word. Не забудьте в начало файла добавить директивы для подключения заголовочного файла, сгенерированного мастером.

// UseWord.cpp : Иллюстрация запуска приложения MS Word

//

#include "stdafx.h"

#include "UseWord.h"

#include <ComDef.h> // объявление класса _com_error

#include "CApplication.h"

#include <ConIO.h>

 

#ifdef _DEBUG

#define new DEBUG_NEW

#endif

CWinApp theApp;

using namespace std;

 

char Buf[1024];

char * Rus(char * Str)

{

CharToOemA(Str,Buf); return Buf;

}

struct OleInit

{ OleInit()

{

 CoInitialize(NULL);

 TRACE("CoInitialize(NULL) executed\n");

}

~OleInit()

{

 CoUninitialize();

 TRACE("CoUninitialize() executed\n");

}

} Init;

 

int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])

{

int nRetCode = 0;

if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0))

{

     _tprintf(_T("Fatal Error: MFC initialization failed\n"));

     return nRetCode = 1;

}

try

{

     LPDISPATCH pDisp;

     LPUNKNOWN pUnk;

     CLSID clsid;

     CApplication m_app;

     /*Получение GUID приложения Word по его внешнему имени

        Word.Application, под которым Word зарегистрирован в реестре*/

     CLSIDFromProgID(L"Word.Application",&clsid);

     /*GetActiveObject позволяет получить интерфейс запущенного экземпляра сервера, если таковой есть, по его clsid*/

     if(GetActiveObject(clsid,NULL,&pUnk)==S_OK)

     {

     VERIFY(pUnk->QueryInterface(IID_IDispatch,

                                   (void **)&pDisp)==S_OK);

     m_app.AttachDispatch(pDisp);

     pUnk->Release();

     TRACE("Подключение к запущенному экземпляру”

“ Word выполнено успешно\n");

     }

     else // самостоятельно запускаем приложение Word

     if(!m_app.CreateDispatch(clsid)) throw

"Не найдено приложение Word";

     /* В этой точке мы либо подключились к уже запущенному

экземпляру Word, либо запустили свой экземпляр приложения */

     m_app.put_Visible(true);

     TRACE("Окно Word должно быть видимо\n");

     cout<<Rus("Нажми любую клавишу для завершения работы")<<endl;

     _getch();

     // Готовим параметры для метода Quit()

     VARIANT SaveChanges, DocumentFormat, Empty;

     SaveChanges.vt=VT_BOOL;

     SaveChanges.boolVal=VARIANT_TRUE;

     DocumentFormat.vt=VT_I4;

     DocumentFormat.intVal=1;

     Empty.vt=VT_EMPTY;

     m_app.Quit(&SaveChanges,&DocumentFormat,&Empty);

}

catch(_com_error &ex) // обработка СОМ ошибок

{     

     AfxMessageBox(ex.ErrorMessage());

}

catch(char * msg)

{

     AfxMessageBox(CString(msg));

}

_getch();

return nRetCode;

}

 

Некоторые комментарии к программе.

В файле CApplication.h нет ни одного GUID! И вообще здесь в программе используется только clsid сервера Word, который мы получаем с помощью функции CLSIDFromProgID(), и еще GUID диспетчерского интерфейса IID_IDispatch, определенный где-то в другом месте.

Функция

void COleDispatchDriver::AttachDispatch(

LPDISPATCH lpDispatch,

BOOL bAutoRelease = TRUE

);

 

подключает интерфейс lpDispatch к объекту класса COleDispatchDriver (класс CApplication является наследником этого класса). Параметр bAutoRelease указывает, должен ли интерфейс освобождаться при выходе объекта из сферы видимости. В нашем случае мы прикрепили полученный с помощью функции QueryInterface() интерфейс pDisp к объекту m_app. После этого мы сможем вызывать методы объекта m_app. Вот примеры реализации оболочек (wrapper) двух методов интерфейса _Application, которые мы используем как методы объекта m_app:

 










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

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