Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Вопрос по примеру из MSDN

841
18 августа 2009 года
_nic
199 / / 29.07.2006
Пример находится по этой ссылке http://msdn.microsoft.com/en-us/library/ms221237.aspx Я хочу при помощи CreateStdDispatch вызвать(или инициализировать,незнаю как отнести это к такому интерфейсу :confused: ) этот COM интерфейс DDiscFormat2DataEvents. В том примере для меня не очень понятны эти строчки:
Код:
static METHODDATA NEARDATA rgmdataCCalc[] =
{
      PROPERTY(VALUE,  IMETH_ACCUM,    IDMEMBER_ACCUM,    VT_I4),
      PROPERTY(ACCUM,  IMETH_ACCUM,    IDMEMBER_ACCUM,    VT_I4),
      PROPERTY(OPND,   IMETH_OPERAND,  IDMEMBER_OPERAND,  VT_I4),
      PROPERTY(OP,     IMETH_OPERATOR, IDMEMBER_OPERATOR, VT_I2),
      METHOD0(EVAL,    IMETH_EVAL,     IDMEMBER_EVAL,     VT_BOOL),
      METHOD0(CLEAR,   IMETH_CLEAR,    IDMEMBER_CLEAR,    VT_EMPTY),
      METHOD0(DISPLAY, IMETH_DISPLAY,  IDMEMBER_DISPLAY,  VT_EMPTY),
      METHOD0(QUIT,    IMETH_QUIT,     IDMEMBER_QUIT,     VT_EMPTY),
      METHOD1(BUTTON,  IMETH_BUTTON,   IDMEMBER_BUTTON,   VT_BOOL),
};

INTERFACEDATA NEARDATA g_idataCCalc =
{
   rgmdataCCalc, DIM(rgmdataCCalc)
};

Где мне ,можно найти нужную информацию для нужного мне интерфейса(я так понял методы которые он содержит,и т.д.) ???
14
19 августа 2009 года
Phodopus
3.3K / / 19.06.2008
Так тебе в итоге че надо, реализовать интерфейс или получить информацию о уже реализованном?
841
19 августа 2009 года
_nic
199 / / 29.07.2006
Цитата: Phodopus
Так тебе в итоге че надо, реализовать интерфейс или получить информацию о уже реализованном?



Получается (на сколько я смог разобратся в этом COM :confused: ) что реализовать.Это я насколько понял делается через IDispatch.

398
19 августа 2009 года
Alexandoros
630 / / 21.10.2005
Давай таки сформулируй задача.
2.2K
19 августа 2009 года
REFOT
181 / / 08.04.2005
:) У меня вот, что вышло:

Код:
#include "stdafx.h"
#include "imapi2.h"

class CEvent
{
    STDMETHOD_(HRESULT, Update)(IDispatch *object, IDispatch *progress);
};

STDMETHODIMP_(HRESULT) CEvent::Update(IDispatch *object, IDispatch *progress)
{
   //если всё нормально, то попадём сюда
   return S_OK;
}

class CDiscFormatDataEvent : public IUnknown
{
public:
    CDiscFormatDataEvent();
    virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID, void**);
    virtual ULONG STDMETHODCALLTYPE AddRef();
    virtual ULONG STDMETHODCALLTYPE Release();
    static  CDiscFormatDataEvent* Create();
private:
    unsigned long m_refs;
public:
    CEvent m_event;
    IUnknown* m_pPunk;
};

static PARAMDATA pUpdate [] =
{
    {OLESTR("object"),   VT_DISPATCH},
    {OLESTR("progress"), VT_DISPATCH}
};

static METHODDATA mUpdate =
{
    OLESTR("Update"), pUpdate, DISPID_DDISCFORMAT2DATAEVENTS_UPDATE, 0, CC_STDCALL, 2, DISPATCH_METHOD, VT_I4
};

static INTERFACEDATA iUpdate =
{
    &mUpdate, 1
};

CDiscFormatDataEvent::CDiscFormatDataEvent() : m_refs(0)
{
}

CDiscFormatDataEvent* CDiscFormatDataEvent::Create()
{
   HRESULT hr = S_OK;
   CDiscFormatDataEvent* pEvent = NULL;
   ITypeInfo *pTI = NULL;
   CreateDispTypeInfo(&iUpdate, LOCALE_SYSTEM_DEFAULT, &pTI);

   /* Вместо CreateDispTypeInfo, лучше делать так:
    LPTYPELIB ptlib = NULL;
    HRESULT hr = LoadRegTypeLib(LIBID_IMAPILib2, IMAPILib2_MajorVersion,  IMAPILib2_MinorVersion, LOCALE_SYSTEM_DEFAULT, &ptlib);
    hr = ptlib->GetTypeInfoOfGuid(IID_DDiscFormat2DataEvents, &pTI);
    ptlib->Release(); */

   if(SUCCEEDED(hr))
   {
      pEvent = new CDiscFormatDataEvent();
      hr = CreateStdDispatch(pEvent, &pEvent->m_event, pTI, &pEvent->m_pPunk);
      pTI->Release();
      if(SUCCEEDED(hr)){
          pEvent->AddRef();
      }
      else{
          delete pEvent;
          pEvent = NULL;
      }
   }
   return pEvent;
}

HRESULT STDMETHODCALLTYPE CDiscFormatDataEvent::QueryInterface(REFIID riid, void **ppvObject)
{
    if (IsEqualIID(riid, IID_IUnknown))
        *ppvObject = this;
    else if (IsEqualIID(riid, IID_IDispatch) || IsEqualIID(riid, IID_DDiscFormat2DataEvents)){
        return m_pPunk->QueryInterface(IID_IDispatch, ppvObject);
    }
    else{
       *ppvObject = NULL;
        return ResultFromScode(E_NOINTERFACE);
    }
    AddRef();
    return S_OK;
}

ULONG STDMETHODCALLTYPE CDiscFormatDataEvent::AddRef()
{
   return ++m_refs;
}

ULONG STDMETHODCALLTYPE CDiscFormatDataEvent::Release()
{
   if(--m_refs == 0 && m_pPunk)
       m_pPunk->Release();
   return m_refs;
}

int _tmain(int argc, _TCHAR* argv[])
{
  ::CoInitialize(NULL);

   CDiscFormatDataEvent* pEvent = CDiscFormatDataEvent::Create();
   if(pEvent == NULL) return 0;

   IDiscFormat2Data* pDiscFormatData = NULL;
   HRESULT hr = CoCreateInstance(CLSID_MsftDiscFormat2Data, NULL, CLSCTX_INPROC_SERVER,
                     IID_IDiscFormat2Data, (void**)&pDiscFormatData);

   if(FAILED(hr)) return 0;
   
   IConnectionPointContainer *pConnPtContainer = NULL;
   hr = pDiscFormatData->QueryInterface(IID_IConnectionPointContainer,(void**)&pConnPtContainer);

   if(FAILED(hr)) return 0;

   IConnectionPoint* pConnectionPoint = NULL;
   hr = pConnPtContainer->FindConnectionPoint(IID_DDiscFormat2DataEvents,&pConnectionPoint);

   if(FAILED(hr)) return 0;

   pConnPtContainer->Release();

   //подписываемся на событие
   DWORD Cookie = 0;
   hr = pConnectionPoint->Advise(pEvent,&Cookie);  
   if(FAILED(hr)) return 0;
 
   //отписываемся от события
   hr = pConnectionPoint->Unadvise(Cookie);
   return 0;
}


Не знаю уж, на сколько всё верно получилось, но суть должна быть понятна.
841
26 августа 2009 года
_nic
199 / / 29.07.2006
Для отслеживания прогресса "прожига" в IMAPI 2 , я на сколько понял мне надо вызвать интерефейс DDiscFormat2DataEvents что бы получить из него IDiscFormat2DataEventArgs
ЗЫ:REFOT мне не ясно где брать начинку для таких классов которые нужно вручную расписывать.
2.2K
26 августа 2009 года
REFOT
181 / / 08.04.2005
Цитата:

Для отслеживания прогресса "прожига" в IMAPI 2 , я на сколько понял мне надо вызвать интерефейс DDiscFormat2DataEvents что бы получить из него IDiscFormat2DataEventArgs



IDiscFormat2DataEventArgs тебе передатут в DDiscFormat2DataEvents::Update(IDispatch *object, IDispatch *progress), где progress и есть IDiscFormat2DataEventArgs.

Цитата:

ЗЫ:REFOT мне не ясно где брать начинку для таких классов которые нужно вручную расписывать.



;) Всю начинку я взял из imapi2.h. Так же можно и в библиотеку типов заглянуть :).

841
27 августа 2009 года
_nic
199 / / 29.07.2006
Порылся в Imapi2.h там для DDiscFormat2DataEvents только перменные методов,а сама "начинка" интерфейса хз где :(
2.2K
29 августа 2009 года
REFOT
181 / / 08.04.2005
Смотрим imapi2.h и находим:
Код:
#define DISPID_DDISCFORMAT2DATAEVENTS_UPDATE  0x200

extern RPC_IF_HANDLE __MIDL_itf_imapi2_0000_0011_v0_0_c_ifspec;
extern RPC_IF_HANDLE __MIDL_itf_imapi2_0000_0011_v0_0_s_ifspec;

#ifndef __DDiscFormat2DataEvents_INTERFACE_DEFINED__
#define __DDiscFormat2DataEvents_INTERFACE_DEFINED__

/* interface DDiscFormat2DataEvents */
/* [helpstring][unique][uuid][oleautomation][nonextensible][object] */


EXTERN_C const IID IID_DDiscFormat2DataEvents;

#if defined(__cplusplus) && !defined(CINTERFACE)
   
    MIDL_INTERFACE("2735413C-7F64-5B0F-8F00-5D77AFBE261E")
    DDiscFormat2DataEvents : public IDispatch
    {
    public:
        virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE Update(
            /* [in] */ __RPC__in_opt IDispatch *object,
            /* [in] */ __RPC__in_opt IDispatch *progress) = 0;
       
    };
   
#else   /* C style interface */


Тут мы видим, что интерфейс имеет метод Update, который имеет id = DISPID_DDISCFORMAT2DATAEVENTS_UPDATE, принимает два параметра IDispatch* и
возвращает значение HRESULT.

Дальше мы всё это описываем:
Код:
//Описываем параметры метода
static PARAMDATA pUpdate [] =
{
   {OLESTR("object") /* Название параметра */, VT_DISPATCH /* Тип параметра*/},
   {OLESTR("progress") /* Название параметра */, VT_DISPATCH /* Тип параметра*/}
};

//Описываем сам метод
static METHODDATA mUpdate =
{
   OLESTR("Update") // Название метода
   ,pUpdate // Параметры описанные выше
   ,DISPID_DDISCFORMAT2DATAEVENTS_UPDATE // Id метода
   ,0 // индекс в VTBL
   ,CC_STDCALL // Соглашение о вызове
   ,2 // количество аргументов метода
   ,DISPATCH_METHOD // указываем что это метод
   VT_I4 // тип возвращаемого значения
};

//Описываем интерфейс
static INTERFACEDATA iUpdate =
{
    &mUpdate // Описание метода Update
    ,1  // Количество членов интерфейса
};


Всё это можно не описывать, а просто загрузить информацию из библиотеки типа:
 
Код:
LPTYPELIB ptlib = NULL;
   HRESULT hr = LoadRegTypeLib(LIBID_IMAPILib2,
                               IMAPILib2_MajorVersion,
                               IMAPILib2_MinorVersion,
                               LOCALE_SYSTEM_DEFAULT,
                               &ptlib);
   hr = ptlib->GetTypeInfoOfGuid(IID_DDiscFormat2DataEvents, &pTI);
   ptlib->Release();


После чего через функцию CreateStdDispatch создаём реализацию IDispatch для описанного интерфейса:

 
Код:
hr = CreateStdDispatch(pEvent // Указатель на реализацию IUnknown для объекта.
                       ,&pEvent->m_event //Указатель на предоставляемый объект.
                       ,pTI,  //Указатель на информацию о типе
                       ,&pEvent->m_pPunk // Возвращаемый интерфейс
);


Тут интерфейс IUnknown для объекта реализуем сами, это методы QueryInterface, AddRef, Release. Тут нет ничего сложного.
pEvent->m_event - этот объект реализует метод Update, который и будет вызываться при наступлении события связанного с прожигом.

Как устроены методы QueryInterface, AddRef, Release и как подписаться на событие, смотри выше.
841
29 августа 2009 года
_nic
199 / / 29.07.2006
Я абсолютно непонимаю как и зачем реализовывать IUnknown если этот интерфейс инициализируется через CoCreateInstance :confused:
2.2K
29 августа 2009 года
REFOT
181 / / 08.04.2005
Цитата: _nic
Я абсолютно непонимаю как и зачем реализовывать IUnknown если этот интерфейс инициализируется через CoCreateInstance :confused:



Интерфейс DDiscFormat2DataEvents нигде не реализован, для него не реализованы ни IUnknown, ни IDispatch, всё нужно делать самому и CoCreateInstance тут не причём.

Смотри, ты хочешь получать информацию о состоянии прожига или чего-то ещё.
Обращаешься к MSDN, а там тебе говорят, да не вопрос, чувак, дай нам только указатель на объект который реализует интерфейс DDiscFormat2DataEvents,
и как только состояние прожига изменится, мы у твоего объекта вызовем метод Update(...);

Ты радостно, быстренько пишешь:

 
Код:
class MyDDiscFormat2DataEvents: DDiscFormat2DataEvents
{
    STDMETHOD_(HRESULT, Update)(IDispatch *object, IDispatch *progress);
};

STDMETHODIMP_(HRESULT) MyDDiscFormat2DataEvents::Update(IDispatch *object, IDispatch *progress)
{
   return S_OK;
}


И думаешь вот и всё, делов-то, интерфейс DDiscFormat2DataEvents реализовал, можно теперь и подписаться на событие,
передав в Advise интерфейса IConnectionPoint указатель на объект MyDDiscFormat2DataEvents.

А тут фиг, не компилится! Требуют реализовать какие-то ещё IUnknown и IDispatch,
которые как оказывается наследует интерфейс DDiscFormat2DataEvents.

Думаешь, что за фигня?!

А потом, почитав немного, выясняешь, что Advice, вызывает у твоего объекта
метод QueryInterface интерфейса IUnknow, которому говорит, дай-ка, пожалуйста, мне указатель на объект DDiscFormat2DataEvents,
а если не дашь, на событие не подпишу!
Ну, а когда происходит само событие… О, ужас! Метод Update твоего объекта, вообще вызывается через интерфейс IDispatch:

 
Код:
pIDispatch->Invoke(
      DISPID_DDISCFORMAT2DATAEVENTS_UPDATE,
      IID_NULL,
      LOCALE_SYSTEM_DEFAULT,
      DISPATCH_METHOD,
      .....);


И ничего не поделаешь, придётся писать реализацию и IUnknow и IDispatch...

Выше я приводил пример, как реализовать интерфейс DDiscFormat2DataEvents и подписаться на событие.

Upd
Ссылки по теме:
http://www.rsdn.ru/article/com/introcom.xml
http://www.rsdn.ru/summary/2167.xml

Исходники рабочей программы:
http://narod.ru/disk/12569938000/BurnCD_src.zip.html
841
29 августа 2009 года
_nic
199 / / 29.07.2006
IDispatch наследуется из IUnknown ,а потом Invoke выполняет нужный метод нужного интерфейса?Или я опять ничего непонял? (я всеравно не представляю как это должно выглядеть :( , откудого в ручной реализации искомого интерфейса IUnknown растет???)
ЗЫ:
http://forum.sources.ru/index.php?act=Attach&type=post&id=2179612
неоткрывается :(
2.2K
29 августа 2009 года
REFOT
181 / / 08.04.2005
ссылку подправил.
Дай лучше icq или ещё что-то, так прощё будет объяснить.
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог