|
|
根据IE浏览器的运行方式,有多种不同的方式可以获取文档指针。
6 b. c' H0 c/ y: ]% F- l; c
+ _1 f% M5 ^4 F& g. I" b <1> 如果你在程序中使用MFC的 CHtmlView 视来浏览网页。
, i' } F" P/ Z- e0 L" O- ]% E 取得文档的方法最简单,调用 CHtmlView::GetHtmlDocument() 函数。
4 w8 W; J, ~: E) i, e } <2> 如果你的程序中使用了“Web 浏览器” 的ActiveX 控件。
& k% \/ Y3 u& E4 s) _1 e/ K 取得文档的方法也比较简单,调用 CWebBrowser2::GetDocument() 函数。
" m, Q) i5 A+ Y/ `4 d <3> 如果你的程序是用 ATL 写的 ActiveX 控件。. A8 @. {4 E4 C4 D8 f
那么需要调用 IOleClientSite::GetContainer 得到 IOleContainer 接口,然后就可以通过 QueryInterface() 查询得到 IHTMLDocument2 的接口。主要代码如下:
# A7 g& C9 }- p% F2 z3 I8 J8 A
' `2 r( ]) F; I9 n$ pCComPtr < IOleContainer > spContainer;
% q' H( W! z# u* R9 R: x* l2 V( e& jm_spClientSite->GetContainer( &spContainer );1 L9 v" F- \. O1 M9 |! U( y' @* D
CComQIPtr < IHTMLDocument2 > spDoc = spContainer;7 C8 H5 s$ y. g: f& H4 L% M
if ( spDoc )
0 X& E4 j1 f. P6 S3 H{- J s3 c J7 {: V+ o7 G: }$ d/ L, \, V
// 已经得到了 IHTMLDocument2 的接口指针
* Q7 O# k: R9 w" x* M# }' K}
% _# K& J! z. s1 s q" D
- M! z3 e: u( w4 d: } <4> 如果你的程序是用 MFC 写的 ActiveX 控件。
% ?4 _( q: a' H0 d 那么需要调用 COleControl::GetClientSite() 得到 IOleContainer 接口,然后的操作和<3>是一致的了。
/ E) Y J/ }2 V8 O <5> IE 浏览器作为独立的进程正在运行。( t8 T8 Z% G7 ~4 {# N
每个运行的浏览器(IE 和 资源浏览器)都会在 ShellWindows 中进行登记,因此我们要通过 IShellWindows 取得实例(示例程序中使用的就是这个方法)。主要代码如下:
. S6 M# F9 j4 N! _
! p+ B9 L/ s+ \" U( |8 F#include < atlbase.h >
5 p- P4 s( Z7 `/ s$ h+ L, `! [#include < mshtml.h >
$ y# k6 j" T& k* I! {6 J' G5 A' H& w/ |# {
void FindFromShell() 1 r+ D ]9 f8 [ j5 E% O
{: i. R2 |: \2 q1 Y3 C! G
CComPtr< IShellWindows > spShellWin;
5 e8 T1 x- u% ] HRESULT hr = spShellWin.CoCreateInstance( CLSID_ShellWindows );
+ G) d6 l3 N' Z/ n if ( FAILED( hr ) ) return;6 f. \& u! T* E# l; v
& z% x4 b" C) G8 [
long nCount=0;0 v% t8 k/ w! P
spShellWin->get_Count(&nCount); // 取得浏览器实例个数1 ?! C' M; l3 Y$ d
9 a/ X4 r _. C" E8 N! d
for(long i=0; i<nCount; i++)6 \* `4 O( M* W* L9 e' r
{( V5 a8 A- E/ ~0 c$ e/ h* F6 W
CComPtr< IDispatch > spDisp;( Q7 C9 P6 [3 Z5 o8 o9 K) B
hr=spShellWin->Item(CComVariant( i ), &spDisp );
! |- ~* H' |: \% r& Y# f if ( FAILED( hr ) ) continue;* @# c0 R7 r9 f! y
5 _) O0 h' S- c CComQIPtr< IWebBrowser2 > spBrowser = spDisp;. w; b7 j; O. d' k) X8 A& W
if ( !spBrowser ) continue;+ F6 \! K9 |3 ^8 L) ]7 C' r: I6 ?
; F$ R7 c* C& B2 } Y# B
spDisp.Release();) {7 E! N% J3 k3 V+ d* l5 X! w: L+ e
hr = spBrowser->get_Document( &spDisp );
! f* i6 _& _, M% p9 D, W | if ( FAILED ( hr ) ) continue;9 u' c7 y- e ?* _
8 t8 V1 n1 n9 N CComQIPtr< IHTMLDocument2 > spDoc = spDisp;
, H) g- i7 w; h% ~, L+ J; b if ( !spDoc ) continue;
9 F/ Q2 K g. F
' T( W- Y p Y% ~$ P+ f$ ?# d // 程序运行到此,已经找到了 IHTMLDocument2 的接口指针
4 D) M% D/ l7 U6 E$ l }1 K) J' W7 _' F6 T$ c
}
+ @( ~2 v/ Q/ X, L2 O
7 t3 i) G" {& e0 Q: i3 O6 A <6> IE 浏览器控件被一个进程包装在一个子窗口中。那么你首先要得到那个进程的顶层窗口句柄(使用 FindWindow() 函数,或其它任何可行的方法),然后枚举所有子窗口,通过判断窗口类名是否是“Internet Explorer_Server”,从而得到浏览器的窗口句柄,再向窗口发消息取得文档的接口指针。主要代码如下: 1 s" k& D5 J3 z% P1 r2 x
2 v4 {4 ?/ r& P- A8 P( V+ `0 ?- N) Q0 Z6 t$ t! g6 T
#include < atlbase.h >
; R( S6 [) d8 w2 P; A7 w#include < mshtml.h >' N9 W0 O4 m5 z T
#include < oleacc.h >
7 s( v7 f" S0 e4 O& o- T#pragma comment ( lib, "oleacc" )5 O, Y: P9 O: _
' Y: j: p6 Q) W6 v$ Y
BOOL CALLBACK EnumChildProc(HWND hwnd,LPARAM lParam)" u7 q8 j, z3 H" `
{5 r+ Y0 A9 i2 ^; S
TCHAR szClassName[100];
4 h7 P: x+ r0 v0 N
5 _9 S6 S1 z7 Y, K ::GetClassName( hwnd, &szClassName, sizeof(szClassName) );
+ a( n! }6 E" T$ e2 g( \ if ( _tcscmp( szClassName, _T("Internet Explorer_Server") ) == 0 )" M% L! H; Y2 T1 f8 \( `( ]9 |
{: H8 M k5 @6 ]3 }% f/ z/ y0 q
*(HWND*)lParam = hwnd;+ c9 i$ ^( J8 {; H {
return FALSE; // 找到第一个 IE 控件的子窗口就停止! F- O6 t5 t2 o$ C y
}
) z( f3 w& u7 j8 m else return TRUE; // 继续枚举子窗口( j& ?; J; y7 x7 z
};" N- G0 z) b- X
! Q! A+ e. ?2 z% M& W5 g
void FindFromHwnd(HWND hWnd) ) M3 U- U k5 Q' W
{
$ ]! T5 T- ^, s' @6 L HWND hWndChild=NULL;
, a/ E& \: M% p$ r ::EnumChildWindows( hWnd, EnumChildProc, (LPARAM)&hWndChild );1 M9 }: k: m- ]* X3 I: M U8 O
if(NULL == hWndChild) return;6 L! F3 }8 J/ F$ D0 y* @
. p9 k4 q% Z5 C+ S. ^/ c
UINT nMsg = ::RegisterWindowMessage( _T("WM_HTML_GETOBJECT") );
" C' i8 m" C3 i% e3 ?8 R1 w LRESULT lRes;
: l/ r/ {/ n3 R) l0 F1 n% T ::SendMessageTimeout( hWndChild, nMsg, 0L, 0L, SMTO_ABORTIFHUNG, 1000, (DWORD*) &lRes );
) q; K3 p* E7 d; S( E5 I
& [3 l4 V: C* ]1 B1 C CComPtr < IHTMLDocument2 > spDoc;
3 ~" q( z2 p0 A- \6 f HRESULT hr = ::ObjectFromLresult ( lRes, IID_IHTMLDocument2, 0 , (LPVOID *) &spDoc );
& M" S; H' z c if ( FAILED ( hr ) ) return;
$ ]" ~6 {+ ~/ z" K
* B V. H8 a% b' I# p6 G8 a // 程序运行到此,已经找到了 IHTMLDocument2 的接口指针2 _9 O; |$ P; U
} |
|