Общие вопросы, касающиеся миграции
Одной из задач проектирования для OLE 2 классов MFC 2,5 (и выше) было сохранить значительную часть той же архитектуре, ввести в действие в MFC 2.0 для поддержки OLE 1.0. В результате многие из те же OLE классы MFC 2.0 до сих пор существуют в этой версии MFC (COleDocument, COleServerDoc, COleClientItem, COleServerItem). Кроме того многие из API в этих классов точности совпадают. Однако OLE 2 настолько радикально отличается от OLE 1.0 вы можете ожидать, что некоторые из деталей изменились. Если вы знакомы с поддержкой MFC 2.0 текстом, вы будете чувствовать себя дома с 2.0 поддержки MFC.
Если вы принимаете существующее приложение MFC/текстом и добавление функциональности OLE 2.0, вам следует прочитать эту записку. Эта записка охватывает некоторые общие вопросы, вы можете столкнуться при портирование функциональность вашего текстом для MFC/OLE 2 и затем обсуждает проблемы, обнаруженные во время переноса двух приложений, включенных в MFC 2.0: образцы MFC OLE OCLIENT и HIERSVR.
Важное значение имеет архитектуру документ/представление MFC
Если приложение не использует архитектуру документ/представление MFC и вы хотите добавить в приложение OLE 2 поддержку, настало время перейти к документ/представление. Многие из преимуществ классов MFC OLE 2 реализуются только после того, как приложение использует встроенный архитектура и компоненты MFC.
Реализация сервера или контейнера без использования архитектуры MFC можно, но не рекомендуется.
Использование MFC осуществление вместо собственного
MFC «готовые осуществление» такие классы, как CToolBar, CStatusBarи CScrollView имеют встроенные специальные случае код для поддержки OLE 2. Таким образом если вы можете использовать эти классы в вашем приложении вы будете пользоваться в их усилия для ознакомления их OLE. Опять же есть возможность «roll своего собственного» классов здесь для этих целей, но не предлагается. Если вам нужно осуществить подобную функциональность, исходный код MFC является одним прекрасным для борьбы с некоторыми из тонкие точек OLE (особенно когда речь заходит о активации на месте).
Изучение образца кода MFC
Существует ряд образцов MFC, которые включают функциональность OLE. Каждый из этих приложений реализует OLE под другим углом:
В HIERSVR - означало главным образом для использования в качестве сервера приложений. Он был включен в MFC 2.0 как приложение MFC/текстом была портирована на MFC/OLE 2 и затем расширена таким образом, чтобы он реализует OLE возможностей, доступных в OLE 2.
OCLIENT - это автономный контейнер приложение, призваны продемонстрировать многие из функций OLE с точки зрения контейнера. Он был портирован от MFC 2.0 и затем расширена для поддержки многие из более передовых функций OLE, такие как форматы пользовательских буфера обмена и ссылки на встроенные элементы.
DRAWCLI - это приложение реализует поддержку контейнера OLE намного как OCLIENT делает, за исключением того, что он делает это в рамках существующей программы рисования объектно ориентированной. Она показывает вам, как вы могли бы реализации поддержки контейнера OLE и интегрировать его в существующее приложение.
SUPERPAD - это приложение, как штраф изолированного приложения, также является OLE-сервер. Поддержка сервера, которое он реализует это довольно минимализма. Особый интерес представляет, как он использует службы OLE буфера обмена для копирования данных в буфер обмена, но использует функциональность встроена в Windows «Правка» управления для реализации функциональности буфера обмена вставить. Это показывает интересное сочетание традиционного использования Windows API, а также интеграцию с новых интерфейсов OLE API.
Для получения дополнительной информации о примеры приложений справке «MFC образца».
Тематическое исследование: OCLIENT от MFC 2.0
Как обсуждалось выше, OCLIENT был включен в MFC 2.0 и осуществлены OLE с MFC/текстом. Шаги, в которых это приложение было первоначально преобразование использовать классы MFC/OLE 2 описаны ниже. Ряд функций были добавлены после завершения первоначальных порт чтобы лучше проиллюстрировать классы MFC/OLE. Эти возможности не будут охватываться здесь; обратитесь к образцу для получения дополнительной информации об этих дополнительных возможностей.
Примечание Ошибки компилятора и поэтапный процесс был создан в Visual C++ 2.0. Сообщения об ошибке и мест могли измениться с Visual C++ 4.0, однако Концептуальная информация остается в силе.
Получение деятельности и запуск
Подход к порт-Образец OCLIENT для MFC/OLE – начать строительство и фиксации ошибок очевидным компилятора, которые приведут. Если взять образец OCLIENT от MFC 2.0 и скомпилировать его в данной версии MFC, вы увидите, что есть не так много ошибок для разрешения. Ниже описываются ошибки в том порядке, в котором они выполнялись.
Исправить ошибки компиляции и
\oclient\mainview.cpp(104): Ошибка C2660: «Рисовать»: функция не принимает параметры 4
Первая ошибка касается COleClientItem::Draw. В MFC/текстом потребовалось больше параметров, чем версия MFC/OLE принимает. Дополнительные параметры часто не были необходимыми и обычно NULL (как в этом примере). Эта версия MFC автоматически определяет значения для lpWBounds когда CDC, которая обращается на метафайл DC. Кроме того параметр pFormatDC уже не необходимым так как рамки будут строить один из «атрибута DC» pDC, в. Поэтому для устранения этой проблемы, просто удалить два дополнительных NULL параметров на призыв вничью.
\oclient\mainview.cpp(273): ошибка C2065: «OLE_MAXNAMESIZE»: необъявленный идентификатор
\oclient\mainview.cpp(273): ошибка C2057: ожидается, что константное выражение
\oclient\mainview.cpp(280): ошибка Ошибка C2664: «CreateLinkFromClipboard»: невозможно преобразовать параметр 1 от 'char [1]' ' enum:: tagOLERENDER '
\oclient\mainview.cpp(286): ошибка Ошибка C2664: «CreateFromClipboard»: невозможно преобразовать параметр 1 от 'char [1]' ' enum:: tagOLERENDER '
\oclient\mainview.cpp(288): ошибка Ошибка C2664: «CreateStaticFromClipboard»: невозможно преобразовать параметр 1 от 'char [1]' ' enum:: tagOLERENDER '
Выше ошибки в результате того факта, что все функции COleClientItem::CreateXXXX в MFC/текстом требуется уникальное имя передано для представления элемента. Это требование в базовых OLE API. Это нет необходимости в MFC/OLE 2, так как OLE 2.0 не использовать DDE как основной механизм коммуникации (имя используется в беседах DDE). Чтобы исправить эту проблему, удалите функцию CreateNewName , а также все ссылки на него. Это легко выяснить то, что каждая функция MFC/OLE ожидает в этой версии, просто, поместив курсор на вызов и нажав F1.
Еще одна область, которая значительно отличается — OLE 2 Обработка буфера обмена. С текстом вы использовали в буфер обмена Windows API-интерфейсы взаимодействуют с буфером обмена. С OLE 2 это делается с другой механизм. API-интерфейсов MFC/текстом предположить, что буфера обмена был открыт до копирования объекта COleClientItem в буфер обмена. Это более не является необходимым и приведет к сбою операций буфер обмена MFC/OLE. Во время редактирования кода для удаления зависимостей на CreateNewName, следует удалить код, который открывает и закрывает в буфер обмена Windows.
\oclient\mainview.cpp(332): ошибка C2065: «AfxOleInsertDialog»: необъявленный идентификатор
\oclient\mainview.cpp(332): ошибка C2064: термин не вычисляет функции
\oclient\mainview.cpp(344): ошибка C2057: ожидается, что константное выражение
\oclient\mainview.cpp(347): ошибка C2039: «CreateNewObject»: не является членом «CRectItem»
Эти ошибки в результате обработчика CMainView::OnInsertObject . Обработка команды «Вставить объект» является еще одной областью, где вещи изменились совсем немного. В этом случае проще просто объединить первоначальную с предоставляемой AppWizard для нового приложения OLE-контейнера. В самом деле это метод, который можно применить для переноса других приложений. В MFC/текстом отображается диалоговое окно «Вставить объект» путем вызова функции AfxOleInsertDialog . В этой версии вы создать объект диалогового окна COleInsertObject и вызов DoModal. Кроме того создаются новые элементы OLE с CLSID вместо того, чтобы строки classname. Конечный результат должен выглядеть примерно так
COleInsertDialog dlg;
Если (dlg.DoModal()! = IDOK)
nbsp; возвращение;
BeginWaitCursor();
CRectItem * pItem = NULL;
ПОПРОБУЙТЕ
{
/ / Сначала создать объект C++
pItem = GetDocument() - > CreateItem();
ASSERT_VALID(pItem);
/ / Инициализировать элемент данных диалогового окна.
Если (! dlg.CreateItem(pItem))
AfxThrowMemoryException();
/ / будет делать любое исключение
ASSERT_VALID(pItem);
/ / выполнить объект при необходимости
Если (dlg.GetSelectionType() == COleInsertDialog::createNewItem)
pItem - > DoVerb(OLEIVERB_SHOW, this);
/ / обновление прямо сейчас
pItem - > UpdateLink();
pItem - > UpdateItemRectFromServer();
/ / Выбор только что вставленного элемента
SetSelection(pItem);
pItem - > Invalidate();
}
УЛОВ (CException, e)
{/ / Очистка элемента
Если (pItem! = NULL)
GetDocument() - > DeleteItem(pItem);
AfxMessageBox(IDP_FAILED_TO_CREATE);
}
END_CATCH
EndWaitCursor()
Примечание Вставить новый объект может отличаться для вашего приложения):
Необходимо также включить lt;afxodlgs.h > который содержит объявление для класса диалогового окна COleInsertObject , а также другие стандартные диалоги, предоставляемые MFC.
\oclient\mainview.cpp(367): ошибка C2065: «OLEVERB_PRIMARY»: необъявленный идентификатор
\oclient\mainview.cpp(367): Ошибка C2660: «DoVerb»: функция не принимать 1 параметры
Эти ошибки вызваны тем, что некоторые константы текстом изменились в OLE 2, несмотря на то, что в концепции они одинаковы. В этом случае OLEVERB_PRIMARY был изменен на OLEIVERB_PRIMARY. В текстом и OLE 2 Основная команда обычно выполняется контейнером когда пользователь дважды щелкает элемент.
Кроме того, DoVerb теперь принимает дополнительный параметр — указатель на представление (CView*). Этот параметр используется только для реализации «Визуального редактирования» (или активации на месте). На данный момент этого параметра установлено значение NULL, так как вы не реализуется эта функция в настоящее время.
Чтобы убедиться, что рамки никогда не попытки на месте активировать, то следует переопределить COleClientItem::CanActivate следующим
BOOL CRectItem::Ca&nActivate()
{
nbsp; вернуть значение FALSE;
}
\oclient\rectitem.cpp(53): ошибка C2065: «GetBounds»: необъявленный идентификатор
\oclient\rectitem.cpp(53): ошибка C2064: термин не вычисляет функции
\oclient\rectitem.cpp(84): ошибка C2065: «SetBounds»: необъявленный идентификатор
\oclient\rectitem.cpp(84): ошибка C2064: термин не вычисляет функции
В MFC/текстом COleClientItem::GetBounds и SetBounds были использованы для запроса и манипулировать степени элемента ( левой и верхней члены всегда были ноль). В MFC/OLE 2 это более непосредственно поддерживается COleClientItem::GetExtent и SetExtent, которые касаются размера или CSize вместо.
Код для вашего нового SetItemRectToServer и UpdateItemRectFromServer вызовы выглядеть следующим образом:
BOOL CRectItem::UpdateItemRectFromServer()
{
nbsp; Assert(m_bTrackServerSize);
Размер CSize;
Если (!.GetExtent(&size))
вернуть значение FALSE; / / пустой
/ / Карта от HIMETRIC в координатах экрана
{
CClientDC screenDC(NULL);
screenDC.SetMapMode(MM_HIMETRIC);
screenDC.LPtoDP(&size);
}
/ / просто установить размер элемента
Если (m_rect.Size()! = размер)
{
/ / аннулировать старый размер/должность
Invalidate();
m_rect.Right = m_rect.left + size.cx;
m_rect.Bottom = m_rect.top + size.cy;
/ /, а также новый размер/положение
Invalidate();
}
Возвращает значение TRUE;
}
BOOL CRectItem::SetItemRectToServer()
{
/ / установить официальные границы для встроенного элемента
Размер CSize = m_rect.Size();
{
CClientDC screenDC(NULL);
screenDC.SetMapMode(MM_HIMETRIC);
screenDC.DPtoLP(&size);
}
ПОПРОБУЙТЕ
{
SetExtent(size); / / может сделать время ожидания
}
УЛОВ (CException, e)
{
вернуть значение FALSE; / / ссылки не допустит SetBounds
}
END_CATCH
Возвращает значение TRUE;
}
\oclient\frame.cpp(50): ошибка C2039: «InWaitForRelease»: не является членом «COleClientItem»
\oclient\frame.cpp(50): ошибка C2065: «InWaitForRelease»: необъявленный идентификатор
\oclient\frame.cpp(50): ошибка C2064: термин не вычисляет функции
В MFC/текстом синхронные вызовы API из контейнера на сервере были имитируемой, так как текстом была по своей сути асинхронные во многих случаях. Необходимо проверить наличие выдающийся асинхронного вызова выполняется перед обработкой команд от пользователя. MFC/текстом предоставляет функцию COleClientItem::InWaitForRelease для этого. В MFC/OLE 2 это не является необходимым, так что вы можете удалить переопределение метода OnCommand в CMainFrame все вместе.
На данный момент OCLIENT компиляции и привязки.
Другие необходимые изменения
Есть несколько вещей, которые не сделали, что будет препятствовать OCLIENT запуску, однако. Это лучше исправить эти проблемы теперь вместо позже.
Прежде всего необходимо инициализировать библиотеки OLE. Это делается путем вызова AfxOleInit из InitInstance:
если (!.AfxOleInit())
{
AfxMessageBox («ошибка инициализации библиотеки OLE");
вернуть значение FALSE;
}
Это также хорошая идея проверить для виртуальных функций для изменения списка параметров. Одной из таких функций является COleClientItem::OnChange, переопределен в каждом контейнерном приложении MFC/OLE. Глядя на интерактивной справки, вы увидите, что дополнительные «DWORD dwParam» был добавлен. Новый CRectItem::OnChange выглядит следующим образом
void CRectItem::OnChange (OLE_NOTIFICATION wNotification, dwParam типа DWORD)
{
Если (m_bTrackServerSize amp; и
!UpdateItemRectFromServer())
{
/ / Пустой объект
Если (wNotification == OLE_CLOSED)
{
/ / нет данных, полученных для объекта - уничтожить его
УТВЕРЖДАТЬ (!.IsVisible());
GetDocument() - > DeleteItem(this);
возвращение; / / обновление не (пункт теряется в настоящее время)
}
}
Если (wNotification! = OLE_CLOSED)
Dirty();
Invalidate(); / / любое изменение приведет к перевыписки
}
В MFC/текстом контейнер приложения производным от COleClientDocкласса документа. В MFC/OLE 2 этот класс были сняты и заменены COleDocument (этой новой Организации упрощает создание контейнера/сервер приложений). Существует # define сопоставляемый COleClientDoc COleDocument упростить портирование приложений MFC/текстом MFC/OLE 2, такие как OCLIENT. Одна из особенностей, не предоставляемые COleDocument , которая была предоставлена COleClientDoc является стандартной команды сообщение записей карты. Это делается таким образом, чтобы серверные приложения, использующие также COleDocument (косвенно), не носить с собой накладные расходы этих обработчиков команд если они не являются контейнера/серверное приложение. Таким образом вам необходимо добавить следующие записи в схеме сообщений CMainDoc:
ON_UPDATE_COMMAND_UI (ID_EDIT_PASTE, OnUpdatePasteMenu)
ON_UPDATE_COMMAND_UI (ID_EDIT_PASTE_LINK, OnUpdatePasteLinkMenu)
ON_UPDATE_COMMAND_UI (ID_OLE_EDIT_LINKS, OnUpdateEditLinksMenu)
ON_COMMAND (ID_OLE_EDIT_LINKS, COleDocument::OnEditLinks)
ON_UPDATE_COMMAND_UI (ID_OLE_VERB_FIRST, OnUpdateObjectVerbMenu)
ON_UPDATE_COMMAND_UI (ID_OLE_EDIT_CONVERT, OnUpdateObjectVerbMenu)
ON_COMMAND (ID_OLE_EDIT_CONVERT, OnEditConvert)
Все эти команды осуществляется в COleDocument, который является базовым классом для документа.
На данный момент OCLIENT представляет собой функциональное приложение контейнера OLE. Возможна вставка элементов любого типа (текстом или OLE 2). Так как необходимый код для включения активации на месте не реализован, редактировать элементы в отдельном окне, подобно с текстом. В следующем разделе рассматриваются необходимые изменения для того, чтобы редактирования на месте (иногда называемый "Визуального редактирования").
Добавление «Визуального редактирования»
Одна из наиболее интересных особенностей OLE является активация на месте (или «Визуального редактирования»). Эта возможность позволяет серверному приложению взять на себя часть контейнера пользовательского интерфейса для пользователя обеспечить более плавный интерфейс редактирования. Для выполнения активации на месте для OCLIENT, некоторые специальные ресурсы должны быть добавлены, а также дополнительный код. AppWizard обычно предоставляет эти ресурсы и код — в самом деле, большая часть кода здесь было заимствовано непосредственно из свежих AppWizard приложения с поддержкой «Контейнер».
Прежде всего необходимо добавить ресурс меню для использования, когда есть элемент, который активен на месте. Дополнительное меню ресурс можно создать в Visual C++, скопировав IDR_OCLITYPE ресурсов и удаления всех кроме файла и окна всплывающие окна. Два разделители будут вставлены между файла и окна всплывающих окон для обозначения разделения групп (он должен выглядеть следующим образом: файл || Окно). Для получения дополнительной информации о что значат эти разделители и способ слияния меню сервера и контейнера увидеть «Меню и ресурсов: слияние меню» в Классах OLE 2.
После того, как у вас есть эти меню, созданные, вам нужно позволить рамки знают о них. Это делается путем вызова CDocTemplate::SetContainerInfo для шаблона документа, прежде чем добавить его в список шаблонов документов в вашем InitInstance. Новый код для регистрации шаблона документа выглядит следующим образом
CDocTemplate * pTemplate = (CMultiDocTemplate) новый
nbsp; IDR_OLECLITYPE,
RUNTIME_CLASS(CMainDoc),
RUNTIME_CLASS(CMDIChildWnd), / / стандарт MDI дочернего фрейма
RUNTIME_CLASS(CMainView));
pTemplate - > SetContainerInfo(IDR_OLECLITYPE_INPLACE);
AddDocTemplate(pTemplate)
Ресурс IDR_OLECLITYPE_INPLACE — специальных ресурсов на месте, созданный в Visual C++.
Для того чтобы активации на месте, есть некоторые вещи, которые необходимо изменить в CView (CMainView) производного класса, а также COleClientItem производного класса (CRectItem). Все из этих переопределений предоставляются AppWizard и большая часть осуществления будет поступать непосредственно из приложения по умолчанию AppWizard.
На первом шаге этого порта активации на месте была отключена полностью переопределения COleClientItem::CanActivate. Чтобы разрешить активацию на месте следует удалить это переопределение. Кроме того значение NULL передается все вызовы DoVerb (есть два из них) потому, что предоставление мнение необходимо только для активации на месте. Для полного осуществления активации на месте, необходимо передать правильное представление в вызове DoVerb . Один из этих вызовов находится в CMainView::OnInsertObject
pItem-> DoVerb(OLEIVERB_SHOW, this)
Другой — в CMainView::OnLButtonDblClk
m_pSelection-> DoVerb(OLEIVERB_PRIMARY, this)
Необходимо переопределить COleClientItem::OnGetItemPosition. Это сообщает серверу, куда положить его окно относительно контейнера окна, когда элемент активирован в месте. Для OCLIENT осуществление является тривиальным
void CRectItem::OnGetItemPosition (CRect& rPosition)
{
rPosition = m_rect;
}
Большинство серверов также реализовать то, что называется «на месте изменение размера.» Это позволяет окно сервера для калибровки и переехал в то время как пользователь редактирует элемент. Контейнер должны участвовать в этой акции, так как перемещение или изменение размера окна обычно влияет на позицию и размер в самом документе контейнера. Осуществление OCLIENT синхронизирует внутренний прямоугольник, поддерживаемый m_rect с новой позиции и размера.
BOOL CRectItem::OnChangeItemPosition(const CRectamp; rectPos)
{
ASSERT_VALID(this);
Если (!.COleClientItem::OnChangeItemPosition(rectPos))
вернуть значение FALSE;
Invalidate();
m_rect = rectPos;
Invalidate();
GetDocument() - > SetModifiedFlag();
Возвращает значение TRUE;
}
На данный момент достаточно код чтобы позволить элемента быть активированы на месте и решать изменение размера и перемещение элемента, когда он активен, но нет никакого кода, который позволит пользователю для выхода из сеанса редактирования. Хотя некоторые серверы будут эта функциональность самих путем обработки клавишу escape, предполагается, что контейнеры предоставляют два способа для отключения элемента: (1), нажав кнопку вне данного пункта и (2), нажав клавишу escape.
Побег ключ добавить ускоритель с Visual C++, которая сопоставляет клавиша VK_ESCAPE к команде, ID_CANCEL_EDIT добавляется к ресурсам. Обработчик для этой команды следует:
/ / Следующие обработчик команд обеспечивает стандарт
/ / Клавиатура Пользовательский интерфейс для отмены на месте
/ / Редактирование session.void CMainView::OnCancelEdit()
{
nbsp; / / Закрыть любой активный элемент на месте на этом представлении.
COleClientItem * pActiveItem = GetDocument() - > GetInPlaceActiveItem(this);
Если (pActiveItem! = NULL)
pActiveItem - > Close();
Assert(GetDocument()-> GetInPlaceActiveItem(this) == NULL);
}
Для обработки в случае, когда пользователь щелкает за пределами элемента, добавляется следующий код в начале CMainView::SetSelection
если (pNewSel! = m_pSelection || pNewSel == NULL)
{
nbsp; COleClientItem * pActiveItem = GetDocument() - > GetInPlaceActiveItem(this);
Если (pActiveItem! = NULL & & pActiveItem! = pNewSel)
pActiveItem - > Close();
}
& nbsp
Когда элемент активен на месте, он должен иметь фокус. Чтобы убедиться, что это так вы обрабатывать OnSetFocus таким образом, чтобы фокус переводится всегда активного элемента когда ваше мнение получает фокус:
/ / Не требуется специальной обработки OnSetFocus и OnSize / / когда объект редактируется на месте.
void CMainView::OnSetFocus (CWnd * pOldWnd)
{
nbsp; COleClientItem * pActiveItem = GetDocument() - > GetInPlaceActiveItem(this);
Если (pActiveItem! = NULL & &
pActiveItem - > GetItemState() == COleClientItem::activeUIState)
{
/ / необходимо установить фокус на этот элемент, если это же мнение
CWnd * pWnd = pActiveItem - > GetInPlaceWindow();
Если (pWnd! = NULL)
{
pWnd - > SetFocus(); / / не вызывают базовый класс
возвращение;
}
}
CView::OnSetFocus(pOldWnd);
}
При изменении размера мнение, вам необходимо уведомить активный элемент, который был изменен прямоугольник отсечения. Для этого Вам предоставить обработчик OnSize:
void CMainView::OnSize (UINT nType, int cx, int cy)
{
nbsp; CView::OnSize (nType, cx, cy);
COleClientItem * pActiveItem = GetDocument() - > GetInPlaceActiveItem(this);
Если (pActiveItem! = NULL)
pActiveItem - > SetItemRects();
}
Тематическое исследование: HIERSVR от MFC 2.0
HIERSVR был также включен в MFC 2.0 и реализации OLE с MFC/текстом. В настоящей записке кратко описывает шаги, которые это приложение первоначально было преобразовано в использовать классы MFC/OLE 2. Ряд функций были добавлены после завершения первоначальных порт чтобы лучше проиллюстрировать классы MFC/OLE 2. Эти возможности не будут охватываться здесь; обратитесь к образцу для получения дополнительной информации об этих дополнительных возможностей.
Примечание Ошибки компилятора и поэтапный процесс был создан в Visual C++ 2.0. Сообщения об ошибке и мест могли измениться с Visual C++ 4.0, однако Концептуальная информация остается в силе.
Получение деятельности и запуск
Подход к порту образца HIERSVR для MFC/OLE – начать строительство и фиксации ошибок очевидным компилятора, которые приведут. Если взять Образец HIERSVR от MFC 2.0 и скомпилировать его в данной версии MFC, вы увидите, что есть не много ошибок для разрешения (хотя есть более чем с Образец OCLIENT). Ниже описываются ошибки в том порядке, в котором они обычно происходят.
Исправить ошибки компиляции и
\hiersvr\hiersvr.cpp(83): ошибка C2039: «RunEmbedded»: не является членом «COleTemplateServer»
Эта первая ошибка указывает более серьезной проблемы с функции InitInstance для серверов. Инициализации, необходимые для OLE-сервера вероятно является одним из крупнейших изменений, которые вам придется сделать приложение MFC/текстом для того чтобы получить его работы. Лучше всего сделать это посмотреть на AppWizard создает для OLE-сервера и изменить код, в случае необходимости. Вот некоторые моменты следует помнить:
Это необходимо для инициализации библиотеки OLE путем вызова AfxOleInit
Звоните SetServerInfo на объекте шаблон документа для задания дескрипторов ресурсов сервера и среды выполнения класса сведения, которые нельзя установить с помощью конструктора CDocTemplate.
Не показывать главное окно вашего приложения, если /Embedding присутствует в командной строке.
Вам понадобится идентификатор GUID для вашего документа. Это уникальный идентификатор для типа вашего документа (128 бит). AppWizard создаст для вас, так что если вы используете техника здесь копирования новый код от нового созданного AppWizard серверного приложения, вы можете просто «украсть» GUID из этого приложения. Если нет, то вы можете использовать GUIDGEN.EXE утилиты в каталоге BIN.
Это необходимо для «подключения» объекта COleTemplateServer к шаблон документа путем вызова COleTemplateServer::ConnectTemplate.
Обновление системного реестра, когда ваше приложение запускается отдельный. Таким образом, если пользователь перемещается.EXE для вашего приложения, запуская его из нового местоположения обновит базу данных регистрации системы Windows на новом месте.
После применения все эти изменения, основанные на AppWizard создает для InitInstance, InitInstance (и связанных с ними GUID) для HIERSVR следует читать:
// this is the GUID for HIERSVR documents
static const GUID BASED_CODE clsid =
{ 0xA0A16360L, 0xC19B, 0x101A, { 0x8C, 0xE5, 0x00, 0xDD, 0x01, 0x11, 0x3F, 0x12 } };
/////////////////////////////////////////////////////////////////////////////
// COLEServerApp initialization
BOOL COLEServerApp::InitInstance()
{
// OLE 2 initialization
if (!AfxOleInit())
{
AfxMessageBox("Initialization of the OLE failed!");
return FALSE;
}
// Standard initialization
LoadStdProfileSettings(); // Load standard INI file options
// Register document templates
CDocTemplate* pDocTemplate;
pDocTemplate = new CMultiDocTemplate(IDR_HIERSVRTYPE,
RUNTIME_CLASS(CServerDoc),
RUNTIME_CLASS(CMDIChildWnd),
RUNTIME_CLASS(CServerView));
pDocTemplate->SetServerInfo(IDR_HIERSVRTYPE_SRVR_EMB);
AddDocTemplate(pDocTemplate);
// create main MDI Frame window
CMainFrame* pMainFrame = new CMainFrame;
if (!pMainFrame->LoadFrame(IDR_MAINFRAME))
return FALSE;
m_pMainWnd = pMainFrame;
SetDialogBkColor(); // gray look
// enable file manager drag/drop and DDE Execute open
m_pMainWnd->DragAcceptFiles();
EnableShellOpen();
m_server.ConnectTemplate(clsid, pDocTemplate, FALSE);
COleTemplateServer::RegisterAll();
// try to launch as an OLE server
if (RunEmbedded())
{
// "short-circuit" initialization -- run as server!
return TRUE;
}
m_server.UpdateRegistry();
RegisterShellFileTypes();
// not run as OLE server, so show the main window
if (m_lpCmdLine[0] == '\0')
{
// create a new (empty) document
OnFileNew();
}
else
{
// open an existing document
OpenDocumentFile(m_lpCmdLine);
}
pMainFrame->ShowWindow(m_nCmdShow);
pMainFrame->UpdateWindow();
return TRUE;
}
Вы заметите, что приведенный выше код ссылается на новый Идентификатор ресурса, IDR_HIERSVRTYPE_SRVR_EMB. Это ресурс меню для использования при редактировании документа, который внедрен в другой контейнер. В MFC/текстом пункты меню для редактирования внедренного элемента были изменены на лету. С помощью структуры совершенно разные меню при редактировании внедренного элемента вместо того, чтобы редактирование документа на основе файла делает его намного проще для предоставления различных пользовательских интерфейсов для этих двух отдельных режимов. Как вы увидите далее, совершенно отдельное меню ресурс используется при редактировании внедренного объекта на месте.
Чтобы создать этот ресурс, загрузки сценария ресурсов в Visual C++ и скопируйте существующий ресурс меню IDR_HIERSVRTYPE. Переименуйте новый ресурс в IDR_HIERSVRTYPE_SRVR_EMB (это же именования, который использует AppWizard). Затем измените «Сохранение файла» на «Обновление файла»; Дайте ему Идентификатор команды ID_FILE_UPDATE. Также измените «Файл, сохранить как» «Файл сохранить копию как»; Дайте ему Идентификатор команды ID_FILE_SAVE_COPY_AS. Рамки обеспечивают осуществление обоих из этих команд.
\hiersvr\svritem.h(60): ошибка C2433: «OLESTATUS»: «виртуального» не разрешено для объявления данных
\hiersvr\svritem.h(60): ошибка C2501: «OLESTATUS»: отсутствует decl спецификаторы
\hiersvr\svritem.h(60): ошибка C2146: синтаксическая ошибка: отсутствует «;» перед идентификатором «OnSetData»
\hiersvr\svritem.h(60): ошибка C2061: синтаксическая ошибка: идентификатор «OLECLIPFORMAT»
\hiersvr\svritem.h(60): ошибка C2501: «OnSetData»: отсутствует decl спецификаторы
Существует ряд ошибок, обусловленных переопределения OnSetData, так как он имеет в виду OLESTATUS типа. OLESTATUS образом, текстом возвращает ошибки. Это изменено на HRESULT в OLE 2, хотя MFC обычно преобразует значение HRESULT в COleException , содержащий ошибку. В данном конкретном случае переопределения OnSetData нет необходимости, поэтому проще всего сделать это удалить его.
\hiersvr\svritem.cpp(30): Ошибка C2660: «COleServerItem::COleServerItem»: функция не принимать 1 параметры
COleServerItem конструктор принимает дополнительный параметр 'BOOL'. Этот флаг определяет, как управление памятью осуществляется на COleServerItem объектов. Установив его равным TRUE, framework обрабатывает управление памятью этих объектов — удалять их, когда они больше не нужны. HIERSVR использует CServerItem (производное от COleServerItem) объекты в рамках своих собственных данных, поэтому вы будете флаг этот значение FALSE. Это позволяет определить, когда удаляется каждый элемент сервера HIERSVR.
\hiersvr\svritem.cpp(44): Ошибка C2259: «CServerItem»: недопустимая попытка создать экземпляр абстрактного класса
\hiersvr\svritem.cpp(44): Ошибка C2259: «CServerItem»: недопустимая попытка создать экземпляр абстрактного класса
Поскольку эти ошибки означают, есть некоторые «чистых виртуальных» функции, которые не были переопределены в CServerItem. Скорее всего это связано с тем, что был изменен список параметров OnDraw на. Чтобы устранить эту ошибку, измените CServerItem::OnDraw так (а также Декларация в svritem.h)
BOOL CServerItem::OnDraw(CDC* pDC, CSizeamp; rSize)
{
/ / запрос от OLE использовать узел
pDC - > SetMapMode(MM_TEXT); / / всегда в пикселях
возвращение DoDraw (pDC, CPoint(0,0), FALSE);
}
Новый параметр — «rSize». Это позволяет заполнить размер рисунка, если это удобно. Этот размер должен быть в HIMETRIC. В этом случае это не удобно заполнить это значение в, поэтому вызывается метод OnGetExtent для получения степени. Для того чтобы работать вы будете иметь для осуществления OnGetExtent:
BOOL CServerItem::OnGetExtent(DV&ASPECT dwDrawAspect, CSizeamp; rSize)
{
Если (dwDrawAspect! = DVASPECT_CONTENT)
возвращение COleServerItem::OnGetExtent (dwDrawAspect, rSize);
rSize = CalcNodeSize();
Возвращает значение TRUE;
}
\hiersvr\svritem.cpp(104): ошибка C2065: «m_rectBounds»: необъявленный идентификатор
\hiersvr\svritem.cpp(104): ошибка C2228: выражение слева от ".SetRect' должен иметь тип класса/структуры/объединения
\hiersvr\svritem.cpp(106): ошибка Ошибка C2664: ' void __pascal __far DPtoLP (struct:: tagPOINT __far *, int) __far const ': не удается преобразовать параметр 1 от «int __far *' для ' struct:: tagPOINT __far *'
В CServerItem::CalcNodeSize функция размер элемента преобразуется в HIMETRIC и в m_rectBounds. Член незарегистрированной 'm_rectBounds' COleServerItem не существует (это было частично заменены m_sizeExtent, но в OLE 2 этот член имеет немного другой использование чем m_rectBounds сделал в текстом). Вместо того, чтобы задавать размер HIMETRIC в этой переменной-члена, вы будете вернуть его. Это возвращаемое значение используется в OnGetExtent, Реализовано ранее.
CSize CServerItem::CalcNodeSize()
{
nbsp; CClientDC dcScreen(NULL);
m_sizeNode = dcScreen.GetTextExtent (m_strDescription,
m_strDescription.GetLength());
m_sizeNode += CSize (CX_INSET * 2, CY_INSET * 2);
/ / установить предлагаемый размер HIMETRIC
Размер CSize (m_sizeNode.cx, m_sizeNode.cy);
dcScreen.SetMapMode(MM_HIMETRIC);
dcScreen.DPtoLP(&size);
Возвращает размер;
}
CServerItem также переопределяет COleServerItem::OnGetTextData. Эта функция является устаревшим в MFC/OLE и заменяется другой механизм. MFC 3.0 версия образца MFC OLE HIERSVR реализует эту функцию путем переопределения COleServerItem::OnRenderFileData. Эта функциональность не важен для этого базового порта, так что вы можете удалить OnGetTextData переопределения.
Существует много больше ошибок в svritem.cpp, которые еще не были рассмотрены. Они не являются «Реал» ошибки — только ошибки, вызванные предыдущие ошибки.
\hiersvr\svrview.cpp(325): Ошибка C2660: «CopyToClipboard»: функция не принимать 2 параметры
COleServerItem::CopyToClipboard больше не поддерживает флаг 'bIncludeNative'. Собственные данные (данные, написанная функцию Serialize элемента сервера) всегда копируется, поэтому удалить первый параметр. Кроме того CopyToClipboard будет создано исключение, когда ошибка происходит вместо того, чтобы возвращение ложь. Измените код следующим образом для CServerView::OnEditCopy
void CServerView::OnEditCopy()
{
nbsp; Если (m_pSelectedNode == NULL)
AfxThrowNotSupportedException();
ПОПРОБУЙТЕ
{
m_pSelectedNode - > CopyToClipboard(TRUE);
}
CATCH_ALL(e)
{
AfxMessageBox ("Копировать в буфер обмена ошибка");
}
END_CATCH_ALL}
Хотя больше ошибок, обусловленных компиляции версии MFC 2.0 HIERSVR чем для той же версии OCLIENT, было на самом деле меньше изменений.
На данный момент HIERSVR будет компилировать и связать и функционировать как OLE-сервер, но без функцию редактирования на месте, которая будет осуществляться следующая.
Добавление «Визуального редактирования»
Чтобы добавить этот серверное приложение «Визуального редактирования» (или активации на месте), существует лишь несколько вещей вы должны заботиться о:
Ресурс меню можно легко создать. Запустите Visual C++, копировать меню ресурсов IDR_HIERSVRTYPE в меню ресурс под названием IDR_HIERSVRTYPE_SRVR_IP. Измените меню так, чтобы остались только меню всплывающие Edit и помощь. Добавить два разделителя в меню между меню Edit и Справка (он должен выглядеть следующим образом: Редактирование || Справка). Для получения дополнительных сведений о что значат эти разделители и способ слияния меню сервера и контейнера см «Меню и ресурсов: слияние меню» в Классах OLE 2.
Точечного рисунка для панели инструментов, подмножество могут быть легко созданы путем копирования одной из свежего AppWizard созданного приложения с «Сервер» вариант проверен. Этот рисунок можно затем импортировать в Visual C++. Не забудьте дать точечного ID IDR_HIERSVRTYPE_SRVR_IP.
Класс, производный от COleIPFrameWnd могут быть скопированы из AppWizard созданного приложения с поддержкой сервера. Скопируйте оба файла, IPFRAME.НПК и IPFRAME.H и добавить их в проект. Убедитесь, что вызов LoadBitmap относится к IDR_HIERSVRTYPE_SRVR_IP, точечный рисунок, созданный на предыдущем шаге.
Теперь, когда все новых ресурсов и классы создаются, добавьте необходимый код, чтобы рамки знает об этих (и знает, что это приложение теперь поддерживает на месте). Это делается путем добавления некоторых больше параметров для SetServerInfo вызывается в функции InitInstance:
pDocTemplate->SetServerInfo (IDR_HIERSVRTYPE_SRVR_EMB,
IDR_HIERSVRTYPE_SRVR_IP, RUNTIME_CLASS(CInPlaceFrame))
Теперь готов для запуска на месте в любом контейнере, который также поддерживает активацию на месте. Но есть одна небольшая ошибка по-прежнему скрытую в коде. В HIERSVR поддерживает контекстное меню, отображаемое, когда пользователь нажимает правую кнопку мыши. Это меню работает когда HIERSVR полностью открыта, но не работает при редактировании вложения на месте. Причина может быть возлагали эту одну строку кода в CServerView::OnRButtonDown
pMenu-gt;TrackPopupMenu(TPM_CENTERALIGN | TPM_RIGHTBUTTON,
Point.x, point.y, AfxGetApp() - > m_pMainWnd)
Обратите внимание, ссылка на (AfxGetApp)-gt; m_pMainWnd. Когда сервер находится в недрах активирован, он имеет главное окно и m_pMainWnd установлен, но обычно он невидим. Кроме того это окно относится к главного окна приложения, MDI фрейм окна, которое появляется, когда сервер является полностью открытым или запустить отдельный. Это относится не к активной рамки окна, когда на месте активируется это фрейм окна, производным от COleIPFrameWnd. Для получения правильного активного окна, даже когда на месте редактирования, эта версия MFC добавляет новую функцию, AfxGetMainWnd. Как правило, следует использовать эту функцию вместо AfxGetApp() - > m_pMainWnd. Этот код нужно изменить следующим образом:
pMenu-gt;TrackPopupMenu(TPM_CENTERALI&GN | TPM_RIGHTBUTTON,
Point.x, point.y, AfxGetMainWnd())
Теперь у вас есть минимально включена для функционального активации на месте OLE-сервер. Но есть еще много функций, доступных с 2 MFC/OLE, которые не были доступны в MFC/текстом. Увидеть образца HIERSVR больше идей на компоненты, которые вы можете осуществить. Ниже перечислены некоторые из особенностей, которые реализует HIERSVR:
Образец HIERSVR в MFC 3.0 также использует несколько иной дизайн для своих элементов сервера. Это помогает сохранить память и ваши ссылки более гибким. С версии 2.0 HIERSVR каждый узел в дереве is-a COleServerItem. COleServerItem имеет немного больше нагрузки, чем это строго необходимо для каждого из узлов, но COleServerItem не требуется для каждой активной ссылки. Но по большей части, есть очень мало активных ссылок в любой момент времени. Чтобы сделать это более эффективно, HIERSVR в этой версии MFC отделяет узел от COleServerItem. Он имеет CServerNode и CServerItem класса. CServerItem (производный от COleServerItem) создает только при необходимости. После того, как контейнер (или контейнеры) прекратить использование этой конкретной ссылки на этом конкретном узле, будет удален объект CServerItem, связанный с CServerNode. Эта конструкция является более эффективным и более гибким. Его гибкость приходит в при работе с несколькими ссылками выбора. Ни один из этих двух версий HIERSVR поддерживает множественное выделение, но было бы намного проще для добавления (и в поддержку ссылки на такой отбор) с версией MFC 3.0 HIERSVR, так как COleServerItem отделяется от собственных данных.
Технические примечания по номеру |nbsp; Технические примечания по категориям