- •Материал к курсам «Объектно-ориентированное программирование», «Инструментальные средства визуального программирования» и «Современные технологии и инструментарий программирования»
- •8. Интерфейс графического устройства, цвет и шрифт 71
- •10. Консольные приложения Windows 91
- •21. Алгоритмы 220
- •22. Профилирование программы в Microsoft Visual Studio 6.0 238
- •23. Некоторые функции api Win32 240
- •24. Разное-всякое 247
- •Часть2.Технология сом 299
- •Предисловие автора
- •1.3.Работа со строками
- •1.3.1.Кодировки и кодовые страницы
- •1.3.2.О кодировке Unicode
- •1.3.3.Использование класса cString
- •1251 (Cyrillic (Windows) ) в кодировку 866 (Cyrillic dos).
- •1.3.4.Некоторые полезные функции класса cString
- •1.4.Явное преобразование типов
- •1.4.1.Преобразование полиморфных типов dynamic_cast
- •1.4.2.Преобразование неполиморфных типов static_cast
- •1.4.3.Преобразование reinterpret_cast
- •2.Соглашения об именах
- •3.Пространства имен
- •4.Макросы и отладка
- •4.1.Макрос trace
- •4.2.Объект afxDump
- •4.3.Классы cDumpContext и cObject
- •4.5.Макрос assert_valid
- •4.6.Макрос verify
- •4.7.Автоматическая диагностика неуничтоженных объектов
- •5.Каркас приложений mfc
- •5.1.Понятие каркаса приложений
- •Каркас приложений и библиотека классов
- •Пример на базе каркаса приложений
- •5.2.Сопоставление сообщений в библиотеке mfc
- •5.3.Документы и их представление
- •5.4.Функции взаимодействия «документ-вид»
- •5.5.Простейшее приложение на базе архитектуры «документ-вид»
- •5.6.Усложненное взаимодействие «документ-вид»
- •6.Класс «вид» библиотеки mfc (версия mvs 6.0)
- •6.1.Что такое «вид»
- •6.2.Интерфейсы sdi и mdi
- •6.3. Сценарий создания приложения drw в ис mvs 6.0
- •6.4.Класс cdrwView
- •6.5.Рисование внутри окна представления: Windows gdi
- •Функция-член OnDraw
- •Контекст устройства в Windows
- •Добавление кода рисования в программу drw
- •6.6.Первое знакомство с редакторами ресурсов
- •Содержимое файла drw.Rc
- •Работа с редактором диалоговых окон
- •6.7.Конфигурации Win32 Debug и Win32 Release
- •6.8.Активизация диагностических макросов
- •6.9.Предкомпилированные заголовочные файлы
- •6.10.Два способа запуска программы
- •7.Класс «вид» библиотеки mfc (версия mvs 2005)
- •7.1.Что такое «вид»
- •7.2.Интерфейсы sdi и mdi
- •7.3. Сценарий создания приложения с архитектурой документ-вид в среде mvs 2005
- •7.4.Класс cdrwView
- •7.5.Рисование внутри окна представления: Windows gdi
- •Функция-член OnDraw
- •Контекст устройства в Windows
- •Добавление кода рисования в программу drw
- •7.6.Конфигурации Win32 Debug и Win32 Release
- •7.7.Активизация диагностических макросов
- •7.8.Два способа запуска программы
- •8.Интерфейс графического устройства, цвет и шрифт
- •8.1.Классы контекста дисплея cClientDc и cWindowDc
- •8.2.Создание и уничтожение cdc-объектов
- •8.3.Состояние контекста устройства
- •8.4.Класс cPaintDc
- •8.5.Объекты gdi
- •8.6.Создание и уничтожение gdi-объектов
- •8.7.Управление gdi-объектами
- •8.8.Стандартные gdi-объекты
- •8.9.Время жизни контекста устройства
- •9.1.Приложение, основанное на диалоговом окне
- •9.2.Приложение без поддержки архитектуры документ-вид
- •9.3.Приложение с поддержкой архитектуры документ-вид
- •9.4.Краткая характеристика базовых классов класса вид
- •9.4.1.Класс cView
- •9.4.2.Класс cFormView
- •9.4.3.Класс cHtmlView
- •9.4.4.Класс cListView
- •9.4.5.Класс cRichEditView
- •9.4.6.Класс cScrollView
- •9.4.7.Класс cTreeView
- •10.2.Создание консоли
- •10.3.Закрытие консоли
- •10.4.Дескрипторы консоли
- •10.5.Входной буфер консоли
- •10.6.Буферы дисплея консоли
- •10.7.Размер буфера окна и дисплея
- •10.8.Скроллинг дисплейного буфера
- •10.9.Методы ввода/вывода в консольных приложениях
- •10.10.Режимы консоли
- •10.11.Высокоуровневый консольный ввод/вывод
- •10.12.Высокоуровневые режимы консоли
- •10.13.Высокоуровневые функции ввода и вывода консоли
- •10.15.Низкоуровневые режимы консоли
- •10.16.Низкоуровневые функции ввода консоли
- •10.14.Низкоуровневые функции ввода и вывода консоли
- •10.17.Низкоуровневые функции вывода консоли
- •10.18.Кодовые страницы в консольных приложениях
- •10.19.Пример консольного приложения ColorRusConsole
- •10.20.Использование графики в консольных приложениях
- •10.21.Изменение заголовка окна приложения и его прятание
- •11.Архитектура документ-вид и диалоговое окно
- •11.1.Как получить доступ к документу из диалогового окна
- •11.1.1.Первый способ
- •11.1.2.Второй способ
- •11.2.Как получить доступ к представлению из диалогового окна
- •11.3.Отображение данных в управляющих элементах диалогового окна и их получение (mvs 6.0)
- •11.4.Создание оконных подклассов для расширенного управления вводом данных
- •12.Обработка файлов
- •12.1.Обработка текстовых файлов (mvs 6.0)
- •12.2.Обработка текстовых файлов (mvs 2005)
- •12.3.Обработка двоичных файлов
- •12.4.Поиск файлов и каталогов по заданному пути и маске
- •12.5.Диалоги по выбору имени файла и каталога
- •13.Обработка сообщений Windows
- •13.1.Обработка сообщений в рамках одного приложения
- •13.2.Об обработке команд
- •13.3.Обработка сообщений в рамках системы
- •14.Разработка и использование собственных dll
- •14.1.Основы dll
- •14.1.1.Согласование импортируемых элементов с экспортируемыми
- •14.1.2.Явное и неявное связывание
- •14.1.3.Связывание по символьным именам против связывания по порядковым номерам
- •14.1.4.Точка входа в dll: функция DllMain
- •14.1.5.Описатели экземпляров и загрузка ресурсов
- •14.1.6.Порядок поиска dll клиентской программой
- •14.1.7.Отладка dll
- •14.1.9.Общие dll mfc-библиотеки
- •14.1.10.Dll-расширения: экспорт классов
- •14.1.11.Последовательность поиска ресурсов в dll-расширении
- •14.2.Разработка библиотеки
- •14.3.Разработка клиентского приложения, использующего библиотеку dll
- •15.Обработка растровых изображений
- •16.Обработка исключительных ситуаций
- •If (блок будет работать)
- •16.1.Введение в обработку исключительных ситуаций
- •16.2.Синтаксис обработки исключительных ситуаций
- •16.3.Синтаксис инициирования исключительных ситуаций
- •16.4.Примеры генерации и обработки исключительных ситуаций
- •17.Классы
- •17.1.Пример класса tVector
- •17.2.Класс tVector с перегруженными операциями
- •18.Шаблоны классов
- •18.1.Пример шаблона класса
- •18.2.Шаблон класса tVector
- •19.Стандартная библиотека, библиотеки mfc и atl
- •19.1.Состав стандартной библиотеки
- •19.2.Библиотеки mfc и atl
- •20.Коллекции
- •20.1.Обзор коллекций mfc
- •20.2.Шаблонные классы коллекций mfc
- •20.3.Использование массивов, списков и ассоциативных массивов
- •20.3.1.Использование простых массивов и списков
- •20.3.2.Члены класса cArray
- •Конструкторы
- •Атрибуты
- •Обработка
- •Доступ к элементам
- •Увеличение размера массива
- •Вставки и удаления
- •Операции
- •20.3.3.Члены класса cList
- •Параметры
- •Возвращаемое значение
- •Замечания
- •Параметры
- •Возвращаемое значение
- •20.3.4.Использование простых ассоциативных массивов
- •20.4.Использование шаблонов коллекций типизированных указателей
- •20.4.1.Использование массивов и списков типизированных указателей
- •20.4.2.Использование типизированных указателей на ассоциативные массивы
- •20.5.Использование контейнера vector
- •20.5.1.Конструкторы
- •Пример использования конструкторов
- •20.5.4.Иллюстрация использования класса vector
- •21.Алгоритмы
- •21.1.Общие соглашения
- •21.2.Итераторы
- •21.3.Функциональные объекты
- •21.4.Распределители
- •21.5.Состав библиотеки алгоритмов
- •21.6.Немодифицирующие алгоритмы
- •21.7.Пример использования шаблонной функции sort() из библиотеки алгоритмов
- •21.8.Сортировка массива объектов пользовательского класса
- •21.9.Еще одна иллюстрация некоторых алгоритмов на примере обработки числового массива
- •22.Профилирование программы в Microsoft Visual Studio 6.0
- •23.Некоторые функции api Win32
- •23.1.Получение информации о компьютере и операционной системе
- •23.1.1.Функция GetLogicalDrives
- •23.1.2.Функция GetDriveType
- •23.1.3.Функция GetDriveType
- •23.1.4.Функция GetDiskFreeSpaceEx
- •23.1.5.Функция GlobalMemoryStatus
- •23.1.6.Функции GetComputerName, GetUserNameA
- •23.1.7.Функции GetSystemDirectory, GetTempPath, GetWindowsDirectory, GetCurrentDirectory
- •23.1.8.Функция GetSystemInfo
- •24.Разное-всякое
- •24.1.Русификация приложений
- •24.2.Помощь и всплывающие подсказки
- •24.3.Использование ini-файла
- •24.3.1.Ansi-версия программы для среды mvs 6.0.
- •24.3.2.Unicode-версия программы для ис mvs-2005 и mvs-2008.
- •24.3.3.Ansi-версия программы для ис mvs-2005.
- •24.3.4.Ansi-версия программы для ис mvs-2008
- •24.4.Установка размеров и положения главного окна-рамки приложения
- •24.5.Создание дополнительного потока в консольном приложении
- •24.6.Интеллектуальные указатели
- •24.7.Управление формой курсора мыши
- •24.8.Как выйти из длительного цикла
- •24.9.Получение изображения содержимого окна
- •Сохранение изображения в файле
- •0, // Первая строка развертки, которая должна
- •0, // Число копируемых линий
- •Int I; // Количество выбираемых линий
- •0, // Первая строка развертки, которая должна быть выбрана
- •0, // Число копируемых линий
- •0, // Первая выбираемая линия для изображения назначения
- •0, // Режим использования
- •24.10.Подстройка очертания окна под контур изображения
- •24.11.Как корректно завершить приложение с графическим интерфейсом из него самого
- •24.12.Обработка ошибок ввода
- •25.Интегрированная среда Microsoft Visual Studio 2005
- •25.1.Терминология
- •25.2.Свойства решения и проекта
- •25.3.Что обозначают иконки на вкладке Class View
- •26.О справочной системе msdn версий 6.0 и 2005
- •26.1.Примеры приложений (версия 6.0)
- •26.2.Учебные пособия (tutorials)
- •26.3.Примеры приложений из msdn-2005
- •26.3.1.Примеры приложений mfc (mfc samples)
- •27.Процессы и потоки
- •27.1.Основные понятия Понятие приложений, процессов и потоков
- •Текущие диск и каталог для процесса
- •Определение версии системы
- •Когда полезно создавать потоки
- •Когда многопоточность неэффективна
- •Механизм многопоточности Windows
- •Приостановка, возобновление и переключение потоков
- •Приостановка и возобновление процессов
- •27.2.Функция потока
- •Функция CreateThread
- •Завершение потока
- •Часть2.Технология сом
- •28.Краткий обзор концепций программирования
- •29.Обзор технологии .Net и c#
- •29.1.Введение
- •29.2.Характеристика платформы .Net Framework
- •Среда разработки: Microsoft Visual Studio
- •Язык f#
- •29.3.Пример консольного приложения
- •29.4.Класс стек на основе связного списка
- •29.5.Чтение текстового файла
- •30.Предпосылки возникновения com
- •31.Межпроцессное взаимодействие
- •34.Введение в com технологии
- •34.1.Основные понятия и определения
- •34.2.Технология com как спецификация и реализация
- •34.3.Составляющие приложений com
- •35.Способы реализации сом серверов
- •35.1.Виды серверов и их основные характеристики
- •35.2.Алгоритм взаимодействия клиента с внутрипроцессным сервером
- •Последовательность действий при вызове клиентом внутрипроцессного сервера.
- •Последовательность действий при вызове клиентом локального или удаленного сервера
- •36.Интерфейсы
- •37.Доступ к серверу с помощью пользовательских интерфейсов
- •38.Доступ к серверу с помощью интерфейса iDispatch
- •38.1.Сценарий для версии mvs 6.0
- •38.2.Сценарий для версии mvs 2005
- •38.3.Доступ к серверу Excel в mvs 2005 с помощью диспетчерского интерфейса
- •39.Применение интеллектуальных указателей для доступа к серверам
- •39.1.Импорт библиотеки типов
- •39.2.Доступ к серверу SolidWorks 2003 с помощью интеллектуальных указателей
- •39.3.Доступ к серверу SolidWorks 2007 с помощью интеллектуальных указателей
- •39.4.Доступ к серверу Microsoft Word с помощью интеллектуальных указателей из консольного приложения
- •39.5.Доступ к серверу Microsoft Word с помощью интеллектуальных указателей из gui-приложения
- •40.Внедрение и связывание объектов
- •40.1.Понятие внедрения и связывания объектов
- •40.2.Серверы и контейнеры
- •41.Обработка ошибок
- •41.1.Функция SetErrorMode – управление реакцией программы на ошибочные состояния
- •41.2.Функции GetLastError и SetLastError – получение кода ошибки и его установка
- •41.3.Коды ошибок hresult
- •41.4.Получение текстов сообщений об ошибках
- •42.Типы данных сом
- •42.1.Типы данных методов и свойств сом объектов
- •43.Приложения
- •43.1.Словарь терминов
- •43.2.О регистрации внутрипроцессного сервера сом
- •5. Степанов а., Менг Ли. Руководство по стандартной библиотеке шаблонов (stl)/ Пер. На русский а.Суханова и а.Кутырина – м.: 1999.
- •Список литературы по платформе .Net
- •9. Дон Бокс, Крис Селлз. Основы платформы .Net, том 1. Общеязыковая исполняющая среда /Пер. С англ. – м.; сПб.: к.: Издательский дом "Вильямс", 2003. – с.288. Isbn 5-8459-0455-2
- •10. Деймьен Уоткинз, Марк Хаммонд, Брэд Эйбрамз. Программирование на платформе .Net среда /Пер. С англ. – м.; сПб.: к.: Издательский дом "Вильямс", 2003. – с.368. Isbn 5-8459-0456-0
- •11. Джеффри Рихтер. Clr via c#. Программирование на платформе Microsoft .Net Framework 2.0 на языке c#. Мастер-класс / Пер. С англ. – м.:Издательство «Русская редакция»; сПб.: Питер, 2007. - 656с.
- •12. Джеффри Рихтер. Программирование на платформе Microsoft .Net Framework / Пер. С англ. – м.:Издательско-торговый дом «Русская редакция», 2003 - 512с.
- •14. Пауэрс Ларс, Майкл Снелл. Microsoft Visual Studio 2008 / Пер. С англ. — сПб.:
- •Список литературы по технологии сом
- •13. Дейл Роджерсон. Основы сом/Пер. С англ.–2-е изд., исправл. И дополн.–м,:Изд.-торг. Дом «Русская редакция».–2000, 400с.
- •15. Дэвид Чеппел. Технология ActiveX и ole/ Пер. С англ. – м.: Издательский отдел "Русская редакция" тоо "Channel Traiding Ltd.", 1999. – 320с.
- •16. Бокс д. Сущность технологии сом. Библиотека программиста. — сПб.: Питер, 2001. — 400 с.: ил. (Есть в электронном формате)
- •17. К. Таваре, к. Фертитта, б. Ректор, к. Селлз. Библиотека atl 8: внутренняя структура и применение. Microsoft Visual Studio 2005. – м.; сПб.:, к.: Издательский дом "Вильямс", 2007, 736с.
38.3.Доступ к серверу Excel в mvs 2005 с помощью диспетчерского интерфейса
Последовательность действий для подключения Excel практически такая же, как и для сервера Word.
Шаг 1. Создание каркаса приложения.
Создадим с помощью мастера Win32 Console Application заготовку обычного консольного приложения с поддержкой MFC. Предполагается, что проекту присвоено имя UseExcel.
Шаг 2. Инициализация OLE.
Как и в случае с Word, добавим в приложение класс OleInit для инициализации служб СОМ. С учетом этого файл реализации консольного приложения UseExcel.cpp будет иметь вид, приведенный в следующем листинге.
#include "stdafx.h"
#include "UseExcel.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» и «CoUninitialize() executed». Рекомендую это проделать практически, следуя концепции RAD (быстрой разработки программ).
Шаг 3. Генерация классов-оболочек для интерфейсов сервера Excel.
Для использования диспетчерских интерфейсов Excel надо получить доступ к их объявлениям, которые находятся, как положено в библиотеке типов, ну а сама библиотека типов, в отличие от Word, размещается в файле Excel.exe.
Для получения описаний интерфейсов и методов Excel надо выполнить команду ProjectAdd Class, в появившемся окне выбрать Categories==MFC и Templates==MFC Class From TypeLib. Нажимаем кнопку Add и в новом появившемся окне открываем список Available type libraries (доступные библиотеки типов). В этом списке перечислены все библиотеки типов, зарегистрированные в реестре. Выбираем в выпадающем списке элемент Microsoft Excel 11.0 Object Library <1.5> (рис.1), а в списке Interfaces мы можем выбирать любые интерфейсы и включать их в список Generated classes с помощью кнопки >. Можно поступить решительно и с помощью кнопика >> сгенерировать классы для всех интерфейсов без разбору. Обратите внимание на то, что в элементах Class и File мастер показывает имена классов и заголовочных файлов, которые он будет генерировать. Закончите работу по генерации объявлений классов нажатием кнопки Finish.
Замечание. Практически того же
результата мы бы смогли добиться и
другим путем, выбрав в окне радиокнопку
Add Class from: File, а не Registry, которая
выбрана по умолчанию. Далее в поле
Location с помощью диалога по открытию
файла мы должны были бы указать имя
файла Excel.exe
|
Рис. 1. Выбор библиотеки типов и интерфейсов
Шаг 4. Запуск сервера Excel.
Теперь модифицируем файл UseExcel.cpp, добавив в него код запуска Excel. Не забудьте в начало файла добавить, для начала, директиву подключения заголовочного файла CApplication.h, необходимого для запуска Excel, а также файлов comdef.h и conio.h. Кстати, вы наверное заметили на вкладке Solution Explorer в папке Header Files великое множество файлов, сгенерированных мастером.
// 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;
}
Закомментировать import
vbcmn98.chm – справка по ActiveX для Visual Basic с примерами кода.
C:\Program Files\Microsoft Office\OFFICE11\1049\VBA*.chm (VBAAC10.chm, VBAOF11.chm, VBAOWS10.chm)
Некоторые комментарии к программе.
В файле 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. Вот пример реализации одного из методов интерфейса _Application, который мы используем как метод объекта m_app:
LPDISPATCH _Application::GetDocuments()
{
LPDISPATCH result;
InvokeHelper(0x6, DISPATCH_PROPERTYGET, VT_DISPATCH, (void*)&result,
NULL);
return result;
}
Объявление этого метода содержится в файле 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, надо проделать такие операции:
Запустить на выполнение MS Word и включить запись макроса – Сервис/Макрос/Начать запись. В появившемся диалоговом окне можно изменить имя макроса и сферу его применения
Выполнить «вручную» те операции, которые необходимо запрограммировать. При этом возможно с помощью кнопок панели управления макроса приостановить или отменить его запись
После завершения всех операций остановить запись и открыть текст макроса, например, с помощью команды Сервис/Макрос/Редактор Visual Basic. Сгенерированный текст макроса можно использовать как шаблон для записи текста программы.
|
Рис. 2. Путь к разделу справки по программированию доступа к сервисам MSWord
