|
|
根据IE浏览器的运行方式,有多种不同的方式可以获取文档指针。* `* |' I( ]: f! o" l
9 h! g( e8 \+ k- p$ h8 @$ x' X <1> 如果你在程序中使用MFC的 CHtmlView 视来浏览网页。
! K* d3 B, K3 }0 Z6 A& q: n5 z 取得文档的方法最简单,调用 CHtmlView::GetHtmlDocument() 函数。
: ?9 W6 r5 d' {: U5 k* c <2> 如果你的程序中使用了“Web 浏览器” 的ActiveX 控件。" u( Q) u: F# D( R9 T
取得文档的方法也比较简单,调用 CWebBrowser2::GetDocument() 函数。9 Y f- F: P/ n0 c# L
<3> 如果你的程序是用 ATL 写的 ActiveX 控件。
3 E3 B/ e6 S/ o# v- A& u 那么需要调用 IOleClientSite::GetContainer 得到 IOleContainer 接口,然后就可以通过 QueryInterface() 查询得到 IHTMLDocument2 的接口。主要代码如下: ( ~+ w* x* I3 L$ ~; N7 N: I R
" s& J; I. e9 W
CComPtr < IOleContainer > spContainer;
% H Z8 K7 A5 X5 @m_spClientSite->GetContainer( &spContainer );/ C- X" w8 z! W# V. k
CComQIPtr < IHTMLDocument2 > spDoc = spContainer;, I* t1 O9 q# h b, _; o! J
if ( spDoc )2 J2 k4 H4 f4 }
{
- s% [1 ]+ R. b- P6 D1 } // 已经得到了 IHTMLDocument2 的接口指针
; h. R: D, q+ `}. _) X a" o# n; |
( f6 A' Q2 O. ?1 ~7 H
<4> 如果你的程序是用 MFC 写的 ActiveX 控件。! u. x; ` X( P
那么需要调用 COleControl::GetClientSite() 得到 IOleContainer 接口,然后的操作和<3>是一致的了。 l9 t1 o2 W5 x3 h
<5> IE 浏览器作为独立的进程正在运行。
0 z" M- g* ?" _* f6 P 每个运行的浏览器(IE 和 资源浏览器)都会在 ShellWindows 中进行登记,因此我们要通过 IShellWindows 取得实例(示例程序中使用的就是这个方法)。主要代码如下:. W: X! S/ R1 y' v
) x1 c' g. t) x8 i4 ]' O#include < atlbase.h >
' w r. t1 V- |+ K#include < mshtml.h >
' }+ \% U e: e1 L$ v/ \
! W7 n+ B6 o* z0 o$ P5 z/ {8 `void FindFromShell()
4 q. ~. s6 Y5 ]2 l7 p5 L{
9 {# H' m4 i4 A: F. t l CComPtr< IShellWindows > spShellWin;
! |5 b* R0 w. L HRESULT hr = spShellWin.CoCreateInstance( CLSID_ShellWindows );) i+ r+ r( G) J
if ( FAILED( hr ) ) return;
' e+ ?+ N( \/ R1 g7 N0 P1 `
$ b( E+ n: f: F' W8 u long nCount=0;4 u3 J* M" U) c+ F4 r( f2 D& P9 d
spShellWin->get_Count(&nCount); // 取得浏览器实例个数7 I& N* c/ @: f
~8 g d1 ?4 }1 T% Y for(long i=0; i<nCount; i++)
, w9 W1 B* A+ U8 X4 k2 ^ {
) M6 p' h2 i9 x# k" S CComPtr< IDispatch > spDisp;. `; q& D9 d3 {" L5 C' ~+ u
hr=spShellWin->Item(CComVariant( i ), &spDisp );" r7 f! |/ W! |, T' R
if ( FAILED( hr ) ) continue;3 L. W) i! y9 E) X7 R, ~# F j
( e$ |3 z$ U" A1 Z7 W
CComQIPtr< IWebBrowser2 > spBrowser = spDisp;
7 ?# Z/ u$ A5 R- P8 b if ( !spBrowser ) continue;, F4 J0 e3 F! E4 {1 W5 r( A
' {8 T9 S1 I" p" X
spDisp.Release();
% C# }* K$ ~3 w* p: E hr = spBrowser->get_Document( &spDisp );* i! K( A# B, w! c3 n
if ( FAILED ( hr ) ) continue;
& {, b1 ?1 T( M' f6 c2 S' n/ z" n3 j
CComQIPtr< IHTMLDocument2 > spDoc = spDisp;
* \: e+ v8 \3 y% f/ q1 J if ( !spDoc ) continue;4 ^% i/ V6 t% q8 c# \) m
. E6 L5 \/ r- r. @
// 程序运行到此,已经找到了 IHTMLDocument2 的接口指针2 T' Y T/ X1 a0 w$ o7 ^$ ~* ]4 v/ p
}. b6 G1 e1 c4 M
}
' G3 L) }1 x* _4 b/ `. m: O- L0 s' L( W/ O3 o0 a9 a
<6> IE 浏览器控件被一个进程包装在一个子窗口中。那么你首先要得到那个进程的顶层窗口句柄(使用 FindWindow() 函数,或其它任何可行的方法),然后枚举所有子窗口,通过判断窗口类名是否是“Internet Explorer_Server”,从而得到浏览器的窗口句柄,再向窗口发消息取得文档的接口指针。主要代码如下:
5 X& M! @0 y: P4 ]# @0 x! J% V+ R
- x# n8 ]% Q7 `9 N7 T
J* @2 N% S, k' J/ u#include < atlbase.h >
5 ?% x) u/ o" i/ K# ~* a5 [#include < mshtml.h >
- }4 l3 X' L" r/ t- h# _#include < oleacc.h >' [& k1 ?9 v# W( }
#pragma comment ( lib, "oleacc" )1 j; p' |3 s, V- s, E
t4 _+ Z; F( Y& B0 j% ZBOOL CALLBACK EnumChildProc(HWND hwnd,LPARAM lParam)3 c: i7 I; u! F Z
{
/ l: {+ h/ t! C$ V. F TCHAR szClassName[100];+ e; m9 j. B0 g- G1 _) j% O/ `7 ^" q
2 k F8 q/ h" d% v; ~5 _7 h ::GetClassName( hwnd, &szClassName, sizeof(szClassName) );4 {! I! \: \8 {( H, g: W
if ( _tcscmp( szClassName, _T("Internet Explorer_Server") ) == 0 )
5 x: N$ G% a$ G( v2 |% R7 `2 t {8 a! i# ~9 H7 ~3 p
*(HWND*)lParam = hwnd;
1 h J3 N3 H! ?% }' \ return FALSE; // 找到第一个 IE 控件的子窗口就停止) n8 o. `. P& X( \
}# B. @) `3 F- W5 T. T
else return TRUE; // 继续枚举子窗口$ j3 y1 [6 X J* x5 ?6 k4 q+ O
};, Y/ R0 y0 |" }, _
$ K6 B( T+ g: l
void FindFromHwnd(HWND hWnd) 7 K" u R' Z7 S9 W7 a y6 ^3 G0 X
{3 y- D# a/ g& W% T
HWND hWndChild=NULL;
+ d6 L$ p$ Q. W$ A( }6 m ::EnumChildWindows( hWnd, EnumChildProc, (LPARAM)&hWndChild );' m( {( u4 G( `3 n3 n. S9 A
if(NULL == hWndChild) return;
4 U0 v9 [. l0 a7 V+ V4 j( P6 z! k) P. k7 C1 ~( t/ _4 T
UINT nMsg = ::RegisterWindowMessage( _T("WM_HTML_GETOBJECT") );
. I+ n2 K& K- p' y+ L LRESULT lRes;
' K8 K P, B& V ::SendMessageTimeout( hWndChild, nMsg, 0L, 0L, SMTO_ABORTIFHUNG, 1000, (DWORD*) &lRes );$ P3 Q5 u5 F! n- U& A, w
$ D: \0 V) l1 M8 p6 ?/ I
CComPtr < IHTMLDocument2 > spDoc;/ o/ m5 Y/ G4 R0 c
HRESULT hr = ::ObjectFromLresult ( lRes, IID_IHTMLDocument2, 0 , (LPVOID *) &spDoc );
2 U/ z5 n% V$ L1 W2 A if ( FAILED ( hr ) ) return;% p2 s$ Y; o/ `! f2 I7 F
3 L6 g8 Q# [# O, U
// 程序运行到此,已经找到了 IHTMLDocument2 的接口指针
% q2 V+ I5 ], @' u* l' m) }( g} |
|