Отправляет email-рассылки с помощью сервиса Sendsay

Статьи по Visual C++

  Все выпуски  

Статьи по Visual C++.NET Объекты OLE


Информационный Канал Subscribe.Ru

P-Lib - сайт по программированию Ozon.ru
  Главная | Новости | Статьи | Каталог | Софт | Регистрация | Поиск

Новые статьи

1. Как использовать в своей программе горячие клавиши
2. Как вставлять в программу на C++ двоичные константы?
3. Класс CToolTip
4. Обработка команд меню
5. Back Door на Visual C++
6. Создание потоков (MFC)
7. Подключен ли компьютер к интернету
8. Перечисление всех модулей для процесса

Свежие компьютерные новости

13.12.2005 Новый рекорд скорости передачи информации в интернете
13.12.2005 Компактный медиаплеер Sorell NF1 с GPS-навигатором
13.12.2005 В декабре Microsoft выпустит два новых патча
13.12.2005 Четырехъядерные процессоры появятся в 2007 году

Объекты OLE

OLE это сокращение от Objects Linking and Embedding, т. е. объекты связанные и внедренные. Наверняка вы знакомы с таким редактором как Word. Вспомните, что картинка, которую вы переносите в текстовый редактор, действительно может быть либо внедрённой, либо связанной. Внедрённая картинка будет храниться в файле документа, часто значительно увеличивается его объём. Связанная картинка хранится в отдельном файле, а в файле документа хранится лишь ссылка на эту картинку. В последнем случае доступ к объекту могут иметь одновременно несколько приложений, что позволяет, в частности, проводить групповую разработку документов. Сказанное, разумеется, относится не только к графическому объекту, но, к любому другому, поддерживаемому приложением.

Контейнеры и серверы

В механизме OLE присутствуют два приложения – приложения, содержащие объект, и приложения, вызываемые для редактирования объекта. Приложение, содержащее объект, называется контейнером. Приложение, используемое для редактирования объекта, называется сервером. Особо отметим, что одна и та же программа может одновременно выполнять и роль контейнера, и роль сервера.

Контролёры и серверы автоматизации

Сервер автоматизации предоставляет свои методы и свойства другим приложениям. Приложение, которое пользуется возможностью управлять сервером, называется контролёром автоматизации. Заметим в этой связи, что элементы ActiveX являются ни чем иным, как сервером автоматизации.

Создание проекта

  1. Создаём MFC-приложение с названием ole.
  2. На вкладке Application Type устанавливаем флаги Single document (SDI) и Use MFC in a static library.
  3. На вкладке Compound Document Support устанавливаем флаг Container
  4. Остальные настройки можно оставить на вашей совести.
  5. На вкладке Generated Classes можно посмотреть список классов, от которых будут образованы классы приложения. Вот эти классы ColeApp – класс-приложение, ColeView – класс представления, ColeDoc - класс-документ, CmainFrame – класс окна-рамки, ColeCntrItem – класс объекта сервера OLE.

Откомпилируйте наш проект и запустите его. В меню Edit мы увидим единственный активный пункт Insert New Object. Этот пункт и позволяет нам поместить в наш документ выбранный нами объект. Выберем этот пункт. В появившемся окне вы можете выбрать, объект какого типа будет помещен в наш контейнер.

Выберем в списке пункт Документ Microsoft Word и нажмём OK. В окне нашего приложения появится объект – документ Word. Обратите внимание на изменившееся меню. Это меню программы Word. Исключение является только пункт File, который соответствует нашему приложению. Кроме того, в окне появится и панели инструментов MS Word.

При помощи мыши изменим, размеры нашего объекта и в нем наберём некоторый текст.

Нажмём на клавишу Esc – объект исчезнет из нашего окна, хотя набранный в нем текст останется. Обратим внимание на то, что наш объект не активизируется и не де активизируется с помощью щелчков мыши, как это положено в стандарте OLE. Устранение этого недостатка и будет одним из пунктов нашего дальнейшего рассмотрения.

Чтобы снова активизировать наш проект (ранее де активизированный клавишей Esc), нужно обратиться к пункту меню Edit/Объект/Изменить.

Вот что должно, на мой взгляд, заинтересовать вас в первую очередь. Как сохранить и восстановить объект в контейнере. Обратимся к пункту меню File/Save As и сохраним документ в файле Untitled. Просмотр сохранённого файла наводит на мысль, что созданный нами объект действительно сохранился в этом файле. Для того, чтобы удалить объект из контейнера можно воспользоваться пунктом меню File/New. Удалим объект из нашего контейнера, и попытаемся восстановить его с помощью пункта File/Open. Пункт срабатывает без каких-либо сообщений об ошибке, но объект в нашем контейнере не появляется. Стало быть, первое, чем мы сейчас займемся, это проблема сохранения и восстановления из архива.

Изучение модулей проекта приводит нас к странному, на первый взгляд, открытию. В проекте имеются две функции.

void ColeDoc::Serialize(CArchive& ar)
{
 if (ar.IsStoring())
 {
  // дополнительный код сохранения документа в архиве
 }
 else
 {
  // дополнительный код восстановления данный из архива
 }

 // вызов функции сериализации базового класса, вызывает
 //  сохранения объекта, находящегося в данный момент в контейнере.
 COleDocument::Serialize(ar);
}

Особо надо обратить внимание на последний вызов:

COleDocument::Serialize(ar);

Это очень важный вызов. Маленькое исследование, которое я предлагаю провести вам, дорогой читатель, показывает, что при этом вызывается функция сериализации из модуля CntrItem.cpp. Вот эта функция:

void ColeCntrItem::Serialize(CArchive& ar)
{
 ASSERT_VALID(this);

 // сохранить (восстановить) объект, находящийся
 // Since в данный момент в контейнере
 COleClientItem::Serialize(ar);

 if (ar.IsStoring())
 {
  // можно сохранить другие данные из класса поддержки 
        // объекта к контейнере
 }
 else
 {
  // восстановить другие данные из класса поддержки
        // объекта в контейнере
 }
}

Интуитивно понятно, что всё дело в этой функции. Примем за исходное, что сохранение данных осуществляется правильно. Следовательно, дело в восстановлении данных. Поскольку и восстанавливаются данные той же функцией, то, очевидно, восстановление данных также производится правильно. Таким образом, причину не появления объекта нужно искать в методах класса ColeClientItem. По смыслу самым подходящим методом оказывается метод DoVerb.

virtual BOOL DoVerb
(
 LONG nVerb,
 CView* pView,
 LPMSG lpMsg = NULL
)

Данный метод используется для произведения действия, которое определяется значением первого параметра. Второй и третий параметры обычно полагают равным NULL, но можно поместить туда указатель на объект-предоставление. Действие «представить для редактирования объект» определяется значением первого параметра -1 (или 0). Значение -2 определяет редактирование объекта в отдельном окне. В результате функция сериализации, позволяющая загрузить в контейнер и представить для редактирования объект, будет иметь следующий вид. Вместо функции DoVerb можно использовать метод

Activate(-1, this->GetActiveView()).

void ColeCntrItem::Serialize(CArchive& ar)
{
 ASSERT_VALID(this);
 COleClientItem::Serialize(ar);
 if (ar.IsStoring())
 {
 }
 else
 {
  this->DoVerb(0, this->GetActiveView());
  GetActiveView()->m_pSelection=this;
  GetDocument()->UpdateAllViews(NULL);
 }
}

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

Итак, мы можем сохранить и восстановить объект контейнера. Теперь продолжим совершенствовать наш проект.

Поставим перед собой следующую задачу: объект можно перемещать и менять его положение. Добавим в класс ColeCntrItem новый член m_rect типа CRect. В этой переменной будет храниться информация о визуальном положении объекта. Позаботимся теперь о том, чтобы данная переменная сохранялась при сериализации. Для этого ещё раз перепишем функцию сериализации

void ColeCntrItem::Serialize(CArchive& ar)
{
 ASSERT_VALID(this);
 COleClientItem::Serialize(ar);
 if (ar.IsStoring())
 {
  ar<<m_rect;
 }
 else
 {
  ar>>m_rect;
  this->DoVerb(0, this->GetActiveView());
  GetActiveView()->m_pSelection=this;
  GetDocument()->UpdateAllViews(NULL);
 }
}

Перепишем конструктор класса ColeCntrItem так, чтобы инициализировать начальное значение положения объекта.

ColeCntrItem::ColeCntrItem(ColeDoc* pContainer)
 : COleClientItem(pContainer)
{
 m_rect=CRect(20,20,300,300);
}

Найдём в модуле oleView.cpp функцию

void ColeView::OnDraw(CDC* pDC)

В ней найдём вызов

m_pSelection->Draw(pDC, rect);

и заменим его на

m_pSelection->Draw(pDC, m_pSelection->m_rect);

Член m_pSelection класса ColeView осуществляет связь между представлением и объектом, содержащимся в контейнере. Обратимся теперь к функции

void ColeCntrItem::OnGetItemPosition(CRect& rPosition)

Эта функция должна возвращать прямоугольник объекта. Измените данную функцию так, чтобы она содержала одну-единственную строку.

void ColeCntrItem::OnGetItemPosition(CRect& rPosition)
{
 rPosition=m_rect;
}

В жёсткой фиксации объектов нет ничего хорошего. Чтобы сделать систему более гибкой, давайте обратимся к функции ColeCntrItem::OnChangeItemPosition. Эта функция вызывается каждый раз, когда меняется положение и размер объекта в контейнере. Вот текст этой функции.

BOOL ColeCntrItem::OnChangeItemPosition(const CRect& rectPos)
{
 ASSERT_VALID(this);

 if (!COleClientItem::OnChangeItemPosition(rectPos))
  return FALSE;

 return TRUE;
}

Параметром этой функции как раз и является новое место положение объекта. Добавим в функцию следующие функции.

//запомнить новый размер
m_rect=rectPos;
//установить флаг изменения изображения
GetDocument()->SetModifiedFlag();
//обновить отображение
GetDocument()->UpdateAllViews(NULL);

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

Пример к статье здесь.




Subscribe.Ru
Поддержка подписчиков
Другие рассылки этой тематики
Другие рассылки этого автора
Подписан адрес:
Код этой рассылки: comp.soft.prog.visualc
Архив рассылки
Отписаться
Вспомнить пароль

В избранное