|
根据IE浏览器的运行方式,有多种不同的方式可以获取文档指针。
' u8 B/ ~4 A* r3 t9 F$ |2 {" o5 |1 |7 [7 r' V4 T' }
<1> 如果你在程序中使用MFC的 CHtmlView 视来浏览网页。
3 e v. [( }' Z) w" Q! U# s 取得文档的方法最简单,调用 CHtmlView::GetHtmlDocument() 函数。
$ f. F6 h% @% H. Z5 V. ^ <2> 如果你的程序中使用了“Web 浏览器” 的ActiveX 控件。1 Z ]$ R. z6 d) D4 E
取得文档的方法也比较简单,调用 CWebBrowser2::GetDocument() 函数。
7 D6 h2 _$ {) G9 K. @! E* | <3> 如果你的程序是用 ATL 写的 ActiveX 控件。! |: ^! ?8 ]; o0 v/ K$ l
那么需要调用 IOleClientSite::GetContainer 得到 IOleContainer 接口,然后就可以通过 QueryInterface() 查询得到 IHTMLDocument2 的接口。主要代码如下:
- L/ a; Q. L2 H- D9 H/ q% t( R. T8 }; v" g/ W) n
CComPtr < IOleContainer > spContainer;
- ^: ~, G4 S% I8 E) E! Am_spClientSite->GetContainer( &spContainer );5 d6 D7 S2 c2 Z8 h; C
CComQIPtr < IHTMLDocument2 > spDoc = spContainer;) r% ?# c2 p i
if ( spDoc )* O; N) V9 w5 F( f! C
{
2 ~$ E7 @& ^; \! z // 已经得到了 IHTMLDocument2 的接口指针
& R$ [" c. E! x& j}
4 q9 h! s9 u+ D9 E+ }' C$ X9 C9 k! Q
<4> 如果你的程序是用 MFC 写的 ActiveX 控件。
* N E; C) F2 |: e i/ Y 那么需要调用 COleControl::GetClientSite() 得到 IOleContainer 接口,然后的操作和<3>是一致的了。
5 s: u! s; V) k' M. n <5> IE 浏览器作为独立的进程正在运行。
+ r4 l# R& d4 Y& G. O" K 每个运行的浏览器(IE 和 资源浏览器)都会在 ShellWindows 中进行登记,因此我们要通过 IShellWindows 取得实例(示例程序中使用的就是这个方法)。主要代码如下:( |8 I0 W+ k( Y/ u4 r C
! K, g: c' F1 B5 h- R4 J. P
#include < atlbase.h >
: f R: n1 ~. M* G( _1 j0 v( Q. @6 r#include < mshtml.h >1 _& d' j) P* @
; F. O2 S" r7 l, D6 `4 X
void FindFromShell() 5 {+ w* V. }- L8 c8 o
{
& D! b( j/ V9 _ h2 R: q5 q4 z CComPtr< IShellWindows > spShellWin;7 T: W( k2 o V3 V" `1 U+ V
HRESULT hr = spShellWin.CoCreateInstance( CLSID_ShellWindows ); U8 _. S( _$ ]7 T1 A
if ( FAILED( hr ) ) return;
# `. l t5 {9 S: ^! O' s, b7 C7 Y) B8 }
long nCount=0;
5 M4 ~: g3 \: x spShellWin->get_Count(&nCount); // 取得浏览器实例个数
2 o$ Q0 O0 M1 @3 A V
) G* ]% n" z) y ]4 F for(long i=0; i<nCount; i++)
2 s& u2 ^3 I. q4 m: V2 i9 c {: e& i' I7 r8 A$ N& q6 c. B
CComPtr< IDispatch > spDisp;
+ y( F0 a. Z9 {7 n# L hr=spShellWin->Item(CComVariant( i ), &spDisp );
3 Z; h/ s" K! p if ( FAILED( hr ) ) continue;
" j- ?6 R" v. z7 ]8 |- J, N$ O" v" T) G- X* c
CComQIPtr< IWebBrowser2 > spBrowser = spDisp;* d/ l# u7 K0 n4 H" Q
if ( !spBrowser ) continue;
, d, H8 c, R! ]: s% Q6 w, y
9 C6 V# F3 A' E. Y spDisp.Release();# T5 ~8 n* a; s" E4 ` j. h
hr = spBrowser->get_Document( &spDisp );. V8 z. T- h& }( j" K; \
if ( FAILED ( hr ) ) continue;- T: L7 s3 ~' v3 `$ D6 E) y
i" Y5 R# f- Q0 H2 H& h7 w0 u CComQIPtr< IHTMLDocument2 > spDoc = spDisp;
6 P# A- e$ p: w0 j( k- n8 s if ( !spDoc ) continue;
% K0 J! ? w1 g) ~' k$ w3 |
`: m4 o4 z& ` y0 K. L9 w. s. w // 程序运行到此,已经找到了 IHTMLDocument2 的接口指针
& y& L; I) X' s6 z9 M" A }
K; `0 c8 N; C6 s) n}7 x; |8 P3 Z8 r, Z, p
4 l% V: Y, g6 m4 O; r7 H* R5 `
<6> IE 浏览器控件被一个进程包装在一个子窗口中。那么你首先要得到那个进程的顶层窗口句柄(使用 FindWindow() 函数,或其它任何可行的方法),然后枚举所有子窗口,通过判断窗口类名是否是“Internet Explorer_Server”,从而得到浏览器的窗口句柄,再向窗口发消息取得文档的接口指针。主要代码如下: + g( ]6 t Q& {& ]0 o+ [
" Y- |+ l" u# k' B
2 g5 A, T; X5 j! H+ J#include < atlbase.h >
2 g2 p9 u8 H1 Q( q' V# J#include < mshtml.h >
! G) `, d4 @* T; K8 P. p4 _- u#include < oleacc.h >! G: t1 }6 A. w0 K ?+ g0 t0 O
#pragma comment ( lib, "oleacc" )3 s# a0 a: S; ] I: f: E9 y( @
( U$ M; m" M+ E" Q; v6 yBOOL CALLBACK EnumChildProc(HWND hwnd,LPARAM lParam) ~# v* r& W: P( ]; H' c5 d
{9 ~" C' L6 [/ A! ]
TCHAR szClassName[100];* e% N0 U( Z4 f3 e; @, n6 V3 X7 W
# B+ F- Y7 G, w6 o6 x1 M3 h& i- g ::GetClassName( hwnd, &szClassName, sizeof(szClassName) );3 Q' J4 `/ G1 }& p$ [; c x
if ( _tcscmp( szClassName, _T("Internet Explorer_Server") ) == 0 )4 K& o3 @3 z* z" T
{% b3 E' h$ U/ ]4 x- Y, r: D
*(HWND*)lParam = hwnd;0 l0 \( u1 H6 ~9 t/ t# y
return FALSE; // 找到第一个 IE 控件的子窗口就停止
i' i y$ M0 y }* I. H0 N; ?; \0 u' v2 X5 X
else return TRUE; // 继续枚举子窗口0 I8 J, Y+ e; i3 F6 k& G4 V3 W2 N
};
5 a3 C- a, b1 b& n! F7 R( q4 d/ K
void FindFromHwnd(HWND hWnd)
1 i- v9 M/ \& U; U" V, m{( z# a1 j# _1 R6 ^1 F$ M" `
HWND hWndChild=NULL;+ D) a0 ]% M4 p3 L* X$ H. }
::EnumChildWindows( hWnd, EnumChildProc, (LPARAM)&hWndChild );* [) n" Y# Q* n/ d
if(NULL == hWndChild) return;5 a" O+ H3 [2 B& A
2 L6 }) e0 }: J
UINT nMsg = ::RegisterWindowMessage( _T("WM_HTML_GETOBJECT") );
: q( ?- v9 _ m5 h LRESULT lRes;8 g. G2 O# W% {+ c0 M
::SendMessageTimeout( hWndChild, nMsg, 0L, 0L, SMTO_ABORTIFHUNG, 1000, (DWORD*) &lRes );
3 Q- w l/ y3 t- \" \1 W+ g
% X9 Y, j% _# S3 a/ d% } CComPtr < IHTMLDocument2 > spDoc;
( i9 N0 t4 }; i5 H HRESULT hr = ::ObjectFromLresult ( lRes, IID_IHTMLDocument2, 0 , (LPVOID *) &spDoc );, g1 z4 S# d- A
if ( FAILED ( hr ) ) return;
4 ~/ `0 A) p% ~# a4 u/ a! A
7 w- F* F0 m- S( u' Z6 u, o: G // 程序运行到此,已经找到了 IHTMLDocument2 的接口指针7 |% W% }$ p: F8 ~5 J
} |
|