|
根据IE浏览器的运行方式,有多种不同的方式可以获取文档指针。
, R3 C) z5 m& p+ f0 Q9 K, U% ]- L. i3 ` W9 V) R7 |( o
<1> 如果你在程序中使用MFC的 CHtmlView 视来浏览网页。- I, p1 U" Q6 E: `7 @& h) ~
取得文档的方法最简单,调用 CHtmlView::GetHtmlDocument() 函数。
5 q4 h! K- L9 n3 E <2> 如果你的程序中使用了“Web 浏览器” 的ActiveX 控件。+ E! o X7 k7 E/ t+ A* a
取得文档的方法也比较简单,调用 CWebBrowser2::GetDocument() 函数。
# t) U/ w5 l% l! A <3> 如果你的程序是用 ATL 写的 ActiveX 控件。& F6 K+ _& o7 q+ e% T5 `' B: R& M2 H
那么需要调用 IOleClientSite::GetContainer 得到 IOleContainer 接口,然后就可以通过 QueryInterface() 查询得到 IHTMLDocument2 的接口。主要代码如下:
, x6 @$ t- D/ U* L0 V* a! C0 s
0 u& [5 q8 R. p! M: J( J0 s& ^3 LCComPtr < IOleContainer > spContainer; a' T0 e, W# t" J
m_spClientSite->GetContainer( &spContainer );) a B& Q' Y$ ?8 A: y% A
CComQIPtr < IHTMLDocument2 > spDoc = spContainer;
; M2 B# j- P; p& I2 p' ^/ r; fif ( spDoc )9 _" Y+ y0 P5 ?% R/ t" @$ i
{
$ b% q7 J9 i- m( @4 j# c& g q // 已经得到了 IHTMLDocument2 的接口指针0 z; n$ n2 J& E+ @
}+ {; c# o$ N- {; ?2 b. N
) ~5 Y K0 n; _! N9 W
<4> 如果你的程序是用 MFC 写的 ActiveX 控件。
# a( {. ~) M6 V. J; Q1 k$ d! U: R 那么需要调用 COleControl::GetClientSite() 得到 IOleContainer 接口,然后的操作和<3>是一致的了。& ~9 U9 |. Y4 v u# \0 N# N
<5> IE 浏览器作为独立的进程正在运行。
# ^! `( C$ X |5 Y3 S7 f 每个运行的浏览器(IE 和 资源浏览器)都会在 ShellWindows 中进行登记,因此我们要通过 IShellWindows 取得实例(示例程序中使用的就是这个方法)。主要代码如下:% A1 ?$ w9 h- E# ~
% J1 y6 c- L L3 `+ F#include < atlbase.h >
~6 i! t( n6 `# r0 ?#include < mshtml.h >
7 | i2 T" o) S/ U1 C- _. z) h; P% }5 p" m/ c6 _- H
void FindFromShell()
) A- r. X1 b5 R: ~9 |{; {+ C0 L6 R4 T# J0 A& _5 M
CComPtr< IShellWindows > spShellWin;* I+ B1 W7 c& Q; d) c- e* i2 f
HRESULT hr = spShellWin.CoCreateInstance( CLSID_ShellWindows );2 {& I5 e( f' i H$ m
if ( FAILED( hr ) ) return;
2 b: U6 }5 D' a0 J& b& T9 r0 S, `6 T9 C4 ~# y
long nCount=0;
5 p N' }2 ~- m4 }8 d. s0 [( A( {, ~ spShellWin->get_Count(&nCount); // 取得浏览器实例个数; j" m4 K0 ~6 r2 ~
" N$ S8 x+ m# f' p" q+ u for(long i=0; i<nCount; i++)0 K0 A: d4 h0 f& y5 S, V" [
{
! J3 o ]2 q- t: T% ?3 K E3 ~3 L CComPtr< IDispatch > spDisp;( E# F- ?8 Q) L! Z' E
hr=spShellWin->Item(CComVariant( i ), &spDisp );+ S. C8 r# ?- w4 S- d1 ^
if ( FAILED( hr ) ) continue;
, S2 e- w2 K+ \* u" v
; O' v' Q. W- p) I CComQIPtr< IWebBrowser2 > spBrowser = spDisp;
3 D7 h# k$ E5 M. {6 [$ B, Y" L% t if ( !spBrowser ) continue;
, Z6 Y, E9 K& k; d5 Z
: e9 r9 S$ ^/ d5 G- i spDisp.Release();9 F! ~* v6 a" Z+ e& Y
hr = spBrowser->get_Document( &spDisp );+ m H" U6 T. N9 f N4 h# Y- e! D
if ( FAILED ( hr ) ) continue;9 k5 n4 I% [: [8 E
! V& `0 k8 X' H' ]- P7 n* h CComQIPtr< IHTMLDocument2 > spDoc = spDisp;0 i1 g3 d/ s. J7 U: c! S
if ( !spDoc ) continue;
: F a+ U! ]+ ? e4 f2 |
9 g. w! Y% d5 T: c // 程序运行到此,已经找到了 IHTMLDocument2 的接口指针) T4 E* W3 h7 e6 X) ~9 |
}. Z9 `/ Q: W; N. v, x, `
}
! g- S( j1 j; {. m/ W. O# v' k- H1 z
<6> IE 浏览器控件被一个进程包装在一个子窗口中。那么你首先要得到那个进程的顶层窗口句柄(使用 FindWindow() 函数,或其它任何可行的方法),然后枚举所有子窗口,通过判断窗口类名是否是“Internet Explorer_Server”,从而得到浏览器的窗口句柄,再向窗口发消息取得文档的接口指针。主要代码如下: * b* h# E: H O! ?
' E4 b& z2 R1 ^- s
6 `" E& v4 b, D0 v#include < atlbase.h >4 L) j3 ]- p: n- d' x" z
#include < mshtml.h >% q* \/ g' {. q; W
#include < oleacc.h >
* {5 r2 G5 C# p) D) @#pragma comment ( lib, "oleacc" )
- }* l" R6 u' n8 _- k% e3 \
* L8 k% }$ m* F# ?BOOL CALLBACK EnumChildProc(HWND hwnd,LPARAM lParam)
. K; a& a) {/ Y$ g{' e1 X! k# A5 y+ \: N. m: t) d/ m
TCHAR szClassName[100];
5 z+ I2 t) }6 N# a; o
+ T4 ^& n* P: [8 ~ a- f% G3 n0 X ::GetClassName( hwnd, &szClassName, sizeof(szClassName) );6 B7 [; X1 ~1 }+ c J) o4 X) l8 z: f5 G
if ( _tcscmp( szClassName, _T("Internet Explorer_Server") ) == 0 )1 H9 m! B% K8 b% B2 _
{( v# x V- c$ U( |' Y' L% b& ]
*(HWND*)lParam = hwnd;
3 _) l, ^8 ~4 w7 s3 E: E return FALSE; // 找到第一个 IE 控件的子窗口就停止
7 o; [8 I2 e }3 T8 l1 u }
) b7 F. G7 k/ k5 z- u+ ~ else return TRUE; // 继续枚举子窗口
\: f3 ?" @+ v$ P, I# |};
0 T: I4 e7 P8 l" T! _( ? Z; k( F3 w6 c7 Z
void FindFromHwnd(HWND hWnd) : C/ _3 n3 Y/ L3 Q
{6 C$ R/ z- }" i6 {* U9 d9 Y8 y7 E
HWND hWndChild=NULL;! R) l1 I. {/ ]7 G$ E' r
::EnumChildWindows( hWnd, EnumChildProc, (LPARAM)&hWndChild );3 p! B/ |$ B% t) a* w- e* q2 u
if(NULL == hWndChild) return;" A" E4 G) U% j& B$ m# S5 ~
% z* D6 ?" {6 Y
UINT nMsg = ::RegisterWindowMessage( _T("WM_HTML_GETOBJECT") );0 Q3 ?, r5 X: R! I
LRESULT lRes;0 ?2 C+ I) p/ n7 {8 a. T+ r
::SendMessageTimeout( hWndChild, nMsg, 0L, 0L, SMTO_ABORTIFHUNG, 1000, (DWORD*) &lRes );
3 {( u4 w& g" O/ Z: I9 v k2 m) ^6 V# r) |
CComPtr < IHTMLDocument2 > spDoc;
% v. A" E+ y- c# R) B' K3 c( V1 P HRESULT hr = ::ObjectFromLresult ( lRes, IID_IHTMLDocument2, 0 , (LPVOID *) &spDoc );
1 q6 \8 ~6 l% x/ S/ i' [# u' U if ( FAILED ( hr ) ) return;: X0 k8 r( }5 X+ X( W. P: S. K. H
) \4 i/ F3 H; w2 I // 程序运行到此,已经找到了 IHTMLDocument2 的接口指针+ z- D0 [ L% @
} |
|