пеередача структуры через VARIANT (VT_RECORD | VT_BYREF)
От: 2can  
Дата: 08.01.05 21:00
Оценка:
Пытаюсь сделать, чтобы 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#.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.