Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лабы Мартын 1(ComCorbaLab2004).doc
Скачиваний:
30
Добавлен:
10.02.2016
Размер:
1.81 Mб
Скачать

1.7.9 Очистка

Перед тем, как завершить программу, нужно убедиться, что все компоненты были правильно освобождены. Классы-оболочки делают большинство необходимых операций самостоятельно. Когда интеллектуальный указатель-член класса выходит за пределы допустимого диапазона, он освобождает ссылки на интерфейсы, которые он содержал. Когда счетчик ссылок на интерфейс обнуляется, COM узнает, что может уничтожить компонент, когда это будет удобно.

Единственное, что нужно сделать самостоятельно - освободить интерфейсы точек взаимодействия, которые также следует создать самостоятельно. Для этого нужно, чтобы компонент модели освободил свою ссылку на интерфейс компонента представления при помощи метода Unadvise() интерфейса IConnectionPoint. Именно для этого использовался интеллектуальный указатель на этот интерфейс и сохранялось значение ключа, возвращенное методом Advise().

Лучше всего выполнить эти операции тогда, когда окно посылает сообщение WM_DESTROY. Для создания обработчика этого события выберается класс CDemoCleintView в окне ClassView и выбераются из всплывающего меню операции Add Windows Message Handler (см. рис. 1.3). Из предложенного списка выберается сообщение WM_DESTROY и нажмаются кнопки Add и Edit. В теле функции OnDestroy() добавляется следующий код перед вызовом CView::OnDestroy() базового класса (а не после него, где мастер приложения расположил комментарий TODO):

try

{

m_pCP->Unadvise(m_dwCookie);

}

catch(_com_error &e)

{

dump_com_error( e );

}

CView::OnDestroy();

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

Рис. 1.3. Новые сообщения и события окна

Теперь можно откомпилировать и запустить приложение, если уже созданы и зарегистрированы сами компоненты, изменять параметры компонента управления и наблюдать за изменениями в компоненте представления (см. листинг 1.1.).

// Листинг 1.1. Эти функции-члены обрабатывают события от компонента

// DemoController, когда пользователь использует элементы управления

// в определении класса CDemoClientView

class CDemoClientView : public CView

{

BOOL OnStopStart(VARIANT_BOOL start);

BOOL OnColorChanged();

BOOL OnSpeedChanged();

}

// в файле реализации CDEmoClientView

BOOL CDemoClientView::OnSpeedChanged()

{

try

{

short speed = m_pController->speed;

m_pModel->ChangeSpeed(speed);

}

catch (_com_error &e)

{

dump_com_error( e );

}

return TRUE;

}

BOOL CDemoClientView::OnColorChanged()

{

try

{

COLORREF color = (COLORREF)m_pController->bkcolor;

m_pView->bkgndColor = (long) color;

}

catch (_com_error &e)

{

dump_com_error( e );

}

return TRUE;

}

BOOL CDemoClientView::OnStopStart(VARIANT_BOOL start)

{

try

{

if (start)

m_pModel->Spin();

else

m_pModel->Stop();

}

catch (_com_error &e)

{

dump_com_error( e );

}

return TRUE;

}

1.7.10 Шаблонный код

В приложении 1 приведен полный шаблонный кодDemoComponentsиDemoClient.

1.8 Использование среды Visual C++

В качестве примера использования среды VisualC++ возможно создать два компонента – один для просмотра, второй для управления. Возможно начать с компонента управления DemoController2. Обращение к меню в среде Visual C++ следующее: New->Projects->ATLCOM APPWIZARD. Здесь включается поддержка MFC и dll-файлов, далее можно ничего не менять. После того как мастер создаст заготовку для компонента, выбирается Insert->New ATL Object->Controls->Composite Control. Компонент управления именуется, например, DemoContoller. После этого включается поддержка connection points.

В результате мастер создаст интерфейс _IdemoControllerEvents (см. рис.1.4).

Рис. 1.4 Создание мастером интерфейса _IdemoControllerEvents

Для работы с контроллером в этот интерфейс добавляются методы, например:

  • ShowMessage – реализует старт;

  • Stop – реализует стоп;

  • Spd(long speed) – управляет скоростью.

Рис. 1.5 Добавление методов в интерфейс

На вкладке ресурсов конструируется вид компонента контроля и выполняется компиляция.

Рис. 1.6 Конструирование внешнего вида компонента контроля

Для класса CdemoController выбирается Implement Connection Point и отмечается интерфейс.

Рис. 1.7 Выбор Implement Connection Point

Мастер создает класс CProxy_IDemoControllerEvents, в котором будут реализованы обработчики методов, повторяющих названия методов интерфейса _IDemoControllerEvents с префиксом Fire_.

Рис. 1.8 Отметка интерфейса

Теперь можно добавить некоторый код обработчиков событий от нажатия кнопок и скроллинга:

// Листинг 1.2. Добавление кода обработчиков событий от нажатия кнопок и скроллинга

public:

long oldspeed;

long speed;

OLE_COLOR m_clrBackColor;

OLE_COLOR m_clrBorderColor;

LONG m_nBorderStyle;

LONG m_nBorderWidth;

enum { IDD = IDD_DEMOCONTROLLER };

LRESULT OnClickedButton1(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)

{

// TODO : Add Code for control notification handler.

//MessageBox("44444");

Fire_ShowMesg();

return 0;

}

LRESULT OnClickedButton2(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)

{

// TODO : Add Code for control notification handler.

Fire_stop();

return 0;

}

LRESULT OnHScroll(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)

{

// TODO : Add Code for message handler. Call DefWindowProc if necessary.

Fire_spd(LOWORD(wParam));

switch(LOWORD(wParam))

{

case SB_RIGHT:

{

speed = 100;

}

break;

case SB_LEFT:

{

speed = 1;

}

break;

case SB_LINELEFT:

{

if (speed > 1) --speed;

}

break;

case SB_LINERIGHT:

{

if (speed < 100) ++speed;

}

break;

case SB_PAGELEFT:

{

if (speed > 20) speed-=20;

}

break;

case SB_PAGERIGHT:

{

if (speed <= 80) speed+=20;

}

break;

case SB_THUMBTRACK:

case SB_THUMBPOSITION: speed = HIWORD(wParam);

default:;

}

Fire_spd(speed);

return 0;

}

}

После компиляции компонент готов к работе. Библиотека размещается в папке Debug текущего каталога.

После этого возможно перейти к компоненту просмотра DemoView. Ход создания компонента, описанный ранее, повторяется вплоть до добавления методов в интерфейс. При добавлении нового ATLкласс будет называться CDDemoView. Далее в ресурсах формируется интерфейс компонента.

Рис. 1.9 Формирование интерфейса компонента

В форму, созданную мастером, может быть помещен компонент DirectAnimation. Для работы с этим компонентом следует импортировать библиотеку.

#import "c:\windows\system\danim.dll" no_namespace // Путь указан для Windows 98

В библиотеке, в частности, описаны интерфейсы, с которыми впоследствии будет выполняться работа при объявлении переменных класса.

long m_speed,m_oldspeed;

IDAViewerControlPtr m_viewer;

IDAStaticsPtr m_statics;

IDAImagePtr m_image,m_imageinit,m_imagenew;

IDATransform2Ptr m_transinit,m_transnew;

Далее добавляются те или иные методы в интерфейс IDDemoView, например, функции prep(), strt(), stp(), spd(long speed).

В классе CDDemoView в интерфейсе IDDemoView вместо шаблонов добавляется реализация этих методов.

// Листинг 1.3. Реализация методов в классе CDDemoView в интерфейсе IDDemoView

STDMETHODIMP CDDemoView::strt()

{

AFX_MANAGE_STATE(AfxGetStaticModuleState())

// TODO: Add your implementation code here

m_speed = m_oldspeed;

m_transnew = m_statics->Rotate2Rate(m_speed);

m_imagenew = m_image->Transform(m_transnew);

m_imageinit->SwitchTo(m_imagenew);

return S_OK;

}

STDMETHODIMP CDDemoView::stp()

{

AFX_MANAGE_STATE(AfxGetStaticModuleState())

// TODO: Add your implementation code here

m_oldspeed = m_speed;

m_speed = 0;

m_transnew = m_statics->Rotate2Rate(m_speed);

m_imagenew = m_image->Transform(m_transnew);

m_imageinit->SwitchTo(m_imagenew);

return S_OK;

}

STDMETHODIMP CDDemoView::prep()

{

AFX_MANAGE_STATE(AfxGetStaticModuleState())

// TODO: Add your implementation code here

CAxWindow(GetDlgItem(IDC_DA)).QueryControl(&m_viewer);

m_statics = m_viewer->GetMeterLibrary();

m_image = m_statics->ImportImage("c:\\image.gif");

m_transinit = m_statics->Rotate2Rate(1);

m_imageinit = m_statics->ModifiableBehavior(m_image->Transform(m_transinit));

m_viewer->PutImage(m_imageinit);

// m_viewer->PutSound(m_statics->Silence);

m_viewer->Start();

return S_OK;

}

STDMETHODIMP CDDemoView::spd(long speed)

{

AFX_MANAGE_STATE(AfxGetStaticModuleState())

// TODO: Add your implementation code here

m_speed = speed;

m_transnew = m_statics->Rotate2Rate(speed);

m_imagenew = m_image->Transform(m_transnew);

m_imageinit->SwitchTo(m_imagenew);

return S_OK;

}

После построения компонент готов к использованию.

После этого целесообразно перейти к приложению-серверу, которое будет использовать эти компоненты. Для начала импортируются библиотеки, например, с помощью кода:

#import "C:\Documents and Settings\UserXX\Мои документы\Com\DemoController2\DemoController2.tlb" no_namespace

#import "C:\Documents and Settings\UserXX\Мои документы\Com\DemoView\DemoView.tlb" no_namespace

В секции объявлений для класса CDemoAppView может быть записано:

CDemoAppDoc* GetDocument();

CWnd m_viewWnd;

CWnd m_controllerWnd;

IDDemoViewPtr m_pView;

IDemoControllerPtr m_pController;

IConnectionPointPtr m_pCP;

DWORD m_dwCookie;

BOOL Fire_ShowMesg();

BOOL Fire_stop();

К этому же классу также может быть добавлена виртуальная функция OnInitialUpdate.

CView::OnInitialUpdate();

// TODO: Add your specialized code here and/or call the base class

m_viewWnd.CreateControl(__uuidof(DDemoView),"View",WS_VISIBLE,CRect(0,0,600,200),this,101);

m_controllerWnd.CreateControl(__uuidof(DemoController),"Controller",WS_VISIBLE,CRect(0,201,600,400),this,102);

m_pModel.CreateInstance(__uuidof(DemoModel2));

m_viewWnd.GetControlUnknown()->QueryInterface(&m_pView);

m_controllerWnd.GetControlUnknown()->QueryInterface(&m_pController);

IConnectionPointContainerPtr pCPC = m_pModel;

IUnknownPtr pUnk = m_pView;

if(pCPC != NULL)

{

pCPC->FindConnectionPoint(__uuidof(IDemoModelConnection),&m_pCP);

if(m_pCP != NULL)

{

m_pCP->Advise(pUnk,&m_dwCookie);

}

}

_pView->prep();

В файл DemoAppView.cpp кроме того добавляется карта событий

BEGIN_EVENTSINK_MAP(CDemoAppView, CView)

ON_EVENT(CDemoAppView, IDC_CONTROLLER, 2, Fire_stop, VTS_NONE)

ON_EVENT(CDemoAppView,102, 1,Fire_ShowMesg, VTS_NONE)

ON_EVENT(CDemoAppView, IDC_CONTROLLER, 3, Fire_spd, VTS_I4)

END_EVENTSINK_MAP()

Наконец, описывается реализация методов, которые целесообразно предварительно добавить во все тот же класс с именами методов класса CProxy_IDemoControllerEvents.

BOOL CDemoAppView::Fire_stop()

{

m_pView->stp();

return TRUE;

}

BOOL CDemoAppView::Fire_spd(long speed)

{

m_pView->spd(speed);

return TRUE;

}

BOOL CDemoAppView::Fire_ShowMesg()

{

m_pView->strt();

return TRUE;

}

Ниже приведен вид возможного варианта откомпилированного приложения.

Рис. 1.10 Результат компиляции приложения