На этом шаге мы реализуем функциональность созданного сервера.
Отсутствие созданного на предыдущем шаге изображения на экране объясняется просто: OLESVR не известно, что существует текущий документ. После запуска OLESVR выберите команду File | New. Выбор New укажет OLESVR, что это текущий документ, и наша звезда на экране:
Рис.1. Результат работы программы OLESVR
Но не совсем удобно заставлять пользователя выбирать File | New после запуска OLESVR. Следующее изменение - это имитация создания нового документа, которое проиллюстрирует посылку сообщения Windows для выполнения элемента меню.
Для создания нового обработчика событий необходимо выполнить следующие действия.
Рис.2. Внешний вид ClassExpert после создания обработчика EvCreate().
Листинг 1. Вызов функции SendMessage() в обработчике EvCreate()
int SDIDecFrame::EvCreate (CREATESTRUCT far& createStruct) { int result; result = TOleFrame::EvCreate(createStruct); // INSERT>> Your code here. // ВСТАВИТЬ>> В этом месте ваш код. SendMessage(WM_COMMAND,CM_FILENEW,0); return result; }
Далее необходимо проверить OLESVR внедрением ее в контейнерное приложение. Протестируем OLESVR с помощью, например, Microsoft Word. Вообще любое корректное контейнерное приложение OLE должно работать с OLESVR. В Microsoft Word создайте новый документ, затем выберите Вставить | Объект. После этого выберите olesver Document. Вы увидите изображение звезды, как и при запуске на выполнение автономного приложения OLESVR.
Так как созданный сервер поддерживает редактирование "по месту", мы увидим, как меню OLESVR заменит собою стандартное меню Microsoft Word. Но мы не писали какую-либо реализацию редактирования "по месту"! Дело в том, что утилита AppЕxpert Borland C++ версии 4.5 автоматически включила его поддержку в код, когда генерировала OLE-приложение.
Теперь если щелкнуть мышью вне области OLESVR на документе Microsoft Word, мы увидим, что произойдет несколько событий. Сначала Word восстановит свое обычное меню. Затем объект OLESVR потеряет фокус ввода, и мы увидим нормальный текстовый курсор.
В заключение отметим, что иногда требуется управлять обновлением внедренного объекта в контейнере. Borland включила в OCF обработчик события OC_VIEWPAINT (над сообщениями OLE) для поддержки отображения внедренного объекта. Задание этого обработчика, например, для нашего класса olesvrOleView (группа событий OLE Messages) вставит следующий код в класс отображения:
bool olesvrOleView::EvOcViewPaint (TOcViewPaint far& vp) { bool result; result = TOleView::EvOcViewPaint(vp); // INSERT>> Your code here. // ВСТАВИТЬ>> Здесь ваш код. return result; }
Передача на структуру TOcViewPaint позволит приложению получить доступ к любым ресурсам, необходимым для обновления рабочей области. Обработчик, задаваемый OCF по умолчанию, вызлвет правильную функцию отображения, в зависимости от того, связан объект или нет. Обработчик TOleWindow::EvOcViewPaint() реализован в файле BC45\SOURCE\OWL\OLEWINDO.CPP следующим образом:
// // Ask server to paint itself in the position and dc provided // Обращение к серверу для отрисовки с заданными позицией и контекстом устройства // bool TOleWindow::EvOcViewPaint(TOcViewPaint far& vp) { // paint according to the view paint structure // отображать в соответствии со структурой рисования TDC dc(vp.DC); Pos = *vp.Pos; // Paint embedded objects // Нарисовать внедренные объекты bool metafile = dc.GetDeviceCaps(TECHNOLOGY) == DT_METAFILE; SetupDC(dc, !metafile); if (vp.Moniker) { PaintLink(dc, true, Pos, *vp.Moniker); } else if (vp.PaintSelection) { PaintSelection(dc, true, Pos, vp.UserData); } else { Paint(dc, true, Pos); PaintParts(dc, true, Pos, metafile); } Pos.SetNull(); return true; }
Как следует из этого фрагмента, структура TOcViewPaint имеет несколько членов, отражающих статус объекта. Структура TOcViewPaint объявляется в файле BC45\INCLUDE\OCF\OCVIEW.H следующим образом:
struct TOcViewPaint { // for part adornment painting over part, & painting views // для раскрашивания изображений HDC DC; TRect* Pos; TRect* Clip; TOcAspect Aspect; bool PaintSelection; // paint the selection only // (рисовать только выбранное) TString* Moniker; // moniker if any // (имя (если есть) связанного объекта) void* UserData; // User data (дата) };
Структура TOcViewPaint содержит всю информацию, необходимую для ображения к функциям PasteLink(), PasteSelection() и Paint(). Обратите внимание, что если имя связанного объекта не задано и флаг PaintSelection не установлен, то вызывается функция TOleWindow::Paint(). Напимним, что эта функция также вызывается поставляемой функцией Paint(), принажлежащей созданному в приложении классу отображения.
На следующем шаге рассмотрим cоздание контейнера OLE.