пеередача структуры через 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#.
Re: пеередача структуры через VARIANT (VT_RECORD | VT_BYREF)
От: EM Великобритания  
Дата: 09.01.05 15:21
Оценка:
Здравствуйте, 2can, Вы писали:

...


Это известная бага в МИДЛе — при объявлении структуры через typedef Guid будет проассоциирован с typedef а не со структурой.
Проверь — если дело в этом, то при сборке должен валиться warning MIDL2368.
Опыт — это такая вещь, которая появляется сразу после того, как была нужна...
Re: пеередача структуры через VARIANT (VT_RECORD | VT_BYREF)
От: Den Raskovalov США http://users.livejournal.com/_denplusplus_
Дата: 10.01.05 04:48
Оценка:
Привет

2>Пытаюсь сделать, чтобы ActiveX-control кидал событие о том, что ему нужны данные,

2>а container (с#) ловил это событие и заполнял структуру, передаваемую в параметре.

В свое время отказался от использования структур, всюду перешел на полноценные объекты. Остался доволен, как слон
... << RSDN@Home 1.1.4 beta 3 rev. 207>>
Re[2]: пеередача структуры через VARIANT (VT_RECORD | VT_BYR
От: 2can  
Дата: 10.01.05 11:10
Оценка:
Здравствуйте, EM, Вы писали:

EM>Здравствуйте, 2can, Вы писали:


EM>...



EM>Это известная бага в МИДЛе — при объявлении структуры через typedef Guid будет проассоциирован с typedef а не со структурой.

EM>Проверь — если дело в этом, то при сборке должен валиться warning MIDL2368.



Да, я читал про эот баг, но MIDL молчит. Тем более я пробовал и так:


    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(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
    };
        typedef struct GV_ITEM GV_ITEM;


и монопенисуально. разница есть (я писал уже — разный код ошибки на выходе GetRecordInfoFromGuids), но всё равно не работает.
Re[2]: пеередача структуры через VARIANT (VT_RECORD | VT_BYR
От: Аноним  
Дата: 10.01.05 11:12
Оценка:
Здравствуйте, Den Raskovalov, Вы писали:

DR>Привет


2>>Пытаюсь сделать, чтобы ActiveX-control кидал событие о том, что ему нужны данные,

2>>а container (с#) ловил это событие и заполнял структуру, передаваемую в параметре.

DR>В свое время отказался от использования структур, всюду перешел на полноценные объекты. Остался доволен, как слон



Т.е. надо сделать что-то типа:

    [
        object,
        uuid(67C165D4-BE9B-11D3-9942-006097FEBF00),
        helpstring("IGridCell Interface"),
        pointer_default(unique)
    ]
    interface IGV_ITEM : IUnknown
        {
           ...
        }


и передавать как VT_UNKNOWN | VT_BYREF ???? так что ли?
Re[3]: пеередача структуры через VARIANT (VT_RECORD | VT_BYR
От: Den Raskovalov США http://users.livejournal.com/_denplusplus_
Дата: 10.01.05 13:56
Оценка:
2>>>Пытаюсь сделать, чтобы ActiveX-control кидал событие о том, что ему нужны данные,
2>>>а container (с#) ловил это событие и заполнял структуру, передаваемую в параметре.

DR>>В свое время отказался от использования структур, всюду перешел на полноценные объекты. Остался доволен, как слон



А>Т.е. надо сделать что-то типа:


А>
А>    [
А>        object,
А>        uuid(67C165D4-BE9B-11D3-9942-006097FEBF00),
А>        helpstring("IGridCell Interface"),
А>        pointer_default(unique)
А>    ]
А>    interface IGV_ITEM : IUnknown
А>        {
А>           ...
А>        }

А>


Ну да. Нужные get'ы/set'ы. Плюс тривиальную реализацию.

А>и передавать как VT_UNKNOWN | VT_BYREF ???? так что ли?


VT_UNKNOWN или просто VT_DISPATCH. А лучше вообще просто явный интерфейс указать.
... << RSDN@Home 1.1.4 beta 3 rev. 185>>
Re[4]: пеередача структуры через VARIANT (VT_RECORD | VT_BYR
От: 2can  
Дата: 10.01.05 14:14
Оценка:
Здравствуйте, Den Raskovalov, Вы писали:

DR>Ну да. Нужные get'ы/set'ы. Плюс тривиальную реализацию.


Понял! спасибо!!! попробую.


А>>и передавать как VT_UNKNOWN | VT_BYREF ???? так что ли?


DR>VT_UNKNOWN или просто VT_DISPATCH. А лучше вообще просто явный интерфейс указать.


Явно к сожалению не получится. Ведь вызов происходит через Proxy-class примерно так:


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;
        pvars[0].vt = VT_DISPATCH | VT_BYREF;
        pvars[0].ppdispVal = &item;
        DISPPARAMS disp = { pvars, NULL, 3, 0 };
        UINT argerr;
        pDispatch->Invoke(11, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &disp, &varResult, NULL, &argerr);
    }
}



Так нужно VT_DISPATCH или VT_DISPATCH | VT_BYREF ???
Re[5]: пеередача структуры через VARIANT (VT_RECORD | VT_BYR
От: Den Raskovalov США http://users.livejournal.com/_denplusplus_
Дата: 10.01.05 14:19
Оценка:
2>Так нужно VT_DISPATCH или VT_DISPATCH | VT_BYREF ???

Если ты передаешь интерфейс (и не возвращаешь), тогда конечно VT_DISPATCH
... << RSDN@Home 1.1.4 beta 3 rev. 185>>
Re[6]: пеередача структуры через VARIANT (VT_RECORD | VT_BYR
От: 2can  
Дата: 10.01.05 14:20
Оценка:
Здравствуйте, Den Raskovalov, Вы писали:

2>>Так нужно VT_DISPATCH или VT_DISPATCH | VT_BYREF ???


DR>Если ты передаешь интерфейс (и не возвращаешь), тогда конечно VT_DISPATCH


а, значит всё таки BYREF — я как раз возвращаю...
ок. спасибо!
Re[4]: пеередача структуры через VARIANT (VT_RECORD | VT_BYR
От: 2can  
Дата: 17.01.05 12:49
Оценка:
Здравствуйте, Den Raskovalov, Вы писали:

2>>>>Пытаюсь сделать, чтобы ActiveX-control кидал событие о том, что ему нужны данные,

2>>>>а container (с#) ловил это событие и заполнял структуру, передаваемую в параметре.

DR>>>В свое время отказался от использования структур, всюду перешел на полноценные объекты. Остался доволен, как слон


Спасибо большое. у меня тоже всё получилось!
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.