В одном топике немного ниже обсуждалась эта проблемма. Я решил проверить действительно ли сабж. невозможен. Написал простенький сервер на ATL с использованием визарда. Сделал сервер с 1 функцией DoVoctory которая генерит одно событие OnVictory, на которое сожусь из VB стандартным способом. Результат: Если событийный интерфейс обьявлен с атрибутом dual, то действительно VB ругается, но если с oleautomation, то всё ок и событие генериться... Так что всё ок. Весь код приведён ниже.
IDL файл.
import "oaidl.idl";
import "ocidl.idl";
//-----------------------------------------------------------------
[
object,
uuid(0481D2ED-E723-11D6-872F-0000214538D0),
dual,
helpstring("IEvObj Interface"),
pointer_default(unique)
]
interface IEvObj : IDispatch
{
[id(1), helpstring("method DoVictory")] HRESULT DoVictory();
};
//-----------------------------------------------------------------
[
oleautomation,
uuid(0481D2EF-E723-11D6-872F-0000214538D0),
helpstring("IEventEvObj Interface")
]
interface IEventEvObj : IDispatch
{
[helpstring("method OnVictory")] HRESULT OnVictory();
};
//-----------------------------------------------------------------
[
uuid(0481D2E1-E723-11D6-872F-0000214538D0),
version(1.0),
helpstring("lernEv 1.0 Type Library")
]
library LERNEVLib
{
importlib("stdole32.tlb");
importlib("stdole2.tlb");
[
uuid(0481D2EE-E723-11D6-872F-0000214538D0),
helpstring("EvObj Class")
]
coclass EvObj
{
[default] interface IEvObj;
[default, source] interface IEventEvObj;
};
};
H — файл сервера.
#ifndef __EVOBJ_H_
#define __EVOBJ_H_
#include "resource.h" // main symbols
class ATL_NO_VTABLE CEvObj :
public CComObjectRootEx<CComSingleThreadModel>,
public CComCoClass<CEvObj, &CLSID_EvObj>,
public IConnectionPointImpl<CEvObj, &IID_IEventEvObj>,
public IConnectionPointContainerImpl<CEvObj>,
public IDispatchImpl<IEvObj, &IID_IEvObj, &LIBID_LERNEVLib>
{
public:
CEvObj()
{
}
DECLARE_REGISTRY_RESOURCEID(IDR_EVOBJ)
DECLARE_PROTECT_FINAL_CONSTRUCT()
BEGIN_COM_MAP(CEvObj)
COM_INTERFACE_ENTRY(IEvObj)
COM_INTERFACE_ENTRY(IDispatch)
COM_INTERFACE_ENTRY(IConnectionPointContainer)
END_COM_MAP()
BEGIN_CONNECTION_POINT_MAP(CEvObj)
CONNECTION_POINT_ENTRY(IID_IEventEvObj)
END_CONNECTION_POINT_MAP()
// IEvObj
public:
STDMETHOD(DoVictory)();
};
#endif //__EVOBJ_H_
CPP файл сервера, содержащий метод DoVictory, который генерит событие
#include "stdafx.h"
#include "LernEv.h"
#include "EvObj.h"
STDMETHODIMP CEvObj::DoVictory()
{
HRESULT hr = 0;
IEventEvObj * pE = NULL;
pE = (IEventEvObj *) m_vec.GetAt(0);
pE->OnVictory();
return S_OK;
}
Клиент на VB.
Private WithEvents obj As EvObj
Private Sub Command1_Click()
Set obj = New EvObj
obj.DoVictory
End Sub
Private Sub obj_OnVictory()
MsgBox "Victory"
End Sub
Вроде и всё. Если некоторые мне скажут, что без атрибута dual интерфейс не есть дуальный возражу следующим образом: "Дуальный интерфейс — интерфейс, методы которого можно вызывать и через IDispatch и через VTBL, что и достигнуто в данном примере. Тем более атрибут oleautomation позволит использовать стандартный маршалер.". Открытым остаётся один вопрос: "Почему VB ругнулся на dual". Попытаюсь это выяснить м доложу о результатах...
ЗЫ: Если кому вдруг понадобятся сырцы могу выслать...