почему ошибка ???
От: potin  
Дата: 01.06.03 20:54
Оценка:
Пытаюсь реализовать IDispatch::Invoke, в конце вызываю DispInvoke и.... ОШИБКА !

HRESULT hr = DispInvoke(this, m_pInfo, dispid, wFlags, pdispparams, pVarResult, pexcepinfo, puArgErr);
// hr = 0x80020003 Член группы не найден


Почему такая ошибка ???
Как лечить ???
Re: почему ошибка ???
От: Vi2 Удмуртия http://www.adem.ru
Дата: 02.06.03 06:43
Оценка:
Здравствуйте, potin, Вы писали:

P>Пытаюсь реализовать IDispatch::Invoke, в конце вызываю DispInvoke и.... ОШИБКА !

P>HRESULT hr = DispInvoke(this, m_pInfo, dispid, wFlags, pdispparams, pVarResult, pexcepinfo, puArgErr);
P>// hr = 0x80020003 Член группы не найден

P>Почему такая ошибка ? Как лечить ?

0x80020003 — это DISP_E_MEMBERNOTFOUND и означает "такого метода в этом интерфейсе нет". Почему нет?
Возможно, что дело в m_pInfo — он может описывать не тот интерфейс.
Возможно, что неверен параметр wFlags — для такого dispid нет требуемого метода или свойства.
Vita
Выше головы не прыгнешь, ниже земли не упадешь, дальше границы не убежишь! © КВН НГУ
Re[2]: почему ошибка ???
От: Аноним  
Дата: 02.06.03 13:48
Оценка:
Здравствуйте, Vi2, Вы писали:

Vi2>0x80020003 — это DISP_E_MEMBERNOTFOUND и означает "такого метода в этом интерфейсе нет". Почему нет?

Vi2>Возможно, что дело в m_pInfo — он может описывать не тот интерфейс.

При подключении к событиям я исп. в IConnectionPointContainer GUID_IID интерфейса DWebBrowserEvent2,
соответственно и ITypeInfo беру с тем же GUID_IID

Vi2>Возможно, что неверен параметр wFlags — для такого dispid нет требуемого метода или свойства.


wFlags я беру из IDispatch::Invoke(....), он туда приходит (я его не изменяю и не использую)
Re[3]: Потому что DWebBrowserEvent2 - это диспинтерфейс
От: Vi2 Удмуртия http://www.adem.ru
Дата: 02.06.03 14:15
Оценка:
Здравствуйте, Аноним, Вы писали:

А>При подключении к событиям я исп. в IConnectionPointContainer GUID_IID интерфейса DWebBrowserEvent2, соответственно и ITypeInfo беру с тем же GUID_IID

DWebBrowserEvent2 — это чистый диспинтерфейс. Он не имеет таблицы функций (как другие интерфейсы — не-диспинтерфейсы), а также не имеет данных, доступных через указатель.

Каким же образом ITypeInfo-объект поможет тебе в обработке запроса?

Только вызвав p->IDispatch::Invoke(...), передав туда все свои параметры, чтобы этот твой Invoke вызвал соответствующую функцию. Но, как правило, DispInvoke вызывается в обработчике IDispatch::Invoke, то, и это разумно, на чистых диспинтерфейсах он возвращает ошибку. Иначе будет бесконечный цикл, не так ли?

Что делать? Реализовывать обработчик по-другому, не через DispInvoke. По-моему, есть какие-то Wizard-ы Студии по реализации таких интерфейсов.
Vita
Выше головы не прыгнешь, ниже земли не упадешь, дальше границы не убежишь! © КВН НГУ
Re[4]: Потому что DWebBrowserEvent2 - это диспинтерфейс
От: Аноним  
Дата: 02.06.03 15:11
Оценка:
Здравствуйте, Vi2, Вы писали:

А как-нибудь без визардов и всякого такого ???? (я пишу без исп. ATL и MFC)
Re[5]: Тогда руками
От: Vi2 Удмуртия http://www.adem.ru
Дата: 03.06.03 04:46
Оценка:
Здравствуйте, Аноним, Вы писали:

А> А как-нибудь без визардов и всякого такого ???? (я пишу без исп. ATL и MFC)

Тогда самому реализовывать каждый метод интерфейса DWebBrowserEvent2, преобразовывая переданные параметры (учитывая, что параметры передаются в обратном порядке, чем они объявлены в IDL):
STDMETHODIMP CWebEvents::Invoke)( /*[in]*/DISPID dispidMember, /*[in]*/ REFIID /*riid*/, /*[in]*/ LCID lcid,
             /*[in]*/ WORD wFlags, /*[in,out]*/ DISPPARAMS* pdispparams,
            /*[out]*/ VARIANT *pvarResult, /*[out]*/ EXCEPINFO *pexcepinfo, /*[out]*/ UINT *puArgErr )
{
    switch( dispidMember ) // DWebBrowserEvents2
    {
    case DISPID_STATUSTEXTCHANGE: // void StatusTextChange([in]BSTR Text)
        ...
        break;

    case DISPID_PROGRESSCHANGE: // void ProgressChange([in] long Progress, [in] long ProgressMax)
        ...
        break;

    case DISPID_COMMANDSTATECHANGE: // void CommandStateChange([in] long Command, [in] VARIANT_BOOL Enable)
        ...
        break;

    ...
    }
    return S_OK;
}
Vita
Выше головы не прыгнешь, ниже земли не упадешь, дальше границы не убежишь! © КВН НГУ
Re[6]: Или заменитель
От: Vi2 Удмуртия http://www.adem.ru
Дата: 03.06.03 04:52
Оценка:
Здравствуйте, Vi2, Вы писали:

Vi2>Тогда самому реализовывать каждый метод интерфейса DWebBrowserEvent2, преобразовывая переданные параметры (учитывая, что параметры передаются в обратном порядке, чем они объявлены в IDL):

Есть еще вариант — сделать дуальный интерфейс, который имеет такие же методы как в DWebBrowserEvent2. В карте твоего объекта указать, что интерфейс DWebBrowserEvent2 реализуется этим дуальным интерфейсом. И использовать тогда DispInvoke с typeinfo этого дуального интерфейса и его указателем. Тогда может примениться обычная техника реализации интерфейса.
Vita
Выше головы не прыгнешь, ниже земли не упадешь, дальше границы не убежишь! © КВН НГУ
Re[6]: Тогда руками
От: Аноним  
Дата: 03.06.03 10:54
Оценка:
Здравствуйте, Vi2, Вы писали:

Vi2>Тогда самому реализовывать каждый метод интерфейса DWebBrowserEvent2, преобразовывая переданные параметры (учитывая, что параметры передаются в обратном порядке, чем они объявлены в IDL):


Всё правильно — я так и делаю, но при этом не получается отослать параметры обратно серверу через pDispParams
Re[7]: Тогда руками
От: Vi2 Удмуртия http://www.adem.ru
Дата: 03.06.03 11:36
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Всё правильно — я так и делаю, но при этом не получается отослать параметры обратно серверу через pDispParams

Ты имеешь в виду параметры [in,out], переданные тебе? Там нет ничего сложного.
    case DISPID_BEFORENAVIGATE2: // void BeforeNavigate2(..., [in,out] VARIANT_BOOL * Cancel)
        VARIANT *pCancelVariant = &pdispparams->rgvarg[0];
        while( (pCancelVariant->vt & VT_TYPEMASK) == VT_VARIANT )
            pCancelVariant = pCancelVariant->pvarVal;
        if( (pCancelVariant->vt & VT_TYPEMASK) == VT_BOOL )
        {
            VARIANT_BOOL *pCancel;
            if( (pCancelVariant->vt & VT_BYREF) != 0) 
                pCancel = &pCancelVariant->boolVal;
            else
                pCancel = pCancelVariant->pboolVal;
            *pCancel = VARIANT_TRUE;
        }
        else
        {
            VariantChangeType( pCancelVariant, pCancelVariant, VARIANT_NOVALUEPROP, VT_BOOL );
            pCancelVariant->boolVal = VARIANT_TRUE;
        }
        return S_OK;
Vita
Выше головы не прыгнешь, ниже земли не упадешь, дальше границы не убежишь! © КВН НГУ
Re[8]: Тогда руками
От: Аноним  
Дата: 03.06.03 11:52
Оценка:
Здравствуйте, Vi2, Вы писали:

VARIANT *pCancelVariant = &pdispparams->rgvarg[0];
ОШИБКА: '=': cannot convert from 'short' to 'short *'
Re[9]: Тогда руками
От: Аноним  
Дата: 03.06.03 12:46
Оценка:
А> VARIANT *pCancelVariant = &pdispparams->rgvarg[0];
А>ОШИБКА: '=': cannot convert from 'short' to 'short *'

ОЙ!!!
Я извиняюсь ! Не туда посмотрел — здесь ошибки нет !
Re[8]: Тогда руками
От: Аноним  
Дата: 03.06.03 12:56
Оценка:
Здравствуйте, Vi2, Вы писали:

Vi2>Ты имеешь в виду параметры [in,out], переданные тебе? Там нет ничего сложного.

Vi2>
Vi2>    case DISPID_BEFORENAVIGATE2: // void BeforeNavigate2(..., [in,out] VARIANT_BOOL * Cancel)
Vi2>        VARIANT *pCancelVariant = &pdispparams->rgvarg[0];
Vi2>        while( (pCancelVariant->vt & VT_TYPEMASK) == VT_VARIANT )
Vi2>            pCancelVariant = pCancelVariant->pvarVal;
Vi2>        if( (pCancelVariant->vt & VT_TYPEMASK) == VT_BOOL )
Vi2>        {
Vi2>            VARIANT_BOOL *pCancel;
Vi2>            if( (pCancelVariant->vt & VT_BYREF) != 0) 
Vi2>                pCancel = &pCancelVariant->boolVal;
Vi2>            else
Vi2>                pCancel = pCancelVariant->pboolVal;
Vi2>            *pCancel = VARIANT_TRUE;
Vi2>        }
Vi2>        else
Vi2>        {
Vi2>            VariantChangeType( pCancelVariant, pCancelVariant, VARIANT_NOVALUEPROP, VT_BOOL );
Vi2>            pCancelVariant->boolVal = VARIANT_TRUE;
Vi2>        }
Vi2>        return S_OK;
Vi2>


Неееее.... не работает
для dispid = 251 (onNewWindow) изменяю последний параметр (pdispparams->rgvarg[0]) на true.......
короче копирую этот код в свою прогу и всё равно открываются новые окна !!

Мне кажется, что в конце реализации IDispatch::Invoke нужно вызывать реальный Invoke сервера с изменённым pdispparams.
Re[8]: ВСЁ ОТЛИЧНО !!!!!!!!!!!!!!!!
От: Аноним  
Дата: 03.06.03 13:13
Оценка:
Здравствуйте, Vi2, Вы писали:

Vi2>Ты имеешь в виду параметры [in,out], переданные тебе? Там нет ничего сложного.

Vi2>
Vi2>    case DISPID_BEFORENAVIGATE2: // void BeforeNavigate2(..., [in,out] VARIANT_BOOL * Cancel)
Vi2>        VARIANT *pCancelVariant = &pdispparams->rgvarg[0];
Vi2>        while( (pCancelVariant->vt & VT_TYPEMASK) == VT_VARIANT )
Vi2>            pCancelVariant = pCancelVariant->pvarVal;
Vi2>        if( (pCancelVariant->vt & VT_TYPEMASK) == VT_BOOL )
Vi2>        {
Vi2>            VARIANT_BOOL *pCancel;
Vi2>            if( (pCancelVariant->vt & VT_BYREF) != 0) 
Vi2>                pCancel = &pCancelVariant->boolVal;
Vi2>            else
Vi2>                pCancel = pCancelVariant->pboolVal;
Vi2>            *pCancel = VARIANT_TRUE;
Vi2>        }
Vi2>        else
Vi2>        {
Vi2>            VariantChangeType( pCancelVariant, pCancelVariant, VARIANT_NOVALUEPROP, VT_BOOL );
Vi2>            pCancelVariant->boolVal = VARIANT_TRUE;
Vi2>        }
Vi2>        return S_OK;
Vi2>


Заработало !
Вот только что-то я не совсем пойму зачем тут нужен while ?
И главное во втором if-е не "!=", а "==" ...... и всё прекрасно работает.
Большое спасибо !
Re[9]: VT_BYREF => pboolVal
От: Vi2 Удмуртия http://www.adem.ru
Дата: 04.06.03 11:29
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Вот только что-то я не совсем пойму зачем тут нужен while ?

Достаточно и одного if-а. Больше чем один уровень не предусматривается. Хотя кто его знает...

А>И главное во втором if-е не "!=", а "==" ...... и всё прекрасно работает.

Писал на коленке и не проверил. А должен был!
if( (pCancelVariant->vt & VT_BYREF) == 0) 
  pCancel = &pCancelVariant->boolVal; // Здесь хранится само значение (без VT_BYREF)
else
  pCancel = pCancelVariant->pboolVal; // Здесь хранится указатель на значение (с VT_BYREF)
Vita
Выше головы не прыгнешь, ниже земли не упадешь, дальше границы не убежишь! © КВН НГУ
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.