BHO-3の質問: IHTMLDocument3のQueryInterfaceが失敗する

このQ&Aのポイント
  • BHO-3のSetSite関数内で、IHTMLDocument3へのポインタ取得を試みていますが、QueryInterfaceが失敗しています。
  • しかし、同じコードの別の部分で、IWebBrowser2へのポインタ取得が成功しています。
  • この問題についてのアドバイスをお願いします。
回答を見る
  • ベストアンサー

BHO-3

いつもお世話になっています。 STDMETHODIMP CHelloWorldBHO::SetSite(IUnknown* pUnkSite) { HRESULT hr = S_OK; if (m_pSite != NULL){ m_pSite->Release(); m_pSite = NULL; } if (pUnkSite != NULL) { IHTMLDocument3 *pDocument3; HRESULT hr2 = pUnkSite->QueryInterface(IID_IHTMLDocument3, (void **)&pDocument3); if (SUCCEEDED(hr2)){ PutEventHandler(pDocument3); } ////////////////////////////// // IWebBrowser2 へのポインタをキャッシュします。 HRESULT hr = pUnkSite->QueryInterface(IID_IWebBrowser2, (void **)&m_spWebBrowser); if (SUCCEEDED(hr)) { // DWebBrowserEvents2 からのイベントをシンクに登録します。 hr = DispEventAdvise(m_spWebBrowser); if (SUCCEEDED(hr)) { m_fAdvised = TRUE; } } 上のコードの IHTMLDocument3 *pDocument3; HRESULT hr2 = pUnkSite->QueryInterface(IID_IHTMLDocument3, (void **)&pDocument3); if (SUCCEEDED(hr2)){ PutEventHandler(pDocument3); } ですが、 HRESULT hr2 = pUnkSite->QueryInterface(IID_IHTMLDocument3, (void **)&pDocument3); の部分で失敗します。 HRESULT hr = pUnkSite->QueryInterface(IID_IWebBrowser2, (void **)&m_spWebBrowser); if (SUCCEEDED(hr)) { // DWebBrowserEvents2 からのイベントをシンクに登録します。 hr = DispEventAdvise(m_spWebBrowser); if (SUCCEEDED(hr)) { m_fAdvised = TRUE; } } が、上手く動くのでまねをしたのですが上手く行きません。 すみませんが、アドバイスお願いします。

質問者が選んだベストアンサー

  • ベストアンサー
  • kumatti1
  • ベストアンサー率60% (73/121)
回答No.1

# ATLなのだから、CComQIPtr/CComBSTR /CComVariant といったクラスを活用した方が簡潔になるのでは。 IWebBrowser2*を得ているのだからDocument プロパティで取得するとか。 http://msdn.microsoft.com/en-us/library/aa752116%28v=vs.85%29.aspx

uyama33
質問者

補足

ありがとうございます。 CComQIPtr<IHTMLDocument3> pDocument3 = spDispDoc; を使った形で、関数を動かせました。 ATLは使ったことが無かったので、IE様のお叱りを受けながら(テストのたびに再起動) プログラムを作っています。 また、よろしくお願いいたします。 void STDMETHODCALLTYPE CHelloWorldBHO::OnDocumentComplete(IDispatch *pDisp, VARIANT *pvarURL) { //////////////////////////////////// IHTMLDocument2 *pDocument2; IDispatch *pDispatch; VARIANT varDispatch; m_pWebBrowser2->get_Document(&pDispatch); pDispatch->QueryInterface(IID_IHTMLDocument2, (void**)&pDocument2);//IID_PPV_ARGS(&pDocument2)); pDispatch->Release(); if (m_pMouseMoveListener != NULL) m_pMouseMoveListener->Release(); m_pMouseMoveListener = new CMouseMoveListener(m_pWebBrowser2, m_hSession); varDispatch.vt = VT_DISPATCH; varDispatch.pdispVal = m_pMouseMoveListener; pDocument2->put_onmousemove(varDispatch); m_pDocument2 = pDocument2; pDocument2->Release(); /////////////////////////////// Copy(m_pDocument2); HRESULT hr = S_OK; // IWebBrowser2 インターフェイスに照会します。 CComQIPtr<IWebBrowser2> spTempWebBrowser = pDisp; // 最上位レベルのブラウザに関連付けられたイベントかどうか。 if (spTempWebBrowser && m_spWebBrowser && m_spWebBrowser.IsEqualObject(spTempWebBrowser)) { // ブラウザから現在の document オブジェクトを取得します... CComPtr<IDispatch> spDispDoc; hr = m_spWebBrowser->get_Document(&spDispDoc); if (SUCCEEDED(hr)) { // ...HTML ドキュメントに照会します。 CComQIPtr<IHTMLDocument3> pDocument3 = spDispDoc; if (pDocument3 != NULL) { PutEventHandler(pDocument3); //GetElementData(pDocument3); //PutElementData(pDocument3); GetMailData(pDocument3); } } } }

関連するQ&A

  • BHO-2

    http://eternalwindows.jp/browser/mshtml/mshtml01.html の関数を、 http://msdn.microsoft.com/ja-jp/library/bb250489(v=vs.85).aspx のなかに組み込みたいと思っています。 BOOL CHelloWorldBHO::GetDocumentFromIE(IHTMLDocument3 **pp) { HWND hwnd; UINT uMsg; LRESULT lResult; HRESULT hr; EnumChildWindows(FindWindow(TEXT("IEFrame"), NULL), EnumChildProc, (LPARAM)&hwnd); if (hwnd == NULL){ return FALSE; } uMsg = RegisterWindowMessage(TEXT("WM_HTML_GETOBJECT")); if (!SendMessageTimeout(hwnd, uMsg, 0, 0, SMTO_ABORTIFHUNG, 1000, (LPDWORD)&lResult)){ MessageBox(NULL, L"WM_HTML_GETOBJECT", L"BHO", MB_OK); return FALSE; } hr = ObjectFromLresult(lResult, IID_IHTMLDocument3, 0, (void **)pp); if (FAILED(hr)) return FALSE; MessageBox(NULL, L"Hello World! ie-end", L"BHO", MB_OK); return TRUE; } で、 uMsg = RegisterWindowMessage(TEXT("WM_HTML_GETOBJECT")); if (!SendMessageTimeout(hwnd, uMsg, 0, 0, SMTO_ABORTIFHUNG, 1000, (LPDWORD)&lResult)){ MessageBox(NULL, L"WM_HTML_GETOBJECT", L"BHO", MB_OK); return FALSE; } の部分で失敗します。 原因はなんでしょうか・ VS2005 と Win7 を使っています。 MessageBox(NULL, L"WM_HTML_GETOBJECT", L"BHO", MB_OK); はバグの確認のため入れてあります。 アドバイスよろしくお願いします。

  • C++ でWindowsAPIを使用する際

    WindowsAPIを使用しようとしているのですが、エラーが出てうまくいきません。 もし原因が分かる方がいらっしゃれば、教えていただけると幸いです。 エラーコード: error C2787:: IFileOperation :このオブジェクトに関連付けられたGUIDがありません。 問題箇所: HRESULT CopyItem(__in PCWSTR pszSrcItem, __in PCWSTR pszDest, PCWSTR pszNewName) { // // Initialize COM as STA. // HRESULT hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE); if (SUCCEEDED(hr)) { IFileOperation *pfo; // // Create the IFileOperation interface // hr = CoCreateInstance(CLSID_FileOperation, NULL, CLSCTX_ALL, IID_PPV_ARGS(&pfo));  //※ここでエラー発生  if (SUCCEEDED(hr)) { // // Set the operation flags. Turn off all UI from being shown to the // user during the operation. This includes error, confirmation, // and progress dialogs. // hr = pfo->SetOperationFlags(FOF_NO_UI); if (SUCCEEDED(hr)) { // // Create an IShellItem from the supplied source path. // IShellItem *psiFrom = NULL; hr = SHCreateItemFromParsingName(pszSrcItem, NULL, IID_PPV_ARGS(&psiFrom)); if (SUCCEEDED(hr)) { IShellItem *psiTo = NULL; if (NULL != pszDest) { // // Create an IShellItem from the supplied // destination path. // hr = SHCreateItemFromParsingName(pszDest, NULL, IID_PPV_ARGS(&psiTo)); } if (SUCCEEDED(hr)) { // // Add the operation // hr = pfo->CopyItem(psiFrom, psiTo, pszNewName, NULL); if (NULL != psiTo) { psiTo->Release(); } } psiFrom->Release(); } if (SUCCEEDED(hr)) { // // Perform the operation to copy the file. // hr = pfo->PerformOperations(); } } // // Release the IFileOperation interface. // pfo->Release(); } CoUninitialize(); } return hr; よろしくお願いします。

  • C++の継承と呼び出しについて

    C++について COMとMediaFoundationについて勉強中ですが、継承とオーバーライド の部分で混乱してしまったので、アドバイスをお願いします。 IUnknownクラスは、三つの純粋仮想関数を持っていて、 virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppvObject)=0; virtual ULONG STDMETHODCALLTYPE AddRef(void)=0; virtual ULONG STDMETHODCALLTYPE Release(void)=0; の三つがあることがわかりました。 そのIUnknownクラスを継承したIMFAsyncCallback、 IMFAsyncCallbackをさらに継承したCPlayerクラスがあります。 CPlayerクラスの中でCPlayer::QueryInterfaceの定義・処理が記述されています。 ここで、ほかのCPlayerクラスの関数内で IUnknownのインスタンス->QueryInterface(引数) ; で呼び出された場合、 CPlayer::QueryInterfaceには飛ばないのでしょうか? 何度ブレークポイントを張ってもきていないので、 いったいどこで処理が行われているか不思議で仕方ないです。 というかIUnknownのインスタンスが作れていることすら疑問です。。。 よろしくお願いします。

  • 描画について

    サイズを綺麗に描画したいのですが(サイズの範囲(rightとbottom)が微妙にずれている)どうしたら描画できるでしょうか? ここら辺かな?と思うところを載せます。 HRESULT ReadBMP(ID3DXSprite** g_pSprite,LPCTSTR lpszFilename,DDXTEX* g_pTexture) { HRESULT hr = S_FALSE; UINT uLevel = 0; IDirect3DSurface9* pSurface = NULL; lstrcpy(g_pTexture->m_Filename,lpszFilename); g_pTexture->m_clrAlpha=g_colorKey; g_pTexture->m_pTexture=NULL; // スプライト情報の生成 if (SUCCEEDED(hr)) hr = ::D3DXCreateSprite(g_pd3dDevice, g_pSprite); if (SUCCEEDED(hr)) hr = ::D3DXCreateTextureFromFileEx(g_pd3dDevice, g_pTexture->m_Filename, 680, 460, 1, D3DUSAGE_RENDERTARGET, D3DFMT_UNKNOWN, D3DPOOL_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, g_pTexture->m_clrAlpha, NULL, NULL, &g_pTexture->m_pTexture); if (SUCCEEDED(hr)) hr = g_pTexture->m_pTexture->GetSurfaceLevel(uLevel, &pSurface); // サーフェイス取得 if (SUCCEEDED(hr)) hr = pSurface->GetDesc(&g_sSurfaceInfo); if (pSurface != NULL) pSurface->Release(); pSurface = NULL; // 失敗したら破棄 if (FAILED(hr)) DestroySplite(*g_pSprite,g_pTexture); return hr; } よろしくお願いします。

  • IUnknown_QueryService ?

    IUnknown_QueryService(pUnkSite, SID_SWebBrowserApp,IID_IWebBrowser2, (void**)&m_pWebBrowser2);// IID_PPV_ARGS(&m_pWebBrowser2));  これを古い形に書き換えるとどうなるのでしょうか? 'IUnknown_QueryService': 識別子が見つかりませんでした とメッセージが出ています。 For those versions of Microsoft Windows that do not include IUnknown_QueryService in Shlwapi.h, this function must be called directly from Shlwapi.dll using ordinal 176. となっています。  よろしくお願いします。

  • C++6.0における動画再生プログラムについて

    動画再生プログラムを作成したのですが、実行するとファイルから選択して動画を再生という形になっています。 ここでやりたいこととしては、実行するとプログラム内で指定したファイルがすぐ再生できるようなプログラムに改良したいと思っています。 どこを改良したらよいかわからないので、どなたか教えていただけませんでしょうか?以下が作成したプログラムです。 #include <windows.h> #include <string.h> #include <dshow.h> //DirectShowのさまざまな準備 #include <conio.h> //getch()用 #include <stdio.h>//インターフェース用のポインタ IGraphBuilder * pigb = NULL; IMediaControl * pimc = NULL; void main (){ OPENFILENAME fname; static char fn [256]; memset ( &fname, 0, sizeof (OPENFILENAME) ) ; fname.lStructSize = sizeof (OPENFILENAME) ; fname.lpstrFile = fn; fname.nMaxFile = sizeof (fn) ; fname.Flags= OFN_FILEMUSTEXIST |OFN_HIDEREADONLY; if ( !GetOpenFileName ( &fname ) ) return ; WCHAR filename [MAX_PATH] ; HRESULT hr; CoInitialize (NULL) ;//ファイル名の変換 MultiByteToWideChar ( CP_ACP, 0, fn, -1, filename, MAX_PATH ) ; //FilterGraphの初期化,GraphBuilderインターフェースを得る hr = CoCreateInstance ( CLSID_FilterGraph, NULL,CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void**) &pigb) ; if (SUCCEEDED (hr) ){//MediaControlインターフェースを得る pigb -> QueryInterface ( IID_IMediaControl, (void**) &pimc ) ; //再生するファイルを指定 hr = pigb -> RenderFile ( filename, NULL ) ; if (SUCCEEDED ( hr ) ){//再生 pimc -> Run () ; printf ("\n 再生中です、再生終了後どれかキーを押してください.") ; getch() ; } } //FilterGraphの開放 if ( pigb )pigb -> Release () ; if ( pimc )pimc -> Release () ; CoUninitialize () ; return ; }

  • RENDERFILEについての質問です

    今現在、DIRECTSHOWで動画でいろいろしてみようと思ったのですが、壁に当たりました。 デバッグ無しで開始すると、 RenderFile hr 40258と表示されます。 ソースですが関連するところを書くと #include <windows.h> #include <string.h> #include <dshow.h> // DirectShowのヘッダファイル #include <qedit.h> // SampleGrabber用 #include <conio.h> // getch()用 #include <stdio.h> #include "list502.h" #pragma warning(disable:4996) void main( void ) { // インターフェース用のポインタ // フィルタグラフ用 IGraphBuilder *pigb = NULL; IMediaControl *pimc = NULL; IMediaSeeking *pims = NULL; // サンプルグラバ用 IBaseFilter *pF = NULL; ISampleGrabber *pGrab = NULL; // これらは後で解放すること。 IMG0 img00; // 表示ウィンドウ用の構造体 BYTE *buffer; // 外部バッファ AM_MEDIA_TYPE amt; WCHAR filename[ MAX_PATH ]; HRESULT hr; img00.hi = (HINSTANCE)GetWindowLong( HWND_DESKTOP, GWL_HINSTANCE ); img00.x = 100; img00.y = 100; gr_reg(); // 表示用ウィンドウの登録 CoInitialize(NULL); // COMの準備 // FilterGraphの初期化 CoCreateInstance( CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void **)&pigb); // フィルタグラフのインターフェースを得る pigb -> QueryInterface( IID_IMediaControl, (void **)&pimc ); pigb -> QueryInterface( IID_IMediaSeeking, (void **)&pims ); // グラバフィルタを作りフィルタグラフに追加 CoCreateInstance( CLSID_SampleGrabber, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (LPVOID *)&pF); pF -> QueryInterface( IID_ISampleGrabber, (void **)&pGrab ); pigb -> AddFilter( pF, L"SamGra" ); // グラバフィルタの挿入場所の特定のための設定 ZeroMemory( &amt, sizeof(AM_MEDIA_TYPE) ); amt.majortype = MEDIATYPE_Video; amt.subtype = MEDIASUBTYPE_RGB24; amt.formattype = FORMAT_VideoInfo; pGrab -> SetMediaType(&amt); OPENFILENAME fname; static char fn[256]; memset(&fname, 0, sizeof(OPENFILENAME)); fname.lStructSize = sizeof(OPENFILENAME); fname.lpstrFile = fn; // パス付きファイル名が格納されるアドレス fname.nMaxFile = sizeof(fn); fname.Flags = OFN_FILEMUSTEXIST | OFN_HIDEREADONLY; if( ! GetOpenFileName( &fname ) ) return ; // ファイル名の変換 MultiByteToWideChar( CP_ACP, 0, fn, -1, filename, MAX_PATH ); // 再生するファイルを指定、この時点で使用するフィルタが決まる hr = pigb -> RenderFile( filename, NULL ); printf( "RenderFile hr %x\n", hr ); if(hr != 0) return; ポイント箇所は WCHAR filename[ MAX_PATH ]; hr = pigb -> RenderFile( filename, NULL ); printf( "RenderFile hr %x\n", hr ); hrが0だと、成功を意味していると思います。それ以外だとリターンで終了します。 強引にhr=0で強引に0にしてみたら Just-in-Timeで例外が発生しました。これは強引に0にしたからだと思います。 %xは16進数を意味しているはずです。 余談ですが、動画ファイル以外(テキストファイルなど)を開くと hr=80040625と出ます。 この数字(16進)はエラーコードなのでしょうか? どうかhrが40258になってしまう理由および解決策をお教え下さい。 お願いいたします。

  • DirectInputについて

    C++でDirectinputの事なのですが。 デバッグには成功するのに、起動した後すぐ強制終了してしまいます。 VOID KeyCheck() { BYTE KeyState[256]; HRESULT hr; hr = g_lpDIDevice->GetDeviceState(256,KeyState); if (SUCCEEDED(hr)) { if (KeyState[DIK_LEFT]&0x80) muki=0; } else hr = g_lpDIDevice->Acquire(); } directxの勉強に簡単なものを書いてみようと思ったのですが、どの辺りがいけないのでしょうか?

  • IDLファイルからソースファイルの実装方法について

    MessageDll.idlファイルで以下のようにコードを書いて、コンパイルしてできた MessageDll_h.hをインクルードして、 MessageComponent.cppに以下のように記述しました。 実装方法を教えてください。 また、間違っている所は指摘して頂きたいです。 DllRegisterServerとか足りない所はありますが、class内部だけでもお願いします。 お願いします。 //MessageDll.idl import "oaidl.idl"; import "ocidl.idl"; [uuid(7BBCC3A6-033D-4306-BC3D-EA358549F30F),version(1.0)] library ComputerLibrary { importlib("stdole2.tlb"); [uuid(9CAEC929-7E14-4af3-80EE-3D4EFECB3DCC), object] interface IMessage : IUnknown { HRESULT Message(); }; [uuid(0689B073-989C-483c-9757-0770F90A8C86)] coclass MessageClass { [default] interface IMessage; }; }; //MessageComponent.cpp #include"MessageDll_h.h" class MessageClass : public IMessage { public: HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppvObject) { // 指定されたIID(Interface ID)に応じて、そのインターフェースポインタを // *ppvObjectに渡してやります。 if (IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_IMessage)) { *ppvObject = static_cast<IMessage *>(this); } else { *ppvObject = NULL; return E_NOINTERFACE; } return S_OK; } ULONG STDMETHODCALLTYPE AddRef() { // 今は何もしません。 return 0; } ULONG STDMETHODCALLTYPE Release() { // Release関数は、その名の通りコンポーネントの開放を行います。 delete this; return 0; } HRESULT STDMETHODCALLTYPE Message() { MessageBox(NULL,"Hello World","",MB_OK); return 0; } };

  • MSHTMLにまつわる領域の確保、解放

    C++BuilderXE2です。vc++2010でも同様と思います。 下記のコード(抜粋)でも曲がりなりにも動くようなのですが、pDoc,pBody,strContent で使用する領域の確保、解放が問題ないのか疑問です。 pBody,strContentはpDocの一部を返すだけならば、pDocが確保されておれば、確保は不要となるのですが。 然らばpDocはDocument->QueryInterfaceで確保されているのでしょうか。 これらの関係で、必要十分な記述を教えて下さい。 なお、これらのIEにまつわる操作はMSHTMLというらしいですが、この元となる仕様などの情報場所はわかりませんか。 void TForm1::gethtml(void) { IHTMLDocument2* pDoc; IHTMLElement* pBody; BSTR strContent; if(CppWebBrowser1->Document==NULL) return; if(SUCCEEDED(CppWebBrowser1->Document->QueryInterface(IID_IHTMLDocument2, (void**)&pDoc))) { pDoc->get_body(&pBody); pBody->get_innerHTML(&strContent); pDoc->close(); pDoc->Release(); Memo1->Lines->Add(AnsiStr(strContent)); // strContentの処理を代表したもの。 } }

専門家に質問してみよう