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 нет требуемого метода или свойства.
Здравствуйте, 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 - это диспинтерфейс
А>При подключении к событиям я исп. в IConnectionPointContainer GUID_IID интерфейса DWebBrowserEvent2, соответственно и ITypeInfo беру с тем же GUID_IID
DWebBrowserEvent2 — это чистый диспинтерфейс. Он не имеет таблицы функций (как другие интерфейсы — не-диспинтерфейсы), а также не имеет данных, доступных через указатель.
Каким же образом ITypeInfo-объект поможет тебе в обработке запроса?
Только вызвав p->IDispatch::Invoke(...), передав туда все свои параметры, чтобы этот твой Invoke вызвал соответствующую функцию. Но, как правило, DispInvoke вызывается в обработчике IDispatch::Invoke, то, и это разумно, на чистых диспинтерфейсах он возвращает ошибку. Иначе будет бесконечный цикл, не так ли?
Что делать? Реализовывать обработчик по-другому, не через DispInvoke. По-моему, есть какие-то Wizard-ы Студии по реализации таких интерфейсов.
А> А как-нибудь без визардов и всякого такого ???? (я пишу без исп. 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;
}
Vi2>Тогда самому реализовывать каждый метод интерфейса DWebBrowserEvent2, преобразовывая переданные параметры (учитывая, что параметры передаются в обратном порядке, чем они объявлены в IDL):
Есть еще вариант — сделать дуальный интерфейс, который имеет такие же методы как в DWebBrowserEvent2. В карте твоего объекта указать, что интерфейс DWebBrowserEvent2 реализуется этим дуальным интерфейсом. И использовать тогда DispInvoke с typeinfo этого дуального интерфейса и его указателем. Тогда может примениться обычная техника реализации интерфейса.
Здравствуйте, Vi2, Вы писали:
Vi2>Тогда самому реализовывать каждый метод интерфейса DWebBrowserEvent2, преобразовывая переданные параметры (учитывая, что параметры передаются в обратном порядке, чем они объявлены в IDL):
Всё правильно — я так и делаю, но при этом не получается отослать параметры обратно серверу через pDispParams
Неееее.... не работает
для dispid = 251 (onNewWindow) изменяю последний параметр (pdispparams->rgvarg[0]) на true.......
короче копирую этот код в свою прогу и всё равно открываются новые окна !!
Мне кажется, что в конце реализации IDispatch::Invoke нужно вызывать реальный Invoke сервера с изменённым pdispparams.
Re[8]: ВСЁ ОТЛИЧНО !!!!!!!!!!!!!!!!
От:
Аноним
Дата:
03.06.03 13:13
Оценка:
Здравствуйте, Vi2, Вы писали:
Vi2>Ты имеешь в виду параметры [in,out], переданные тебе? Там нет ничего сложного. Vi2>
Заработало !
Вот только что-то я не совсем пойму зачем тут нужен while ?
И главное во втором if-е не "!=", а "==" ...... и всё прекрасно работает.
Большое спасибо !
А>Вот только что-то я не совсем пойму зачем тут нужен while ?
Достаточно и одного if-а. Больше чем один уровень не предусматривается. Хотя кто его знает...
А>И главное во втором if-е не "!=", а "==" ...... и всё прекрасно работает.
Писал на коленке и не проверил. А должен был!
if( (pCancelVariant->vt & VT_BYREF) == 0)
pCancel = &pCancelVariant->boolVal; // Здесь хранится само значение (без VT_BYREF)else
pCancel = pCancelVariant->pboolVal; // Здесь хранится указатель на значение (с VT_BYREF)