Здравствуйте _defrager, Вы писали:
D>Делаю себе браузер на движке ie и наткнулся на такой код в MFC:
D>(Mfc7, ViewHtml.cpp, ExecFormsCommand)
D>///////////////////////////////////////// D> HRESULT hr = E_FAIL;
D> CComPtr<IHTMLDocument2> spDoc = (IHTMLDocument2*) GetHtmlDocument(); D> if (spDoc != NULL) D> { D> CComQIPtr<IOleCommandTarget> spCmdTarget = spDoc; D> if (spCmdTarget != NULL) D> hr = spCmdTarget->Exec(&CMDSETID_Forms3, dwCommandID, D> OLECMDEXECOPT_DONTPROMPTUSER, pVarOut, pVarIn); D> }
D> return hr; D>////////////////////////////////////////
D>Как я понимаю, здесь теряется один Release() , потому что Release() нужно вызвать и для spDoc, D>и для диспатча,возвращаемого GetHtmlDocument()
D>Так ведь?
Здравствуйте Dima2, Вы писали:
D>Здравствуйте _defrager, Вы писали:
D>>Делаю себе браузер на движке ie и наткнулся на такой код в MFC:
D>А для чего по твоему обертка CComPtr, а непросто IHTMLDocument2* ?
В этой строчке вызовется AddRef() для spDoc и когда spDoc выйдет из области видимости
вызовется Release() для spDoc. А где вызовется Release для LPDISPATCH который возвратит GetHtmlDocument?
Ведь если не заморачиваться с CComPtr пришлось бы писать так
///////////////
LPDISPATCH lpDisp = GetHtmlDocument()
if (lpDisp)
{
...
lpDisp->Release()
}
///////////////
Здравствуйте _defrager, Вы писали:
D>Давай считать вместе
D>CComPtr<IHTMLDocument2> spDoc = (IHTMLDocument2*) GetHtmlDocument();
D>В этой строчке вызовется AddRef() для spDoc и когда spDoc выйдет из области видимости D>вызовется Release() для spDoc. А где вызовется Release для LPDISPATCH который возвратит GetHtmlDocument?
Мда, вообще-то наверное ты прав. Посмотрел я реализацию GetHtmlDocument(), она просто берет св-во IWebBrowser2::get_Document. И уж если не предположить что get_Document не делает AddRef ???
Хотя MSDN изобилует подобного рода примерами:
#import <mshtml.tlb>
CMyAppView::LoadData()
{
AfxOleInit(); // Initialize the COM library
MSHTML::IHTMLDocument2Ptr pIDoc;
MSHTML::IHTMLElementCollectionPtr pICollection;
pIDoc = GetHtmlDocument();
....
}
IHTMLDocument2Ptr spDoc;
// Get the active document
spDoc = GetHtmlDocument();
if ( spDoc )
{
.....
Здравствуйте Dima2, Вы писали:
D>Здравствуйте _defrager, Вы писали:
D>>Давай считать вместе :)
D>>CComPtr<IHTMLDocument2> spDoc = (IHTMLDocument2*) GetHtmlDocument();
D>>В этой строчке вызовется AddRef() для spDoc и когда spDoc выйдет из области видимости D>>вызовется Release() для spDoc. А где вызовется Release для LPDISPATCH который возвратит GetHtmlDocument?
D>Мда, вообще-то наверное ты прав. Посмотрел я реализацию GetHtmlDocument(), она просто берет св-во IWebBrowser2::get_Document.
Вот-вот
D>И уж если не предположить что get_Document не делает AddRef ???
Нее...это врядли...
D>Хотя MSDN изобилует подобного рода примерами:
D>
D> IHTMLDocument2Ptr spDoc;
D> // Get the active document
D> spDoc = GetHtmlDocument();
D> if ( spDoc )
D> {
D>.....
D>
Тут еще есть вторая СЕРЬЕЗНАЯ проблема:
Я по наивности скопировал mfcшный код "CСomPtr<IHTMLDocument2> spDoc = (IHTMLDocument2*) GetHtmlDocument(); "
и получил эксепшен когда пытался вызвать put_charset у документа не поддерживающего IHTMLDocument2
из-за нелепого преобразования типа (IDispatch*) => (IHTMLDocument2*)
Здравствуйте _defrager, Вы писали:
D>>>В этой строчке вызовется AddRef() для spDoc и когда spDoc выйдет из области видимости D>>>вызовется Release() для spDoc. А где вызовется Release для LPDISPATCH который возвратит GetHtmlDocument?
D>>Мда, вообще-то наверное ты прав. Посмотрел я реализацию GetHtmlDocument(), она просто берет св-во IWebBrowser2::get_Document.
D>Вот-вот
Единственное объяснение может быть в том, что LPDISPATCH — это не IDispatch*, а IDispatchPtr, как в #import-е генерится. У меня текстов 7 нет, посмотрите. Интересно ведь.
D>Тут еще есть вторая СЕРЬЕЗНАЯ проблема:
D>Я по наивности скопировал mfcшный код "CСomPtr<IHTMLDocument2> spDoc = (IHTMLDocument2*) GetHtmlDocument(); " D>и получил эксепшен когда пытался вызвать put_charset у документа не поддерживающего IHTMLDocument2 D>из-за нелепого преобразования типа (IDispatch*) => (IHTMLDocument2*)
Это не преобразование нелепое, а использование spDoc в дальнейшем. NULL, однако!
Здравствуйте Vi2, Вы писали:
Vi2>Здравствуйте _defrager, Вы писали:
D>>>>В этой строчке вызовется AddRef() для spDoc и когда spDoc выйдет из области видимости D>>>>вызовется Release() для spDoc. А где вызовется Release для LPDISPATCH который возвратит GetHtmlDocument?
D>>>Мда, вообще-то наверное ты прав. Посмотрел я реализацию GetHtmlDocument(), она просто берет св-во IWebBrowser2::get_Document.
D>>Вот-вот
Vi2>Единственное объяснение может быть в том, что LPDISPATCH — это не IDispatch*, а IDispatchPtr, как в #import-е генерится. У меня текстов 7 нет, посмотрите. Интересно ведь.
Здравствуйте Vi2, Вы писали:
Vi2>Здравствуйте _defrager, Вы писали:
D>>Тут еще есть вторая СЕРЬЕЗНАЯ проблема:
D>>Я по наивности скопировал mfcшный код "CСomPtr<IHTMLDocument2> spDoc = (IHTMLDocument2*) GetHtmlDocument(); " D>>и получил эксепшен когда пытался вызвать put_charset у документа не поддерживающего IHTMLDocument2 D>>из-за нелепого преобразования типа (IDispatch*) => (IHTMLDocument2*)
Vi2>Это не преобразование нелепое, а использование spDoc в дальнейшем. NULL, однако!
А вот и нет!!! ССоmPtr не переходит к другому интерфейсу, т.е
при вызове CСomPtr<IHTMLDocument2> spDoc = (IHTMLDocument2*) GetHtmlDocument();
spDoc не будет равен NULL даже если IHTMLDocument2 не поддерживается, другое дело CСomQIPtr<IHTMLDocument2> spDoc = GetHtmlDocument().
Поэтому делать "(IHTMLDocument2*) GetHtmlDocument()" крайне опасно.
Здравствуйте _defrager, Вы писали:
D>А вот и нет!!! ССоmPtr не переходит к другому интерфейсу, т.е
D>при вызове CСomPtr<IHTMLDocument2> spDoc = (IHTMLDocument2*) GetHtmlDocument(); D>spDoc не будет равен NULL даже если IHTMLDocument2 не поддерживается, другое дело CСomQIPtr<IHTMLDocument2> spDoc = GetHtmlDocument().
D>Поэтому делать "(IHTMLDocument2*) GetHtmlDocument()" крайне опасно.
А! Ну да! Видимо в примере IHTMLDocument2 гарантировалось используемым объектом.
А вообще это порочная практика от МФС — кастировать к потомку от базы, для этого есть QI. В обратную сторону (от IHTMLDocument2* к IDispatch*) безопасно.
1). в этом куске
CComPtr<IHTMLDocument2> spDoc = (IHTMLDocument2*) GetHtmlDocument();
вызывается конструктор копирования, а не оператор присваения
2) даже если бы вызывался оператор присваения, Release() не вызывался бы, так как spDoc был бы равен NULL.
Вобщем похоже в 7м MFC код дорабатывался с больщого бодуна — чуть пониже нашел еще такую штуку
налядно конечно, но не сильно професианально :-\
хотя компилятор наверное все-равно из-этого сделает: *pbEnabled = cmdInfo.cmdf & OLECMDF_ENABLED;
...надо проверить