|
根据IE浏览器的运行方式,有多种不同的方式可以获取文档指针。
0 ? K, T$ q9 N
. g5 p9 ^! \* t: q# s <1> 如果你在程序中使用MFC的 CHtmlView 视来浏览网页。* X0 a3 E9 K8 Z; ]
取得文档的方法最简单,调用 CHtmlView::GetHtmlDocument() 函数。
. s, O% z& n1 E- `2 X) h' k* r <2> 如果你的程序中使用了“Web 浏览器” 的ActiveX 控件。
, q. e. W* Q* J$ U 取得文档的方法也比较简单,调用 CWebBrowser2::GetDocument() 函数。
2 q( a9 E3 B" S! S1 H; ^; X# d <3> 如果你的程序是用 ATL 写的 ActiveX 控件。2 o0 ] z3 r( S
那么需要调用 IOleClientSite::GetContainer 得到 IOleContainer 接口,然后就可以通过 QueryInterface() 查询得到 IHTMLDocument2 的接口。主要代码如下:
0 a. O3 P% k4 O/ W: F4 i9 c( ?4 g- p' I
CComPtr < IOleContainer > spContainer;
) c+ \! w" W" H. Y- |* h7 bm_spClientSite->GetContainer( &spContainer );4 G- b8 J5 p* _6 ]3 k
CComQIPtr < IHTMLDocument2 > spDoc = spContainer;
1 _* M# j7 _1 V( \* W) S3 cif ( spDoc )
5 Q2 x0 A1 d) m, R7 r/ h! V& A{8 Q! H! v8 O* F. r7 a
// 已经得到了 IHTMLDocument2 的接口指针2 ]7 C* V- {/ K' H
}
3 W$ T/ t0 X% }8 S$ F( ~6 @! x
: g# ^) @$ b* Q' h" E& M <4> 如果你的程序是用 MFC 写的 ActiveX 控件。
, e( `0 D5 m% i* {) \) p5 t 那么需要调用 COleControl::GetClientSite() 得到 IOleContainer 接口,然后的操作和<3>是一致的了。! |5 y" A1 Y& U
<5> IE 浏览器作为独立的进程正在运行。$ P" n1 p/ B$ u! y4 p2 n" E9 v
每个运行的浏览器(IE 和 资源浏览器)都会在 ShellWindows 中进行登记,因此我们要通过 IShellWindows 取得实例(示例程序中使用的就是这个方法)。主要代码如下:
% A9 v4 R& B- o L9 Y0 c4 Q; e. x9 u8 G, J+ D6 p8 F& `, U
#include < atlbase.h >
5 r! i* ^" R! z/ X' @#include < mshtml.h >5 ` _% [$ ?$ q1 e) A/ l
+ ~7 J- Y, q" k
void FindFromShell()
; P& g& h5 k8 ~! r0 ?2 @+ T4 |+ q{% L' b" o$ M7 e; l# h7 f) l" }
CComPtr< IShellWindows > spShellWin;
0 M# M& q6 f) s' e HRESULT hr = spShellWin.CoCreateInstance( CLSID_ShellWindows );4 `6 F. k \: ]" [: f( S
if ( FAILED( hr ) ) return;$ k6 l) k, G7 Q0 g& ~
( K' ]9 U) z4 y) a
long nCount=0;$ r9 j4 E) X- {' S
spShellWin->get_Count(&nCount); // 取得浏览器实例个数# Z6 Y g% v# V+ x
- C4 d/ K( U3 W7 _3 O& [/ c
for(long i=0; i<nCount; i++)* O V. O' u, ]. ]! r
{
) J* Q( `: E+ C3 B! s CComPtr< IDispatch > spDisp;
" q4 ^/ Q. k8 c7 q hr=spShellWin->Item(CComVariant( i ), &spDisp );
3 ^) l1 b8 k+ h: L if ( FAILED( hr ) ) continue;
7 O4 ]# z. v' b
3 u6 N' J. y' L CComQIPtr< IWebBrowser2 > spBrowser = spDisp;: Z `* J/ E$ [3 U
if ( !spBrowser ) continue;$ f3 Q* u+ i. S3 x( E$ J4 \* }4 p
5 y& V9 H1 f+ q; j, M spDisp.Release();
/ J+ Y8 z6 j) V1 t5 b hr = spBrowser->get_Document( &spDisp );
/ H d6 D/ w) q' a9 Q if ( FAILED ( hr ) ) continue;' z+ j6 }1 d1 W; h" @2 X; s
' q" w. T0 D9 `# p2 t6 _$ T& t; o CComQIPtr< IHTMLDocument2 > spDoc = spDisp;/ x: u1 l! j) K7 J( [% W" `
if ( !spDoc ) continue;+ ?' S$ G S' o" q2 H$ V. C
$ t" n) O, D/ M& @0 Q& S
// 程序运行到此,已经找到了 IHTMLDocument2 的接口指针
/ Y8 b% r' U* h, p; z }
' O# ]2 q. r3 k+ M5 S/ h}
, @* D! J' f( f0 s* ^7 x3 c
3 a6 C3 k) m2 `1 K M( s; t <6> IE 浏览器控件被一个进程包装在一个子窗口中。那么你首先要得到那个进程的顶层窗口句柄(使用 FindWindow() 函数,或其它任何可行的方法),然后枚举所有子窗口,通过判断窗口类名是否是“Internet Explorer_Server”,从而得到浏览器的窗口句柄,再向窗口发消息取得文档的接口指针。主要代码如下: ( z9 {5 m; ?1 c X; P8 h! P
/ A; V5 ~2 E+ D% w
6 b% Q4 F8 t4 J7 C8 T* I; [
#include < atlbase.h >" l0 f0 D4 D ]* R- k
#include < mshtml.h >
7 B( o5 y+ c6 D% j& J#include < oleacc.h >1 L* }1 ~0 @, G) Y% }+ z. O
#pragma comment ( lib, "oleacc" )
$ f1 j9 p8 x" ~! |+ A' T0 i. P8 C
BOOL CALLBACK EnumChildProc(HWND hwnd,LPARAM lParam)
8 J# S. h# u* V{
% y' C, G4 N) F( R+ m TCHAR szClassName[100];
( U. N4 O/ J& i6 b4 [5 C9 M0 V1 |7 w; _) X+ O E
::GetClassName( hwnd, &szClassName, sizeof(szClassName) );
1 o4 X) m7 W! K2 a- D! l' M# g0 q" r; I if ( _tcscmp( szClassName, _T("Internet Explorer_Server") ) == 0 )
1 m* D: I# }& G {
! E6 ?7 d3 t8 }. _- K2 l% Q *(HWND*)lParam = hwnd;
2 ?1 a9 w# r2 Z- ]: c6 U: [ return FALSE; // 找到第一个 IE 控件的子窗口就停止
+ e% A q9 t# k1 F, w8 Z1 Q7 v }
# A F+ C* O8 K3 x9 t; b2 d else return TRUE; // 继续枚举子窗口 n: b& f- s; B' r
};: |0 p' a; n, k2 P! F
9 M3 }7 X. i p+ B; F
void FindFromHwnd(HWND hWnd) 2 x6 [2 Z+ h* z/ Q( N1 V0 Z/ R
{
) o3 u) }6 `+ V# z5 f, K HWND hWndChild=NULL;
7 J4 b J! X' G% w9 P; y) ]0 x ::EnumChildWindows( hWnd, EnumChildProc, (LPARAM)&hWndChild );
. T4 p6 y9 {4 E2 S \% V ]8 l if(NULL == hWndChild) return;+ E9 v2 J& E! S+ s) } T
( o7 n; C Y6 K) q5 \/ O
UINT nMsg = ::RegisterWindowMessage( _T("WM_HTML_GETOBJECT") );
9 n: J$ s4 a5 n3 c! h LRESULT lRes;; \. {) Q2 V2 |
::SendMessageTimeout( hWndChild, nMsg, 0L, 0L, SMTO_ABORTIFHUNG, 1000, (DWORD*) &lRes );9 J2 W0 C5 L6 m
0 P' `4 h! S" }$ g: `
CComPtr < IHTMLDocument2 > spDoc;
- g6 G( a0 O% `4 l* p+ I5 {8 ]9 c: O HRESULT hr = ::ObjectFromLresult ( lRes, IID_IHTMLDocument2, 0 , (LPVOID *) &spDoc );6 j& b+ i" l6 I+ C" [
if ( FAILED ( hr ) ) return;
; R) P+ Z" s/ Y( Z( G
; h- D0 c1 w: y2 I+ Y9 n // 程序运行到此,已经找到了 IHTMLDocument2 的接口指针: d/ n! T9 [$ s
} |
|