Студопедия

КАТЕГОРИИ:

АвтоАвтоматизацияАрхитектураАстрономияАудитБиологияБухгалтерияВоенное делоГенетикаГеографияГеологияГосударствоДомЖурналистика и СМИИзобретательствоИностранные языкиИнформатикаИскусствоИсторияКомпьютерыКулинарияКультураЛексикологияЛитератураЛогикаМаркетингМатематикаМашиностроениеМедицинаМенеджментМеталлы и СваркаМеханикаМузыкаНаселениеОбразованиеОхрана безопасности жизниОхрана ТрудаПедагогикаПолитикаПравоПриборостроениеПрограммированиеПроизводствоПромышленностьПсихологияРадиоРегилияСвязьСоциологияСпортСтандартизацияСтроительствоТехнологииТорговляТуризмФизикаФизиологияФилософияФинансыХимияХозяйствоЦеннообразованиеЧерчениеЭкологияЭконометрикаЭкономикаЭлектроникаЮриспунденкция

STDMETHODCALLTYPE – _stdcall




REFIID          – const GUID &

 

В файле Unknwn.h можно также найти много других описаний, определяющих структуру таблицы vtable, заголовки функций для вызова proxy, stub и т.д.

В этом примере поставлена цель описания интерфейса и соответствующего класса, которые предоставляют возможность вызова одного единственного метода MyBeep(), заставляющего звучать встроенный динамик компьютера заданное время с заданной частотой.

Алгоритм создания приложения следующий.

 

Шаг 1. Создание заготовки приложения.

С целью последующей проверки кода создадим, с помощью мастера Win32 Console Application, заготовку проекта с именем BeepPrj и выберем поддержку MFC. 

 

Шаг 2. Добавление в проект нового класса.

С помощью команды Insert→New Class добавим в проект новый класс с именем IBeep, выбрав C++ в окне мастера Categories и С++ Class в окне Templates. Нажмем кнопку Add и в новом окне в поле ввода Class name введем имя IBeep и с помощью кнопки Change изменим предлагаемые мастером имена файлов IBeep.h и IBeep.cpp на Beep.h и Beep.cpp. В качестве базового укажем класс IUnknown, нажмем кнопку Finish. Итак, мы получили файлы Beep.h и Beep.cpp, содержащие нужные нам заготовки.

 

Шаг 3. Описание класса интерфейса и класса реализации.

Удалим из файлов Beep.h и Beep.cpp объявления и заготовки для конструктора и деструктора класса IBeep, которые нам не нужны.

Опишем в файле Beep.h класс IBeep следующим образом:

Class IBeep : public IUnknown

{

public:

STDMETHOD (MyBeep)()=0;

};

 

Рис. 1. Окно добавления класса

 

 

Рис. 2. Окно ввода имени нового класса, родительского класса и имен файлов

 

 

Здесь макрос STDMETHOD означает virtual HRESULT _stdcall. Как и в языке Object Pascal, метод MyBeep() мы объявляем виртуальным и в классе IBeep мы не будем и не должны выполнять его реализацию.  

Добавим все в тот же файл Beep.h объявление класса реализации CBeep, и, попутно, вставим в этот файл константу с уникальным идентификатором IID_IBeep, которую удобно получить с помощью команды меню ToolsèCreate GUID среды MVS 2008. Таким образом, файл Beep.h должен приобрести такой вид:

#pragma once

#include "unknwn.h"

static const GUID IID_IBeep =

{ 0xd186d488, 0xc332, 0x4423, { 0x83, 0x46, 0x95, 0xea,

0x77, 0xea, 0x33, 0x3c } };



Class IBeep : public IUnknown

{

public:

STDMETHOD (MyBeep)()=0;

};

Class CBeep : public IBeep 

{

public:

CBeep() { m_nRef=0;}

virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID, void **);

ULONG STDMETHODCALLTYPE AddRef();

ULONG STDMETHODCALLTYPE Release();

HRESULT STDMETHODCALLTYPE MyBeep();

protected:

ULONG m_nRef;

};

 

Обратите внимание на то, что в классе объявлена переменная m_nRef – счетчик ссылок на интерфейс, (неабстрактные) функции интерфейса IUnknown и функция MyBeep().  

 

Шаг 4. Реализация класса CBeep.

Реализация этого класса (в файле Beep.cpp) должна быть такой:

#include "StdAfx.h"

#include "Beep.h"

HRESULT CBeep::MyBeep()

{

TRACE("\nЗвучим!\n");

return Beep(2000,500)?S_OK:S_FALSE;

}

HRESULT CBeep::QueryInterface(REFIID iid, void ** ppv)

{

if ((iid == IID_IUnknown) || (iid == IID_IBeep))

 {

   *ppv = (IBeep*) this; //

   AddRef();

   return NOERROR;

}

*ppv=NULL;

return E_NOINTERFACE;

}

ULONG CBeep::AddRef()

{

return ++m_nRef;

}

ULONG CBeep::Release()

{

if(--m_nRef==0)

{

       delete this;

       TRACE("\nОбъект уничтожен\n");

       return 0;

}

return m_nRef;

}

 

Шаг 5. Использование интерфейса.

Применим интерфейс непосредственно в функции _tmain(). Вот листинг файла BeepPrj.cpp:

 

#include "stdafx.h"

#include "BeepPrj.h"

#include "Beep.h"

#include <ConIO.h>

#ifdef _DEBUG

#define new DEBUG_NEW

#endif

CWinApp theApp;

using namespace std;

int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])

{

int nRetCode = 0;

// initialize MFC and print and error on failure

if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0))

{

       // TODO: change error code to suit your needs

       _tprintf(_T("Fatal Error: MFC initialization failed\n"));

       nRetCode = 1;

}

//     CBeep cb; cb.MyBeep(); /*работает, но интерфейс и СОМ в целом

здесь ни при чем */

IBeep *IntfBeep=NULL;

CBeep *pBeep=new CBeep; /* создаем СОМ-объект, «прикидываясь» фабрикой

классов. В реальной СОМ это будет происходить

следующего оператора */

HRESULT hr=pBeep->QueryInterface(IID_IBeep,(void**)&IntfBeep);

if(SUCCEEDED(hr))

{

       TRACE("\nПолучен интерфейс объекта CBeep\n");

       IntfBeep->MyBeep();

       IntfBeep->Release(); /* Если этого не сделать, то будет

                             утечка памяти: в окне Debug появится

                             сообщение "Detected memory leaks!"*/

}

else

{

       TRACE("\nНе получен интерфейс объекта CBeep\n");

}

_getch();

return nRetCode;

}

 

Если запустить программу на выполнение, то в окне Debug мы должны увидеть, в частности, и такие строки:










Последнее изменение этой страницы: 2018-04-12; просмотров: 436.

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