|
根据IE浏览器的运行方式,有多种不同的方式可以获取文档指针。4 C( ?, s9 f! ^$ x4 @: w5 B
; _8 n0 P& Z. d: D
<1> 如果你在程序中使用MFC的 CHtmlView 视来浏览网页。, @9 f2 P3 H( P5 Z
取得文档的方法最简单,调用 CHtmlView::GetHtmlDocument() 函数。2 w4 ~# Y4 h+ C8 I/ ?+ @7 V: [1 B
<2> 如果你的程序中使用了“Web 浏览器” 的ActiveX 控件。
4 G3 y0 L6 {. c$ @- D 取得文档的方法也比较简单,调用 CWebBrowser2::GetDocument() 函数。3 \6 ]6 @4 `4 m
<3> 如果你的程序是用 ATL 写的 ActiveX 控件。
5 N5 X2 I; O0 t. E* X 那么需要调用 IOleClientSite::GetContainer 得到 IOleContainer 接口,然后就可以通过 QueryInterface() 查询得到 IHTMLDocument2 的接口。主要代码如下:
; ]8 D% l2 |+ T0 ~0 |7 j3 A+ V/ S7 ^) I! S/ f% M; N
CComPtr < IOleContainer > spContainer;
- F0 R. i9 y9 p: tm_spClientSite->GetContainer( &spContainer );0 h, ]0 U# j2 w* Y8 a, D4 o, b9 J
CComQIPtr < IHTMLDocument2 > spDoc = spContainer;) b8 T3 Q6 C2 Y. @. k4 h+ v
if ( spDoc )
* j# [* P* t# y/ u{
]: o" R8 [4 X( m6 `2 M // 已经得到了 IHTMLDocument2 的接口指针
1 k1 z, F% F; G}! s7 W, l2 Y; z
0 }' ?8 [: r7 p" ~2 w) Q3 Y <4> 如果你的程序是用 MFC 写的 ActiveX 控件。; A8 \/ r( o" V$ o2 n
那么需要调用 COleControl::GetClientSite() 得到 IOleContainer 接口,然后的操作和<3>是一致的了。1 T2 k3 ~4 _ l' f, O Q( b
<5> IE 浏览器作为独立的进程正在运行。
: t: m+ ]+ g) a4 w 每个运行的浏览器(IE 和 资源浏览器)都会在 ShellWindows 中进行登记,因此我们要通过 IShellWindows 取得实例(示例程序中使用的就是这个方法)。主要代码如下:
5 }/ ?2 v4 S$ H- A& O* C9 q0 w8 R$ u W! l% e
#include < atlbase.h >
, f; k8 d5 J% d; r#include < mshtml.h >
4 M- K+ E& y5 M* `) y, y) o2 }( Q+ ?; W! D
void FindFromShell()
' I: Q2 y' u* @/ Q( H/ S: Z* D{
! ?" R& w3 V5 T4 F+ _+ a; ]5 i/ K CComPtr< IShellWindows > spShellWin;
( C9 |3 q/ b4 C1 T HRESULT hr = spShellWin.CoCreateInstance( CLSID_ShellWindows );
9 j3 f u+ z% f, Q! r if ( FAILED( hr ) ) return;* Y4 `' G5 _; W9 ?) p$ P3 n
8 H6 u( B b; s1 k
long nCount=0; g4 E, e$ r, B- M+ [! Z
spShellWin->get_Count(&nCount); // 取得浏览器实例个数% p" w! c& F( z- s4 @& {& h- J
( b: ~5 G( I$ M/ w for(long i=0; i<nCount; i++)! A, }3 y* c' P; x `6 X% ]1 O) }
{7 f: P. p- S) v2 o# t+ C
CComPtr< IDispatch > spDisp;
3 c/ I' K, W& Y9 K0 W hr=spShellWin->Item(CComVariant( i ), &spDisp );; v! x" x/ V) _8 }, z7 |
if ( FAILED( hr ) ) continue;) ?* f; M& d0 a$ l2 k( q; {
0 X! {; Q1 w# m% E+ H M$ _4 Z! K0 g
CComQIPtr< IWebBrowser2 > spBrowser = spDisp;* I+ ~! l" a: n% s0 E
if ( !spBrowser ) continue;
/ W p2 j# D/ ], d/ L0 Z9 M! T% T7 G3 d
spDisp.Release();
- I6 N$ _1 n( d' ]0 g& Q$ } hr = spBrowser->get_Document( &spDisp );
F8 H7 f( X% g" C6 L( ^ if ( FAILED ( hr ) ) continue;* v+ U0 R4 ?( x3 i
' z( Y1 T% }6 q: p
CComQIPtr< IHTMLDocument2 > spDoc = spDisp;9 k. h2 W( \- n
if ( !spDoc ) continue;! I7 c" `" P* l1 ], V$ E
, Y k7 v$ s& r+ n // 程序运行到此,已经找到了 IHTMLDocument2 的接口指针
1 P7 P: J c8 c& g. d0 r" h }$ x( F3 E# R- u# z @$ B
}
2 \* @( N9 r2 N! b6 ?% _/ Q
/ p3 }; L, h8 e" ]* ]" K <6> IE 浏览器控件被一个进程包装在一个子窗口中。那么你首先要得到那个进程的顶层窗口句柄(使用 FindWindow() 函数,或其它任何可行的方法),然后枚举所有子窗口,通过判断窗口类名是否是“Internet Explorer_Server”,从而得到浏览器的窗口句柄,再向窗口发消息取得文档的接口指针。主要代码如下: D5 y$ Y% k1 [
. h! u: d% v- i2 v0 Y( o& t' a) L8 U2 f6 [3 [' F
#include < atlbase.h >. w* h& F: _; O, L, n: z
#include < mshtml.h >2 A# A u4 W( c W! h) W
#include < oleacc.h >+ h$ Q% s8 L+ [) U
#pragma comment ( lib, "oleacc" )" ^1 t! X2 M) s
3 d& R' h5 c8 m S
BOOL CALLBACK EnumChildProc(HWND hwnd,LPARAM lParam)
3 s7 d7 C" Z0 a8 P8 O6 g{
+ A% h# }; c( U3 b' A TCHAR szClassName[100];0 T& @+ }- W- G) a; l+ f/ l
5 {, f2 S$ c) D# C% e7 ] ::GetClassName( hwnd, &szClassName, sizeof(szClassName) );0 [* {* l* w" u3 @* x! n
if ( _tcscmp( szClassName, _T("Internet Explorer_Server") ) == 0 )5 M- L, g7 ?. J4 ]# L0 P/ m( K
{
9 G K( v/ |$ N2 B$ {) G1 H' ?# ^ *(HWND*)lParam = hwnd;
' d/ z! s: |: K3 I0 f( s6 V return FALSE; // 找到第一个 IE 控件的子窗口就停止5 O! e2 z/ k4 v
}
& A7 I# N, A( [, W) i else return TRUE; // 继续枚举子窗口" j8 O: F& `" K% R5 H, G: H4 @
};1 n% u' r& g8 F+ _; m$ m" K, S
& W0 R2 x6 \" D2 v" ^+ @
void FindFromHwnd(HWND hWnd) 1 y4 Z3 [6 I% Z, V
{
; m) N! B Z$ L* G, t HWND hWndChild=NULL;
2 B9 j1 Q- M4 P" K+ W3 t% p ::EnumChildWindows( hWnd, EnumChildProc, (LPARAM)&hWndChild );/ x# |/ U, t: J6 x2 X+ S# M* o9 }
if(NULL == hWndChild) return;0 R* A6 p/ X2 f
5 t. T$ u* \, Q! K3 F5 Y
UINT nMsg = ::RegisterWindowMessage( _T("WM_HTML_GETOBJECT") );
. N3 N9 Y8 W9 H0 j LRESULT lRes;
0 _" P1 Z- A& p5 p* b- a6 V ::SendMessageTimeout( hWndChild, nMsg, 0L, 0L, SMTO_ABORTIFHUNG, 1000, (DWORD*) &lRes );
& e& ^# K8 R, \ n+ E
! _' n6 ?0 \. E5 C CComPtr < IHTMLDocument2 > spDoc;
, b6 C# e; C9 } H5 o HRESULT hr = ::ObjectFromLresult ( lRes, IID_IHTMLDocument2, 0 , (LPVOID *) &spDoc ); h" T2 I* P( _+ S/ |5 j2 c* x
if ( FAILED ( hr ) ) return;1 A, A3 b ^8 F- J
1 b) d" ~1 l4 o // 程序运行到此,已经找到了 IHTMLDocument2 的接口指针0 p/ C. p/ E" c" V+ Q4 e+ W
} |
|