Студопедия КАТЕГОРИИ: АвтоАвтоматизацияАрхитектураАстрономияАудитБиологияБухгалтерияВоенное делоГенетикаГеографияГеологияГосударствоДомЖурналистика и СМИИзобретательствоИностранные языкиИнформатикаИскусствоИсторияКомпьютерыКулинарияКультураЛексикологияЛитератураЛогикаМаркетингМатематикаМашиностроениеМедицинаМенеджментМеталлы и СваркаМеханикаМузыкаНаселениеОбразованиеОхрана безопасности жизниОхрана ТрудаПедагогикаПолитикаПравоПриборостроениеПрограммированиеПроизводствоПромышленностьПсихологияРадиоРегилияСвязьСоциологияСпортСтандартизацияСтроительствоТехнологииТорговляТуризмФизикаФизиологияФилософияФинансыХимияХозяйствоЦеннообразованиеЧерчениеЭкологияЭконометрикаЭкономикаЭлектроникаЮриспунденкция |
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; просмотров: 484. stydopedya.ru не претендует на авторское право материалов, которые вылажены, но предоставляет бесплатный доступ к ним. В случае нарушения авторского права или персональных данных напишите сюда... |