На этом шаге мы рассмотрим, как задать функциональность созданному серверу.
После того, когда программа сгенерирована, в нее нужно добавить код, задающий функциональность сервера OLE. Необходимо включить код, рисующий изображение, а также провести другие незначительные изменения.
Допустим, мы хотим сначала заняться вопросами отображения. Как и в любой созданной с помощью AppExpert программе, основная часть рисования выполняется классом отображения, производным от класса OWL TOleView. Файл, в котором содержится реализация отображения, имеет имя LSVROLVW.CPP. Приведем первоначальный текст этого файла с переводом некоторых комментариев:
Листинг 1. Файл LSVROLVW.CPP
/* Project olesvr Copyright c 1994. All Rights Reserved. SUBSYSTEM: olesvr.exe Application FILE: lsvrolvw.cpp AUTHOR: OVERVIEW ======== Source file for implementation of olesvrOleView (TOleView). Исходный файл реализации olesvrOleView (TOleView). */ #include <owl\owlpch.h> #pragma hdrstop #include "olsvrapp.h" #include "lsvrolvw.h" #include <stdio.h> //{{olesvrOleView Implementation}} //{{Реализация olesvrOleView}} // // Build a response table for all messages/commands handled // by olesvrOleView derived from TOleView. // Создать таблицу для всех сообщений/команд, поддерживаемых // olesvrOleView, производным от TOleView. // DEFINE_RESPONSE_TABLE1(olesvrOleView, TOleView) //{{olesvrOleViewRSP_TBL_BEGIN}} EV_WM_GETMINMAXINFO, EV_OC_VIEWSHOWTOOLS, //{{olesvrOleViewRSP_TBL_END}} END_RESPONSE_TABLE; ////////////////////////////////////////////////////////// // olesvrOleView // ========== // Construction/Destruction handling. // Обработка создания/уничтожения. olesvrOleView::olesvrOleView (TDocument& doc, TWindow* parent) : TOleView(doc, parent) { ToolBar = 0; // INSERT>> Your constructor code here. // ВСТАВИТЬ>> В этом месте код вашего конструктора. } olesvrOleView::~olesvrOleView () { // INSERT>> Your destructor code here. // ВСТАВИТЬ>> В этом месте код вашего конструктора. } // // Paint routine for Window, Printer, and PrintPreview for a TOleView client. // Процедура рисования для Window, Printer и PrintPreview клиента TOleView. // void olesvrOleView::Paint (TDC& dc, bool erase, TRect& rect) { olesvrApp *theApp = TYPESAFE_DOWNCAST(GetApplication(), olesvrApp); if (theApp) { // Only paint if we're printing and we have something to paint, // otherwise do nothing. // Рисовать только в случае, если необходимо что-нибудь напечатать // или отобразить. if (theApp->Printing && theApp->Printer && !rect.IsEmpty()) { // Use pageSize to get the size of the window to render into. // For a Window it's the client area, // for a printer it's the printer DC dimensions and for // print preview it's the layout window. // Использовать pageSize для получения // размера окна для визуализации информации. // Для Window - это рабочая область, // для принтера - это размеры контекста устройства, // для print preview - это окно формата. TSize pageSize(rect.right - rect.left, rect.bottom - rect.top); TPrintDialog::TData &printerData = theApp->Printer->GetSetup(); // Compute the number of pages to print. // Вычислить число страниц, которые необходимо напечатать. printerData.MinPage = 1; printerData.MaxPage = 1; TOcView *ocView = GetOcView(); // // Default TOcPart painting // Рисование TOcPart по умолчанию // TRect clientRect = GetClientRect(); TRect logicalRect = clientRect + (TSize&)ocView->GetOrigin(); for (TOcPartCollectionIter i(GetOcDoc()->GetParts()); i; i++) { TOcPart& p = *i.Current(); if (p.IsVisible(logicalRect)) { TRect r = p.GetRect(); r -= ocView->GetOrigin(); p.Draw(dc, r, clientRect); // Draw the embedded object. // Нарисовать внедренный объект. if (p.IsSelected()) { TUIHandle handle(r, TUIHandle::HandlesIn | TUIHandle::Grapples | TUIHandle::HatchBorder, 5); handle.Paint(dc); } else { TUIHandle handle(r, TUIHandle::HatchBorder, 5); handle.Paint(dc); } } } // INSERT>> Special printing code goes here. // ВСТАВИТЬ>> В этом месте выполняется печать. } else { TOleView::Paint(dc, erase, rect); // INSERT>> Normal painting code goes here. // ВСТАВИТЬ>> В этом месте выполняется обычное рисование. } dc.TextOut(0, 30, "olesvr OLE Server"); } } void olesvrOleView::EvGetMinMaxInfo (MINMAXINFO far& minmaxinfo) { olesvrApp *theApp = TYPESAFE_DOWNCAST(GetApplication(), olesvrApp); if (theApp) { if (theApp->Printing) { minmaxinfo.ptMaxSize = TPoint(32000, 32000); minmaxinfo.ptMaxTrackSize = TPoint(32000, 32000); return; } } TOleView::EvGetMinMaxInfo(minmaxinfo); } bool olesvrOleView::EvOcViewShowTools (TOcToolBarInfo far& tbi) { // Construct & create a control bar for show, destroy our bar for hide // Сконструировать и создать панель управления для отображения, // уничтожить нашу панель для сокрытия if (tbi.Show) { if (!ToolBar) { ToolBar = new TControlBar(this); olesvrApp *theApp = TYPESAFE_DOWNCAST(GetApplication(), olesvrApp); CHECK(theApp); theApp->CreateGadgets(ToolBar, true); } ToolBar->Create(); tbi.HTopTB = (HWND)*ToolBar; } else { if (ToolBar) { ToolBar->Destroy(); delete ToolBar; ToolBar = 0; } } return true; }
Основная процедура отображения, генерируемая AppExpert функция olesvrOleView::Paint(TDC& dc, bool erase, TRect& rect), которая содержит управляющий код, но в действительности ничего не рисует. Запрограммируем код для функции Paint(), рисующий пятиконечную звезду. Закрасим звезду, с помощью функции GDI Polygon(), и зададим несколько опций. Создадим новую функцию в классе olesvrOleView с именем OurPaint(), которая и будет рисовать изображение.
При вызове olesvrOleView::Paint() этой функции передаются три параметра: ссылка на объект TDC, логическая переменная, указывающая, следует ли очистить область пользователя, и ссылка на объект TRect, содержащая координаты прямоугольника в области пользователя, который следует перерисовать. Точно такие же параметры передаются при вызове функции OurPaint(). В листинге 2 приводится функция OurPaint().
Листинг 2. Функция olesvrOleView::OurPaint()
void olesvrOleView::OurPaint (TDC& dc, bool /*erase*/, TRect& rect) { //Это функция отображения. TPoint Points[10]; HBRUSH cBrush; int OldFillMode; int FillMode=ALTERNATE; cBrush=CreateSolidBrush(RGB(254,128,6)); TRect Clientrect; GetWindow()->GetClientRect(Clientrect); Clientrect.left=15; Clientrect.right=75; Clientrect.bottom=75; Clientrect.top=15; Points[0].x=(Clientrect.right+Clientrect.left)/2; Points[0].y=Clientrect.top; Points[1].x=Clientrect.right; Points[1].y=Clientrect.bottom; Points[2].x=Clientrect.left; Points[2].y=((Clientrect.bottom+Clientrect.top)/3)*1; Points[3].x=Clientrect.right; Points[3].y=((Clientrect.bottom+Clientrect.top)/3)*1; Points[4].x=Clientrect.left; Points[4].y=Clientrect.bottom; Points[5]=Points[0]; dc.SelectObject(cBrush); OldFillMode=dc.SetPolyFillMode(FillMode); dc.Polygon(Points,6); dc.SetPolyFillMode(OldFillMode); dc.RestoreBrush(); DeleteObject(cBrush); }
Следует также добавить вызов функции OurPaint() в тело функции olesvrOleView::Paint(). Эта модификация приводится в листинге 3 в выделенной сроке.
Листинг 3. Обращение к функции OurPaint() в теле функции olesvrOleView::Paint())
. . . .
{
TOleView::Paint(dc, erase, rect);
// Вставить >> В этом месте выполняется обычное рисование.
OurPaint(dc, erase, rect);
}
dc.TextOut (0, 30, "olesvr OLE Server");
}
}
Необходимо внести прототип функции в заголовочный файл LSVROEVW.H, как показано в листинге 4.
Листинг 4. Заголовочный файл LSVROLVW.H с добавленным прототипом функции OurPaint())
#if !defined(__lsvrolvw_h) // Sentry, use file only if it's not already included. // Предотвращение повторных включений этого файла. #define __lsvrolvw_h /* Project olesvr Copyright c 1994. All Rights Reserved. SUBSYSTEM: olesvr.exe Application FILE: lsvrolvw.h AUTHOR: OVERVIEW ======== Class definition for olesvrOleView (TOleView). Определение класса olesvrOleView (TOleView). */ #include <owl\owlpch.h> #pragma hdrstop #include "olsvrapp.rh" // Definition of all resources. // Определение всех ресурсов. //{{TOleView = olesvrOleView}} class olesvrOleView : public TOleView { public: olesvrOleView (TDocument& doc, TWindow* parent = 0); virtual ~olesvrOleView (); void olesvrOleView::OurPaint (TDC& dc, bool erase, TRect& rect); private: TControlBar *ToolBar; //{{olesvrOleViewVIRTUAL_BEGIN}} public: virtual void Paint (TDC& dc, bool erase, TRect& rect); //{{olesvrOleViewVIRTUAL_END}} //{{olesvrOleViewRSP_TBL_BEGIN}} protected: void EvGetMinMaxInfo (MINMAXINFO far& minmaxinfo); bool EvOcViewShowTools (TOcToolBarInfo far& tbi); //{{olesvrOleViewRSP_TBL_END}} DECLARE_RESPONSE_TABLE(olesvrOleView); }; //{{olesvrOleView}} #endif // __lsvrolvw_h sentry.
Когда вы добавите функцию OurPaint() (в файл исходного текста и в заголовочный файл) и обращение к OurPaint(), следует построить проект и попытаться запустить программу. Если не было совершено никаких ошибок при внесении изменений, компилятор должен выдать лишь одно предупреждение (параметр erase функции OurPaint() нигде не используется), и в результате вы получите исполняемый файл.
Однако при запуске программы в рабочей области OLESVR ничего не отображается!
На следующем шаге мы рассмотрим решение этой проблемы.