以下サイトを参考に、後述のプログラムを作成しました。
https://www.usefullcode.net/2006/12/ieihtmldocument2.html
プログラムは正常に動作しているのですが、
後続の疑問点が解消できない為、
ご存じの方がおりましたら、ご回答をお願いいたします。
言語:C++
環境:Windows10 64bit / Visual Studio 2019
作成したプログラム
C++
1#include <atlstr.h> 2#include <exdisp.h> 3#include <mshtml.h> 4 5bool GetHTMLDocument2FromHWND(HWND hWnd, IHTMLDocument2** ppIHTMLDocument2, bool bHwndIsServer = true) 6{ 7 HINSTANCE hInst; 8 LRESULT lRes; 9 UINT nMsg; 10 LRESULT ret; 11 12 LPFNOBJECTFROMLRESULT pfObjectFromLresult; 13 14 if (ppIHTMLDocument2 == NULL || hWnd == NULL || IsWindow(hWnd) == FALSE) 15 return false; 16 17 if (bHwndIsServer == false) 18 { 19 hWnd = FindWindowEx(hWnd, NULL, _T("Internet Explorer_Server"), NULL); 20 if (hWnd == NULL) 21 return false; 22 } 23 24 hInst = LoadLibrary(_T("OLEACC.DLL")); 25 if (hInst == NULL) 26 return false; 27 28 nMsg = RegisterWindowMessage(_T("WM_HTML_GETOBJECT")); 29 ret = SendMessageTimeout(hWnd, nMsg, 0, 0, SMTO_ABORTIFHUNG, 1000, (DWORD*)&lRes); 30 if (ret == 0) 31 return false; 32 33 pfObjectFromLresult = (LPFNOBJECTFROMLRESULT)GetProcAddress(hInst, "ObjectFromLresult"); 34 if (pfObjectFromLresult) 35 (*pfObjectFromLresult)(lRes, IID_IHTMLDocument2, 0, (void**)ppIHTMLDocument2); 36 37 FreeLibrary(hInst); 38 39 return *ppIHTMLDocument2 ? true : false; 40} 41 42class CDnpEnumInternetExplore 43{ 44 // EnumWindowsのコールバック関数 45 static BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam) 46 { 47 int nRet; 48 TCHAR pszName[1024]; 49 50 nRet = GetClassName(hwnd, pszName, sizeof(pszName)); 51 if (nRet == 0) 52 return TRUE; 53 54 nRet = _tcscmp(pszName, _T("IEFrame")); 55 if (nRet != 0) 56 return TRUE; 57 58 EnumChildWindows(hwnd, EnumChildProc, (LPARAM)NULL); 59 60 return TRUE; 61 } 62 63 // EnumChildWindowsのコールバック関数 64 static BOOL CALLBACK EnumChildProc(HWND hwnd, LPARAM lParam) 65 { 66 int nRet; 67 bool ret; 68 HRESULT hr; 69 BSTR bstrURL; 70 TCHAR pszName[1024]; 71 IHTMLDocument2* pIHTMLDocument2; 72 73 nRet = GetClassName(hwnd, pszName, sizeof(pszName)); 74 if (nRet == 0) 75 return TRUE; 76 77 nRet = _tcscmp(pszName, _T("Internet Explorer_Server")); 78 if (nRet != 0) 79 return TRUE; 80 81 pIHTMLDocument2 = NULL; 82 ret = GetHTMLDocument2FromHWND(hwnd, &pIHTMLDocument2); 83 if (ret == false || pIHTMLDocument2 == NULL) 84 return TRUE; 85 86 bstrURL = NULL; 87 hr = pIHTMLDocument2->get_URL(&bstrURL); 88 if (SUCCEEDED(hr)) 89 { 90 CAtlString strURL; 91 92 strURL = (WCHAR*)bstrURL; 93 SysFreeString(bstrURL); 94 95 printf("%ws\n", strURL); 96 } 97 98 pIHTMLDocument2->Release(); 99 100 return TRUE; 101 } 102 103public: 104 void EnumStart() 105 { 106 BOOL ret; 107 ret = EnumWindows(EnumWindowsProc, (LPARAM)NULL); 108 } 109}; 110 111void main() 112{ 113 CoInitialize(NULL); 114 115 CDnpEnumInternetExplore cEnum; 116 117 cEnum.EnumStart(); 118 119 CoUninitialize(); 120}
疑問点その1
ObjectFromLresult を LoadLibrary(_T"OLEACC.DLL") を用いて使用している点について疑問に思いました。
ObjectFromLresult は oleacc.h で宣言されています。
なので、#include <oleacc.h> からでも利用できるのでは?と思い、実際にやってみました。
修正後のプログラム(GetHTMLDocument2FromHWND のみ)
C++
1#include <oleacc.h> 2 3bool GetHTMLDocument2FromHWND(HWND hWnd, IHTMLDocument2** ppIHTMLDocument2, bool bHwndIsServer = true) 4{ 5 LRESULT lRes; 6 UINT nMsg; 7 LRESULT ret; 8 9 if (ppIHTMLDocument2 == NULL || hWnd == NULL || IsWindow(hWnd) == FALSE) 10 return false; 11 12 if (bHwndIsServer == false) 13 { 14 //"Shell DocObject View"へのハンドルとして処理 15 hWnd = FindWindowEx(hWnd, NULL, _T("Internet Explorer_Server"), NULL); 16 if (hWnd == NULL) 17 return false; 18 } 19 20 nMsg = RegisterWindowMessage(_T("WM_HTML_GETOBJECT")); 21 ret = SendMessageTimeout(hWnd, nMsg, 0, 0, SMTO_ABORTIFHUNG, 1000, (DWORD*)&lRes); 22 if (ret == 0) 23 return false; 24 25 HRESULT hRes; 26 hRes = ObjectFromLresult(lRes, IID_IHTMLDocument2, 0, (void**)ppIHTMLDocument2); 27 28 return *ppIHTMLDocument2 ? true : false; 29}
この場合、下記2つのエラーが発生します。
LNK2019 未解決の外部シンボル ObjectFromLresult@16 が関数 "bool cdecl GetHTMLDocument2FromHWND(struct HWND *,struct IHTMLDocument2 * *,bool)" (?GetHTMLDocument2FromHWND@@YA_NPAUHWND_@@PAPAUIHTMLDocument2@@_N@Z) で参照されました
LNK1120 1 件の未解決の外部参照
未解決の外部シンボルとのことだったので、
oleacc.h で extern "C" の記載がないのかと思いましたが、
確認した所、extern "C" は記載されていました。
C++ は不慣れなもので、根本的に使い方が間違っている可能性も否めませんが、
oleacc.h のインクルードでなく、動的に oleacc.dll を利用しているのは理由があるのでしょうか。
また、oleacc.h から該当の関数を使用する場合はどの様にコーディングしたらよいのでしょうか。
疑問点その2
LPFNOBJECTFROMLRESULT についてですが、
こちらは oleacc.h で宣言されています。
何故、oleacc.h をインクルードせずに利用できるのでしょうか。
疑問点その3
参考にしたサイトのソースでは、
EnumWindows から EnumWindowsProc_ を呼び出し、
EnumWindowsProc_ から EnumWindowsProc を呼び出していました。
個人的に、EnumWindows から EnumWindowsProc を呼び出せばよいのでは?と考え、
上述のソースコードにしたのですが、
一度 EnumWindowsProc_ を経由するのには理由があるのでしょうか。
明確な理由は作った本人にしか分からないかもしれませんが、
何かしら思い当たる点がございましたらご教示下さい。
疑問点その4
参考にしたサイトのソースでは、
::IsWindow の様に、グローバル名前空間からの解決を明示していました。
上記ソースでは衝突も起こらない為、個人的に要らないかなと考えて省略しましたが、
明示した方がよいのでしょうか。
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
退会済みユーザー
2020/07/13 05:12