|
|
根据IE浏览器的运行方式,有多种不同的方式可以获取文档指针。# c# t1 F! B! L- O
" I2 I+ P1 v* k. C% r0 N$ ~+ o
<1> 如果你在程序中使用MFC的 CHtmlView 视来浏览网页。" t f6 r6 T3 `7 p" V! `
取得文档的方法最简单,调用 CHtmlView::GetHtmlDocument() 函数。. U+ d) V' e( `: d8 c
<2> 如果你的程序中使用了“Web 浏览器” 的ActiveX 控件。
6 C) u5 D5 P: `: d 取得文档的方法也比较简单,调用 CWebBrowser2::GetDocument() 函数。
7 _- z& U: S$ W- c* [) y <3> 如果你的程序是用 ATL 写的 ActiveX 控件。
- |) i6 L2 `8 }4 Y# [ 那么需要调用 IOleClientSite::GetContainer 得到 IOleContainer 接口,然后就可以通过 QueryInterface() 查询得到 IHTMLDocument2 的接口。主要代码如下: : j% i8 O L+ `' |. ~; c# F
6 J+ r5 H8 H' a _9 gCComPtr < IOleContainer > spContainer;
# ~* i) M% C+ f+ }- x I! k9 C) T$ Wm_spClientSite->GetContainer( &spContainer );, U7 Q8 s Q% S' K+ N7 U
CComQIPtr < IHTMLDocument2 > spDoc = spContainer;
- W& K5 J1 i8 u; Q3 Fif ( spDoc )6 {& E4 \( _1 ]8 Y% N: R
{% T; r. I" N' j3 @+ t! [# \+ b; R
// 已经得到了 IHTMLDocument2 的接口指针; S- i3 Y8 j2 b7 q
}6 A# m) I- b! K8 x9 S
. ?3 E0 q/ i% Z" @1 i3 P4 U
<4> 如果你的程序是用 MFC 写的 ActiveX 控件。
7 u; Y! @; \4 S' |! z% e 那么需要调用 COleControl::GetClientSite() 得到 IOleContainer 接口,然后的操作和<3>是一致的了。
& d1 O: c( |: c9 Z5 ?2 Y* ~) C <5> IE 浏览器作为独立的进程正在运行。! |! i3 w2 g- a/ _4 N* F
每个运行的浏览器(IE 和 资源浏览器)都会在 ShellWindows 中进行登记,因此我们要通过 IShellWindows 取得实例(示例程序中使用的就是这个方法)。主要代码如下:) X: A, ?' [/ k/ Q. ^7 ?
# e# q9 Q" Z; h k#include < atlbase.h >8 M2 X" h- X/ H2 u& B. ~; z: V9 L
#include < mshtml.h >
% _0 x4 o" V8 y" ~) J
/ z9 ~/ t5 x' |( i" X: R) bvoid FindFromShell() + k1 l7 e$ `" o* K* @
{
; c& N u4 ^$ S5 I* q9 z CComPtr< IShellWindows > spShellWin;
$ j0 U: N/ ~4 f! ]8 j" {1 l HRESULT hr = spShellWin.CoCreateInstance( CLSID_ShellWindows );
6 j0 U4 a) k* j& ]: X8 a1 c8 m if ( FAILED( hr ) ) return;
2 W a7 B. T+ Y: B5 C! L- z. f) r0 B# |1 u. y3 n& x
long nCount=0;
$ N7 y7 k& W" b( J spShellWin->get_Count(&nCount); // 取得浏览器实例个数
% M; I' m% G( ^; e3 u3 w9 F+ f8 g1 i) [
for(long i=0; i<nCount; i++); w0 O% ^4 z" w" R" h
{) ^- x% ]+ m& [
CComPtr< IDispatch > spDisp;. K1 f0 J+ F& w! G6 s* B! }1 {; r
hr=spShellWin->Item(CComVariant( i ), &spDisp );
& ^8 {+ ?6 [! U% Z if ( FAILED( hr ) ) continue;. [5 G* b7 Z& a, }
( `( X6 o- \5 k- ^4 s
CComQIPtr< IWebBrowser2 > spBrowser = spDisp;
2 ?) k2 E; P4 N4 T: ^ if ( !spBrowser ) continue; L/ F! a, O8 u) ~6 t3 g7 T
% X$ I6 P6 Q5 G' Z$ u) a0 q
spDisp.Release();
$ w/ W% s& u, }( ~! v hr = spBrowser->get_Document( &spDisp );
2 ^3 \/ i" p: t7 ~ if ( FAILED ( hr ) ) continue;
( W& e9 o# s* @9 ]5 I' Y/ n: O' a) P$ b2 K! C' R( j- O9 y1 M
CComQIPtr< IHTMLDocument2 > spDoc = spDisp;
/ T2 p0 J; S# Z9 F if ( !spDoc ) continue;
( ?4 n2 ?. {) ^4 t& x8 a' L: `
// 程序运行到此,已经找到了 IHTMLDocument2 的接口指针+ R: a: @0 k: w/ \8 J! \- E
}4 c+ p! i9 t' y3 t( J
}
4 d& z. Y; C1 }' a$ r7 r- m: g9 ?7 r
<6> IE 浏览器控件被一个进程包装在一个子窗口中。那么你首先要得到那个进程的顶层窗口句柄(使用 FindWindow() 函数,或其它任何可行的方法),然后枚举所有子窗口,通过判断窗口类名是否是“Internet Explorer_Server”,从而得到浏览器的窗口句柄,再向窗口发消息取得文档的接口指针。主要代码如下: + s' x8 s' ^ E" W; g ?4 x
. k' ~' f' s, b$ T5 R: K
0 x: A; b# G6 i3 n* n2 |
#include < atlbase.h >' o3 ^& Y# g" d B I
#include < mshtml.h >
9 ` G) M$ C& ?+ k% [( T#include < oleacc.h >% m# u+ x: @0 D
#pragma comment ( lib, "oleacc" )! B: O/ l9 o% e! j l1 ~$ {4 W
2 C* H* F$ f+ Q n/ |( _BOOL CALLBACK EnumChildProc(HWND hwnd,LPARAM lParam)
8 O& R# e+ s, q3 X- Y2 Z{
, D8 W1 Y+ P/ h Y7 Y8 z# C) d. v TCHAR szClassName[100];* v* R7 y T3 k$ r' f) m
$ T8 n( G' n" C; R- [! f. Q8 B
::GetClassName( hwnd, &szClassName, sizeof(szClassName) );' J' N7 V7 [ Q3 f2 D8 ^
if ( _tcscmp( szClassName, _T("Internet Explorer_Server") ) == 0 ). [; P- \6 B ]6 t
{( l r/ `) W. C; x# G$ q8 C
*(HWND*)lParam = hwnd;* [: d$ p* N$ }
return FALSE; // 找到第一个 IE 控件的子窗口就停止0 d+ V8 p& B9 I+ G6 {# o/ F9 G( \
}
H) J) s( g, X) a5 P$ u else return TRUE; // 继续枚举子窗口
9 I$ [) I, L. k5 k$ K; R" s! `};3 x$ h; L, e3 C4 h
8 ?& ?4 X0 E4 q( ]: x/ N) cvoid FindFromHwnd(HWND hWnd)
& t N0 |+ n7 c% V8 t' T$ H{
+ O$ q- u3 T6 F4 B! t HWND hWndChild=NULL;! ]4 W" C, d. S8 ?! \5 O
::EnumChildWindows( hWnd, EnumChildProc, (LPARAM)&hWndChild );
$ C% i2 t6 b! V# ^# U7 ~ if(NULL == hWndChild) return;. H% T6 [( v& U- e9 s+ d
}' Z. M' H V% E8 Y5 g UINT nMsg = ::RegisterWindowMessage( _T("WM_HTML_GETOBJECT") );
% z0 w% P- @2 l' P) R" L8 m7 q1 Q' c LRESULT lRes;7 {( X9 j% g) e* _4 O4 F
::SendMessageTimeout( hWndChild, nMsg, 0L, 0L, SMTO_ABORTIFHUNG, 1000, (DWORD*) &lRes );/ }; n( g) R& L: v0 T6 j; @
+ r4 U; v% n2 h: q; u/ v$ ~" G. R! G CComPtr < IHTMLDocument2 > spDoc;
( a1 h; j7 h# f3 C HRESULT hr = ::ObjectFromLresult ( lRes, IID_IHTMLDocument2, 0 , (LPVOID *) &spDoc );5 A8 V3 [2 O9 O/ Q
if ( FAILED ( hr ) ) return;1 f' `$ m7 r; `
, T% j5 ~2 U% {' `- \* C
// 程序运行到此,已经找到了 IHTMLDocument2 的接口指针; F, B3 g% L0 O+ u" y$ f
} |
|