Пытаюсь сделать, чтобы ActiveX-control кидал событие о том, что ему нужны данные,
а container (с#) ловил это событие и заполнял структуру, передаваемую в параметре.
В TLB описано примерно следующее:
library ATLNEWGRIDLib
{
// Horizontal Text Alignment
typedef enum
{
grOrizAlignLeft = 0, //DT_LEFT
grOrizAlignRight = 1, //DT_RIGHT
grOrizAlignCenter = 2 //DT_CENTER
} grOrizontalAlignment;
// Vertical Text Alignment
typedef enum
{
grVertAlignBottom = 0, //DT_BOTTOM
grVertAlignTop = 1, //DT_TOP
grVertAlignCenter = 2 //DT_VCENTER
} grVerticalAlignment;
typedef
[uuid(1A6B865F-58C4-11D3-B221-006097FEBF00)]
struct LOGFONTNEW
{
LONG lfHeight;
LONG lfWidth;
LONG lfEscapement;
LONG lfOrientation;
LONG lfWeight;
BYTE lfItalic;
BYTE lfUnderline;
BYTE lfStrikeOut;
BYTE lfCharSet;
BYTE lfOutPrecision;
BYTE lfClipPrecision;
BYTE lfQuality;
BYTE lfPitchAndFamily;
BYTE lfFaceName[32];
} LOGFONTNEW;
typedef
[uuid(1A6B865E-58C4-11D3-B221-006097FEBF00)]
struct GV_ITEM
{
int row; // Row and
int col; // Column of item
UINT mask; // Mask for use in getting/setting cell data
UINT nState; // cell state (focus/hilighted etc)
DWORD nFormat; // Format of cell
int iImage; // index of the list view item’s icon
COLORREF crBkClr; // Background colour (or CLR_DEFAULT)
COLORREF crFgClr; // Forground colour (or CLR_DEFAULT)
COLORREF crHlBkClr; // Highlight background colour (or CLR_DEFAULT)
COLORREF crHlFgClr; // Highlight forground colour (or CLR_DEFAULT)
grOrizontalAlignment hAlign;
grVerticalAlignment vAlign;
LPARAM lParam; // 32-bit value to associate with item
LOGFONTNEW lfFont; // Cell font
UINT nMargin; // Internal cell margin
int * strText; // Text in cell
} GV_ITEM;
[
uuid(466C80A1-58C4-11D3-B221-006097FEBF00),
helpstring("_IGridEvents Interface")
]
dispinterface _IGridEvents
{
methods:
[id(11), helpstring("method GetVirtual")] HRESULT GetVirtual(int row, int col, GV_ITEM* item);
};
}
Соответсвенно Proxy-класс для того, чтобы "fire"-ить событие:
template <class T>
class CProxy_IGridEvents : public IConnectionPointImpl<T, &DIID__IGridEvents, CComDynamicUnkArray>
{
public:
HRESULT Fire_GetVirtual(int row, int col, GV_ITEM* item)
{
CComVariant varResult = VT_EMPTY;
T* pT = static_cast<T*>(this);
int nConnectionIndex;
CComVariant* pvars = new CComVariant[3];
int nConnections = m_vec.GetSize();
for (nConnectionIndex = 0; nConnectionIndex < nConnections; nConnectionIndex++)
{
pT->Lock();
CComPtr<IUnknown> sp = m_vec.GetAt(nConnectionIndex);
pT->Unlock();
IDispatch* pDispatch = reinterpret_cast<IDispatch*>(sp.p);
if (pDispatch != NULL)
{
VariantClear(&varResult);
pvars[2].vt = VT_I4;
pvars[2].lVal = row;
pvars[1].vt = VT_I4;
pvars[1].lVal = col;
HRESULT hr;
GUID GUID_GV_ITEM = {0x1A6B865E, 0x58C4, 0x11D3, {0xB2, 0x21, 0x00, 0x60, 0x97, 0xFE, 0xBF, 0x00}};
CComPtr<IRecordInfo> spRecInfo;
hr = GetRecordInfoFromGuids( LIBID_ATLNEWGRIDLib,
1, 0,
LOCALE_USER_DEFAULT,
GUID_GV_ITEM,
&spRecInfo );
if(FAILED(hr))
{
_com_issue_errorex(hr, NULL, IID_NULL);
}
pvars[0].vt = VT_RECORD | VT_BYREF;
pvars[0].pvRecord = (PVOID)item;
pvars[0].pRecInfo = spRecInfo;
DISPPARAMS disp = { pvars, NULL, 3, 0 };
UINT argerr;
hr = pDispatch->Invoke(11, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &disp, &varResult, NULL, &argerr);
}
}
delete[] pvars;
return varResult.scode;
}
}
вот там, где отмечено — возникает проблема.
hr == 0x80028019 [Old format or invalid type library.]
пробовал менять определения структуры в TLB, потому что где-то читал, что может глючить MIDL-compiler, и что надо повесить uuid не на typedef, а на саму структуру. но это дает лишь
hr == 0x8002802b [Element not found.]
есть идеи? может можно вообще обойтись без IRecordInfo?
пробовал делать это не Event-ом, а просто CALLBACK-функцией, но видимо это не предусмотренный способ, потому что возникали непонятные run-time first chance exceptions где-то внутри COM объекта, видимо, связанные с работой GC в C#.