|
根据IE浏览器的运行方式,有多种不同的方式可以获取文档指针。
7 e% x. }) N9 `1 w, j! L4 b; j8 ?
0 y3 I7 r/ X3 P5 h3 ~ <1> 如果你在程序中使用MFC的 CHtmlView 视来浏览网页。9 b0 W* F1 ?3 e2 S1 p2 l
取得文档的方法最简单,调用 CHtmlView::GetHtmlDocument() 函数。
3 A U' l- X3 k2 J5 K/ u7 j0 \ <2> 如果你的程序中使用了“Web 浏览器” 的ActiveX 控件。
8 w& _" [# S" ?- [3 N$ M 取得文档的方法也比较简单,调用 CWebBrowser2::GetDocument() 函数。0 U0 Q+ j8 I3 {/ F- |5 [) _* Y
<3> 如果你的程序是用 ATL 写的 ActiveX 控件。
+ S) a1 C; T" K" O3 @9 b( E# m 那么需要调用 IOleClientSite::GetContainer 得到 IOleContainer 接口,然后就可以通过 QueryInterface() 查询得到 IHTMLDocument2 的接口。主要代码如下: ; ^( `# |" ]8 u
8 ^5 U; i2 f- GCComPtr < IOleContainer > spContainer;
6 N! a2 h5 R( {, e/ D. A5 _+ F: am_spClientSite->GetContainer( &spContainer );
+ t* c( Q1 E+ A iCComQIPtr < IHTMLDocument2 > spDoc = spContainer;6 I5 C: ?! [. n9 n8 A# l8 g2 ~3 L
if ( spDoc )
+ L+ H8 R/ H0 A- g+ T1 ~1 c{
: v1 I, A* s* Q8 F X // 已经得到了 IHTMLDocument2 的接口指针
& C1 Z n* N: s' s! R}# p/ L# }! t& }; T
5 S: J' ~+ S( B
<4> 如果你的程序是用 MFC 写的 ActiveX 控件。, D7 t* H4 _8 E) q
那么需要调用 COleControl::GetClientSite() 得到 IOleContainer 接口,然后的操作和<3>是一致的了。
3 m; A5 Y" x& V' a3 j3 }$ t <5> IE 浏览器作为独立的进程正在运行。8 t3 e5 w7 V% D# C5 t6 F
每个运行的浏览器(IE 和 资源浏览器)都会在 ShellWindows 中进行登记,因此我们要通过 IShellWindows 取得实例(示例程序中使用的就是这个方法)。主要代码如下:6 G& D3 J" ^$ v" ~& |5 s9 C
# g/ D3 g9 {1 }" V3 J#include < atlbase.h >- y1 A# X/ f; f* _
#include < mshtml.h >& }# \9 F/ B; [3 z
3 t8 ]. d( `& O; y) |
void FindFromShell()
: w$ S4 A) k* a" t$ A) Y. O{
; l3 l/ {) c+ |9 a( s A CComPtr< IShellWindows > spShellWin;
$ {% ?3 F, O8 g, m HRESULT hr = spShellWin.CoCreateInstance( CLSID_ShellWindows );3 W. g3 t% ~ w# h' g- I7 Z. O
if ( FAILED( hr ) ) return;* S1 t; t9 G" K# K6 n: p5 t8 E8 m5 w* Z
% [# d" _( m0 V' G l4 a long nCount=0;
0 l( l6 }! a, J; C0 O' d, C spShellWin->get_Count(&nCount); // 取得浏览器实例个数" S: `1 Z" B8 b$ {! K$ i
- X, }/ P3 \- H2 s
for(long i=0; i<nCount; i++)# q6 _" x1 w! e3 f, l+ o! f
{1 Z, ]( h0 z' J' ^
CComPtr< IDispatch > spDisp;
7 G; h) z8 Y$ q2 C4 S; t7 _2 j hr=spShellWin->Item(CComVariant( i ), &spDisp );
5 N6 O% Y5 {7 ]& {3 ^9 T if ( FAILED( hr ) ) continue;3 R1 C: m. I0 b3 R% @2 z
! {* H' o8 @+ U/ u CComQIPtr< IWebBrowser2 > spBrowser = spDisp;. P3 q6 x. t7 A6 _ S, Y
if ( !spBrowser ) continue;
3 _6 F! o! r8 M8 z S" w$ [2 e. B7 p
spDisp.Release();5 Q, b1 R7 j8 h8 k& g9 r$ ^& }
hr = spBrowser->get_Document( &spDisp );
' u7 ^0 T: _8 O w3 q0 z& n if ( FAILED ( hr ) ) continue;0 I2 ^9 x/ U4 J! x; N! P: D
- o/ ^3 i- p9 T$ R" ` CComQIPtr< IHTMLDocument2 > spDoc = spDisp;
' o, u1 Q d3 D' T3 X0 O- A if ( !spDoc ) continue;" W9 R7 A; A4 S8 y$ C+ h1 d2 `* g2 \
* }, }2 Z& e1 j$ `5 v
// 程序运行到此,已经找到了 IHTMLDocument2 的接口指针
8 f) u+ {* ^0 c4 C; ?. g }
) \1 S/ J1 U. ~, P5 p}
y, b5 k+ [6 d5 d
+ M' x! }( U2 P& U& J4 u( d <6> IE 浏览器控件被一个进程包装在一个子窗口中。那么你首先要得到那个进程的顶层窗口句柄(使用 FindWindow() 函数,或其它任何可行的方法),然后枚举所有子窗口,通过判断窗口类名是否是“Internet Explorer_Server”,从而得到浏览器的窗口句柄,再向窗口发消息取得文档的接口指针。主要代码如下:
2 C# U6 w. E% ?/ h; {7 `9 L: Q4 `7 w2 Y9 c8 H$ k/ U! J' |; p
: P" k% o, X) y" k" f' Q. `#include < atlbase.h >2 y2 y7 K) H. |& r
#include < mshtml.h >
& c" B6 Q1 F9 d#include < oleacc.h >
1 ?, \5 I4 Q/ V#pragma comment ( lib, "oleacc" )5 @8 b% T; x$ m5 n- {
1 m* j5 k! e( f% H f+ d( gBOOL CALLBACK EnumChildProc(HWND hwnd,LPARAM lParam)+ C3 @0 \+ @8 y+ l5 N v {! ?) }
{# F3 U/ C: d, C
TCHAR szClassName[100];
2 L' Q2 T8 h2 {, Y& _8 ?) W! x% r
::GetClassName( hwnd, &szClassName, sizeof(szClassName) );
3 ~/ E' q% H& d- f F if ( _tcscmp( szClassName, _T("Internet Explorer_Server") ) == 0 )& u; }3 z) G. t3 Q
{
$ x% d S8 o: @" } *(HWND*)lParam = hwnd;
; W: V9 g) h7 A* [' C return FALSE; // 找到第一个 IE 控件的子窗口就停止3 k' r: [* Q7 o4 ?& e
}7 v, N# q' T! V+ ` |+ w
else return TRUE; // 继续枚举子窗口
8 u$ A) @6 ^$ z9 b};
0 G( q% n5 B# Q2 [ C
; h9 g a0 e! _, Jvoid FindFromHwnd(HWND hWnd)
) |/ t' Z% H$ `4 q{$ h: ?; a3 G6 g- f' A' I: o) b* d
HWND hWndChild=NULL;
7 O2 }+ @% @# n6 d7 d" v2 T* C ::EnumChildWindows( hWnd, EnumChildProc, (LPARAM)&hWndChild );' }' o4 }5 K- l; \; f2 v* Z! J
if(NULL == hWndChild) return;+ p0 e" z; z% m4 {, R
3 V- J# U* Y" n0 W( l
UINT nMsg = ::RegisterWindowMessage( _T("WM_HTML_GETOBJECT") ); U X; A3 D$ t3 e- F/ N
LRESULT lRes;
i$ n8 y) a) z' B( ^: L ::SendMessageTimeout( hWndChild, nMsg, 0L, 0L, SMTO_ABORTIFHUNG, 1000, (DWORD*) &lRes );8 Z4 P( q q7 k1 R! u5 f% g3 ^5 _, X
. i' q( i2 O# X* U* |) Z# p6 M
CComPtr < IHTMLDocument2 > spDoc;
}; {- z7 ?% s' T( g) E. a- A HRESULT hr = ::ObjectFromLresult ( lRes, IID_IHTMLDocument2, 0 , (LPVOID *) &spDoc );5 d, k- l! `# c6 ?5 k& \! g5 b
if ( FAILED ( hr ) ) return;" g0 f; y/ c2 x' [' ? T
S) m! }9 ^/ ~. ]1 m
// 程序运行到此,已经找到了 IHTMLDocument2 的接口指针
i7 Y4 k5 q+ a& M3 e) `} |
|