|
|
根据IE浏览器的运行方式,有多种不同的方式可以获取文档指针。
; ^+ Z4 Y% B# V; S1 J8 r( q: r. ~7 G0 n
<1> 如果你在程序中使用MFC的 CHtmlView 视来浏览网页。
w! k! e& J( R- {6 {; t 取得文档的方法最简单,调用 CHtmlView::GetHtmlDocument() 函数。; B0 _6 W6 [" t: x- f- Z
<2> 如果你的程序中使用了“Web 浏览器” 的ActiveX 控件。$ c4 Y) p2 X o! E
取得文档的方法也比较简单,调用 CWebBrowser2::GetDocument() 函数。
, V7 l$ o6 l0 i0 F1 x q <3> 如果你的程序是用 ATL 写的 ActiveX 控件。
" y/ l1 b0 ^: [: q7 t2 { 那么需要调用 IOleClientSite::GetContainer 得到 IOleContainer 接口,然后就可以通过 QueryInterface() 查询得到 IHTMLDocument2 的接口。主要代码如下: / B' S; v) ^; K* W4 F+ R
8 t n) W& D/ z- FCComPtr < IOleContainer > spContainer;) y3 X4 P8 A9 f* y6 F6 L- `
m_spClientSite->GetContainer( &spContainer );
6 g% ]0 _( L8 PCComQIPtr < IHTMLDocument2 > spDoc = spContainer;% M+ X' ^ N: ~ h
if ( spDoc )# y j5 a2 h5 C4 S0 X
{
4 [2 U' g& n v9 f7 m- M" i2 w // 已经得到了 IHTMLDocument2 的接口指针
& Q9 V+ l3 k5 k9 D( U}3 X. n3 [8 M0 X
/ Y2 k4 Z/ D& @. M <4> 如果你的程序是用 MFC 写的 ActiveX 控件。0 }3 [* }% w* ^$ N' J8 s( J
那么需要调用 COleControl::GetClientSite() 得到 IOleContainer 接口,然后的操作和<3>是一致的了。3 u; Y7 W! K0 v. V0 N( b
<5> IE 浏览器作为独立的进程正在运行。
* B6 [, p8 y6 L) O 每个运行的浏览器(IE 和 资源浏览器)都会在 ShellWindows 中进行登记,因此我们要通过 IShellWindows 取得实例(示例程序中使用的就是这个方法)。主要代码如下:
' }* a! O T1 g: R( }+ V& |& K2 E4 [# P0 P
#include < atlbase.h >
; g5 k3 K1 ~/ X1 M) Z! Z$ U#include < mshtml.h >2 O( ~5 ^, U ?1 [3 c7 _+ H8 ^# B
- r# Z" X; }! T, S+ t1 m! F0 I
void FindFromShell()
& e* P5 P; J* f7 I( Q{7 o. c; H- _! L9 g& z
CComPtr< IShellWindows > spShellWin;7 O- Y. c9 p0 Y/ |. F
HRESULT hr = spShellWin.CoCreateInstance( CLSID_ShellWindows );# E, s& }- q+ V# ]
if ( FAILED( hr ) ) return;
& B9 h# {9 V u8 D% o3 n& j* U. d" A: d* G8 q! W. Y
long nCount=0;
. z" ^. y6 u# w3 _$ f) H spShellWin->get_Count(&nCount); // 取得浏览器实例个数: a4 m' M0 v @" k$ T9 B
% J; x3 `% i# g for(long i=0; i<nCount; i++)+ H+ x* o! z. I$ L/ S! y
{
9 [, N' l9 v# [ CComPtr< IDispatch > spDisp;
' B3 R: s: U3 M) h- ~$ |+ l hr=spShellWin->Item(CComVariant( i ), &spDisp );
: q& n5 V8 p; ] if ( FAILED( hr ) ) continue;( f9 N+ J! {- R/ Y9 J. t
- q5 E9 z! g2 e9 F) w; E4 Y. [2 e6 C CComQIPtr< IWebBrowser2 > spBrowser = spDisp;
. F; I) m6 T; ~8 I if ( !spBrowser ) continue;: }& f, T& b) L( a* v' h! e$ m
% c8 ~0 r( Z1 E: A6 E$ j. U' Q
spDisp.Release();
6 i- K2 @4 r% ]4 v2 J hr = spBrowser->get_Document( &spDisp );
# |" \# b+ m n: g2 z' D* C if ( FAILED ( hr ) ) continue;# F) u+ U8 T! G2 N
) ] d8 `, k, z; y. { CComQIPtr< IHTMLDocument2 > spDoc = spDisp;
9 M A' g1 u) O+ ^" J9 s" E if ( !spDoc ) continue; P% e! Y6 N* E! G
0 k/ x1 {3 R O: j, M
// 程序运行到此,已经找到了 IHTMLDocument2 的接口指针
# M2 C: y8 l7 k3 G& ?) w) u. s }
' | Y7 y, [, Q}
9 A0 B: p5 L7 J3 Y, _5 E1 q- ^
* K1 C3 \8 l7 g: Q$ m <6> IE 浏览器控件被一个进程包装在一个子窗口中。那么你首先要得到那个进程的顶层窗口句柄(使用 FindWindow() 函数,或其它任何可行的方法),然后枚举所有子窗口,通过判断窗口类名是否是“Internet Explorer_Server”,从而得到浏览器的窗口句柄,再向窗口发消息取得文档的接口指针。主要代码如下: : R5 P1 ^: T# g. i7 n$ |- k
% s# w O6 h! N" t
4 \$ ^4 w4 Y& ?1 w/ I#include < atlbase.h >$ h: e- B: N' B# R1 r
#include < mshtml.h >8 r7 v9 x2 l/ b1 U
#include < oleacc.h >1 E3 `1 {6 D& P c
#pragma comment ( lib, "oleacc" )- v$ V! r! T8 F' b; P
' `+ n% A Y. X2 iBOOL CALLBACK EnumChildProc(HWND hwnd,LPARAM lParam)
0 i+ Z+ {' Z0 _+ I5 I: w" w{& b' B7 r8 H6 `) ^+ N: F6 y/ s& G' z& m6 s( h
TCHAR szClassName[100];1 p8 ^* S/ ]8 Z; K
) s9 n% E: h! H9 i5 V ::GetClassName( hwnd, &szClassName, sizeof(szClassName) );, f" J5 ~ N9 d6 w* I
if ( _tcscmp( szClassName, _T("Internet Explorer_Server") ) == 0 )
$ E7 F+ g1 F3 P+ c, G* } {+ d6 q" Z. x, Q; q" R7 l/ E G, f. V
*(HWND*)lParam = hwnd;# O7 ?3 w5 B) F9 O6 j
return FALSE; // 找到第一个 IE 控件的子窗口就停止6 ^% k% w) z# Q+ j* t2 W3 m
}
- R. c7 }+ {2 m. @! W! }) ` else return TRUE; // 继续枚举子窗口! x; _) I- v& u, _0 T0 D3 M
}; N8 a! x- h; Z1 U2 r, @8 }
7 n: i, p; [* I. F: x
void FindFromHwnd(HWND hWnd) ( o' t3 n" d- O
{
/ s4 i0 g: B- \- M( D HWND hWndChild=NULL;% K# P9 s$ B9 r7 n6 i: k
::EnumChildWindows( hWnd, EnumChildProc, (LPARAM)&hWndChild );
; m4 Y/ S8 Z9 z7 E a1 k. ~0 Z) @ if(NULL == hWndChild) return;
6 B# I7 t( I G$ H" z3 F: i1 Z, |9 q* S( n3 f
UINT nMsg = ::RegisterWindowMessage( _T("WM_HTML_GETOBJECT") );
; E7 y- ?& M; X& ] LRESULT lRes;0 w) v' b9 [) N K* G
::SendMessageTimeout( hWndChild, nMsg, 0L, 0L, SMTO_ABORTIFHUNG, 1000, (DWORD*) &lRes );
; K7 X! O' a* }6 \. e( j4 [7 l. ^' H3 |8 t/ K* T
CComPtr < IHTMLDocument2 > spDoc;, a! w* ?. {: ]8 l4 h% E
HRESULT hr = ::ObjectFromLresult ( lRes, IID_IHTMLDocument2, 0 , (LPVOID *) &spDoc );
# \6 o6 J2 n- B9 I: Y if ( FAILED ( hr ) ) return;
1 u9 m' T9 O8 j0 ^% H0 R
- W( d2 _; T# X# ~: }( E2 B y0 N // 程序运行到此,已经找到了 IHTMLDocument2 的接口指针
8 v6 _8 N1 ]; @ i; Z" h+ e} |
|