|
|
根据IE浏览器的运行方式,有多种不同的方式可以获取文档指针。
4 M: V" x s2 {) E7 K% W U* N
2 y$ b, Y0 G- \* I, Y) ]! m8 N <1> 如果你在程序中使用MFC的 CHtmlView 视来浏览网页。" K8 W. o( Z5 i3 n& Y- n
取得文档的方法最简单,调用 CHtmlView::GetHtmlDocument() 函数。& L, l* r$ F) r6 p# i6 f: I/ M
<2> 如果你的程序中使用了“Web 浏览器” 的ActiveX 控件。
& ?) }8 K# W# \6 B( j 取得文档的方法也比较简单,调用 CWebBrowser2::GetDocument() 函数。
5 G, V# y' q, \5 ^ <3> 如果你的程序是用 ATL 写的 ActiveX 控件。
6 E8 V m. H- G1 k+ R1 G 那么需要调用 IOleClientSite::GetContainer 得到 IOleContainer 接口,然后就可以通过 QueryInterface() 查询得到 IHTMLDocument2 的接口。主要代码如下:
; _9 N8 T& I* b# P9 D6 c4 O- I) y1 O3 U( s( R/ K
CComPtr < IOleContainer > spContainer;0 z; ^) n }4 J" S% [
m_spClientSite->GetContainer( &spContainer );
6 `, s. n* y. H) Y' I6 GCComQIPtr < IHTMLDocument2 > spDoc = spContainer;" T$ D" N6 d" u: U0 O5 s5 m$ W
if ( spDoc )9 W0 X- {8 ]+ G0 }" w" ^! @
{6 K7 p5 u+ F; a' F! H0 c3 _" D
// 已经得到了 IHTMLDocument2 的接口指针" m. D/ h4 V. _6 {
}6 z- H$ O/ w0 }
+ X$ p0 e, P0 {7 Y$ `* E <4> 如果你的程序是用 MFC 写的 ActiveX 控件。
* L5 \3 V D+ \: ^ 那么需要调用 COleControl::GetClientSite() 得到 IOleContainer 接口,然后的操作和<3>是一致的了。# S4 f6 e! p' [$ c- p6 Y
<5> IE 浏览器作为独立的进程正在运行。
2 Q' F- D7 E# x. M 每个运行的浏览器(IE 和 资源浏览器)都会在 ShellWindows 中进行登记,因此我们要通过 IShellWindows 取得实例(示例程序中使用的就是这个方法)。主要代码如下:9 S* i |( F8 `
) }/ D5 }" \' s5 | _2 N
#include < atlbase.h >$ d4 a) ~9 x$ F* [
#include < mshtml.h >9 P* Z% S9 ^1 V) J) U5 ]
. G" @8 |$ t' k; @+ E9 X3 ovoid FindFromShell() ( n5 a8 V, T" p# Q5 O Q
{
- z1 U, F7 ^- [6 z# C# |+ \ CComPtr< IShellWindows > spShellWin;
/ W1 c! r |' [+ { HRESULT hr = spShellWin.CoCreateInstance( CLSID_ShellWindows );1 {2 I" Q% {. p \1 T, z
if ( FAILED( hr ) ) return;
5 E( H- P, `! k, F
3 ?# q7 ~- ]6 ]; o+ s& D7 l long nCount=0;; F, v. G6 J. v4 q4 L
spShellWin->get_Count(&nCount); // 取得浏览器实例个数9 @/ q# n3 ~9 z2 t$ L5 [
2 E) S8 R7 W: ~4 ~ for(long i=0; i<nCount; i++)
6 j% ]+ E7 l2 N6 N! T {
9 ~) i0 U+ E9 Q CComPtr< IDispatch > spDisp;
U9 D' J5 R2 a0 ^5 K1 U/ j" h7 F hr=spShellWin->Item(CComVariant( i ), &spDisp );
" I# \! l% j* _9 k* S6 q+ b if ( FAILED( hr ) ) continue;9 s" H4 ?4 `, E
+ q3 W# _( h8 S# }) i( ~2 c' U CComQIPtr< IWebBrowser2 > spBrowser = spDisp;
9 y0 n0 k" b( n$ J" w if ( !spBrowser ) continue;/ X8 {0 `/ z$ a- u. _
7 W, x: h2 d, N2 G* Y spDisp.Release();
5 ?) X: D" j6 r* e1 R hr = spBrowser->get_Document( &spDisp );
% m, R; Z, X5 m6 g! y9 i if ( FAILED ( hr ) ) continue;. n9 X2 `8 }/ A7 ?
/ f0 G ~# [/ Z0 x# P
CComQIPtr< IHTMLDocument2 > spDoc = spDisp;! P5 z, t0 X9 p- j. W1 ?
if ( !spDoc ) continue;" O0 I" S; o, f" e' U; p
) w% f6 _( G% N+ C) x+ J
// 程序运行到此,已经找到了 IHTMLDocument2 的接口指针% B# @/ A F2 k+ n8 m' `
}
: j+ x4 V1 Q5 C w} T1 z3 m3 ^! \6 V* D% b& o( p
. @: e9 v& N8 A. i$ m <6> IE 浏览器控件被一个进程包装在一个子窗口中。那么你首先要得到那个进程的顶层窗口句柄(使用 FindWindow() 函数,或其它任何可行的方法),然后枚举所有子窗口,通过判断窗口类名是否是“Internet Explorer_Server”,从而得到浏览器的窗口句柄,再向窗口发消息取得文档的接口指针。主要代码如下:
( {& }2 Z) f" w; {( \
# |2 g- H. g8 S
% D1 ~5 A, Y; e2 [% y, Q#include < atlbase.h >$ n4 p! _% x+ V; C
#include < mshtml.h >+ Q' q( t9 c/ Z/ T1 F# _$ s1 A B
#include < oleacc.h >
6 `% u- P( F' I#pragma comment ( lib, "oleacc" )
' p. j- `5 G) R* r3 b; }( b" R# j3 v6 z) P C6 y6 Q4 V/ N
BOOL CALLBACK EnumChildProc(HWND hwnd,LPARAM lParam)
4 o7 c; L$ c* o, w+ X3 d{
[- K: H5 d+ A# M TCHAR szClassName[100];" y+ n7 r/ ~* k2 z
6 v1 m) O/ z! ?, ? ::GetClassName( hwnd, &szClassName, sizeof(szClassName) );! ?, e7 `- z4 |* T) b# W; h
if ( _tcscmp( szClassName, _T("Internet Explorer_Server") ) == 0 )
3 ]# G, x, |) e/ F5 d- V* a5 I' { {
+ H: D/ g4 G/ G9 v7 a' G *(HWND*)lParam = hwnd;
o6 t6 M- t7 I" B3 A return FALSE; // 找到第一个 IE 控件的子窗口就停止
+ G/ M& `* _5 d- F5 U" ?. I }$ P; V2 b. E1 \% W
else return TRUE; // 继续枚举子窗口
. k4 P2 M2 M% I9 b};# k8 J$ E* w- g8 ^9 m
8 D$ D. {5 M, o' q
void FindFromHwnd(HWND hWnd) & b3 E6 h, k4 X K# Q2 P
{
( `5 U- Q) K u6 i2 Y" P HWND hWndChild=NULL;
R6 ~; e7 P6 o3 [# c. }6 W ::EnumChildWindows( hWnd, EnumChildProc, (LPARAM)&hWndChild );
+ V2 W$ g0 x- i9 |; N0 n if(NULL == hWndChild) return;1 R4 Y$ f& G6 `$ V ]2 E. i- U
1 u* s$ F) p: u9 Z( p UINT nMsg = ::RegisterWindowMessage( _T("WM_HTML_GETOBJECT") );5 f: s( L% ]: k' T/ r0 [
LRESULT lRes;
9 q* Q9 ]( m. ^/ K$ \, p8 q i1 X5 j ::SendMessageTimeout( hWndChild, nMsg, 0L, 0L, SMTO_ABORTIFHUNG, 1000, (DWORD*) &lRes );
! v" N a$ z! t @4 g
9 j8 ^4 C0 H& D2 x+ w6 h! p CComPtr < IHTMLDocument2 > spDoc;
, T; c, ^: k ^6 Y0 ?- N# ^ E9 C0 I8 ` HRESULT hr = ::ObjectFromLresult ( lRes, IID_IHTMLDocument2, 0 , (LPVOID *) &spDoc );
& d* q! i- I. @% [0 h if ( FAILED ( hr ) ) return;
3 w; M( R' p5 e; n y K+ I- f5 p5 r, S/ ~2 C( K$ K1 J. c
// 程序运行到此,已经找到了 IHTMLDocument2 的接口指针1 m: I$ X8 G8 P. d, @
} |
|