|
|
根据IE浏览器的运行方式,有多种不同的方式可以获取文档指针。 E: B$ U. k( I6 j. Z: p4 `
, X. {: K! Q9 R! X' ^9 I$ l' w
<1> 如果你在程序中使用MFC的 CHtmlView 视来浏览网页。5 ~0 O' L, e" U
取得文档的方法最简单,调用 CHtmlView::GetHtmlDocument() 函数。
5 x- X& t, f6 n, k$ D <2> 如果你的程序中使用了“Web 浏览器” 的ActiveX 控件。4 \# h0 c3 [4 @' q" G
取得文档的方法也比较简单,调用 CWebBrowser2::GetDocument() 函数。$ [; b6 z; H. m: Y
<3> 如果你的程序是用 ATL 写的 ActiveX 控件。
* L6 Q4 j" `( k5 f" E4 E J 那么需要调用 IOleClientSite::GetContainer 得到 IOleContainer 接口,然后就可以通过 QueryInterface() 查询得到 IHTMLDocument2 的接口。主要代码如下:
! N" l4 ^0 _& Y
! k+ v! s! H. Z& ]" ZCComPtr < IOleContainer > spContainer;9 I% D4 S1 i' h& U. z1 ]2 R4 P
m_spClientSite->GetContainer( &spContainer );/ ~: v ` A% Y2 T( a' R \5 j8 l/ w \
CComQIPtr < IHTMLDocument2 > spDoc = spContainer;
% h+ Y' u7 X% l9 C% `+ A( x tif ( spDoc )
" Q8 y( @' S {$ m{2 Y$ i" _; d O" K8 E. `
// 已经得到了 IHTMLDocument2 的接口指针
$ \2 s4 u: [8 e. t4 z# S0 A}/ @, S- H6 A1 q2 N2 r# x6 m
+ v4 ]2 T$ ]. ~6 B" ]$ p4 W r
<4> 如果你的程序是用 MFC 写的 ActiveX 控件。
7 k A/ A, K/ r8 V2 U7 E: \ 那么需要调用 COleControl::GetClientSite() 得到 IOleContainer 接口,然后的操作和<3>是一致的了。
- Y) o* Q! C' b2 f <5> IE 浏览器作为独立的进程正在运行。
2 O; ?& H' e/ W, P 每个运行的浏览器(IE 和 资源浏览器)都会在 ShellWindows 中进行登记,因此我们要通过 IShellWindows 取得实例(示例程序中使用的就是这个方法)。主要代码如下:
3 ^7 _- o0 E9 _& F1 o0 r$ W! o' E$ D+ x: Q) ]5 I+ T E$ W
#include < atlbase.h >
; b; R5 g c: v3 S2 X* {, J! o#include < mshtml.h >& {- f; x8 Z: r2 y! ~" d. \3 j
# `$ K9 f8 n+ B( v. M! l: J
void FindFromShell()
5 W s/ n7 s9 N/ M a{
) l, @+ q, N8 d' `' d CComPtr< IShellWindows > spShellWin;
* z! L1 Z0 a& n& w4 t2 r* w HRESULT hr = spShellWin.CoCreateInstance( CLSID_ShellWindows );
% Y, |5 T( c1 I if ( FAILED( hr ) ) return;
6 N6 e, R- ^$ k+ n% L
8 n% |' E, z9 M* P7 v long nCount=0;
- r5 t5 r7 b& p4 ]' X spShellWin->get_Count(&nCount); // 取得浏览器实例个数
" K/ D% h" d- s3 `- Y# {6 H6 u7 a4 \7 g7 e7 T. P" ~0 @& p
for(long i=0; i<nCount; i++)2 K7 G$ D/ G2 S4 V
{
( s5 \3 e2 u$ D8 w% N CComPtr< IDispatch > spDisp;
3 {% b0 j4 ^; z$ y hr=spShellWin->Item(CComVariant( i ), &spDisp );7 o9 I6 s( x- g, Q) ^4 l
if ( FAILED( hr ) ) continue;# |" ] U: B* p( a
% E. W7 D/ j- j( n8 |: s
CComQIPtr< IWebBrowser2 > spBrowser = spDisp;
# U% p; v1 W7 r( ? if ( !spBrowser ) continue;. K& X% U. x/ ?5 h! J# p
& u7 D) ~! i0 W! L" k spDisp.Release();3 {0 c; M6 M. F
hr = spBrowser->get_Document( &spDisp );
V$ R( T8 u/ l# H if ( FAILED ( hr ) ) continue;# p1 c2 E+ j+ h B( L- Y6 y
% Y! @8 [* X& C
CComQIPtr< IHTMLDocument2 > spDoc = spDisp;
' k3 ]9 e% f; Y* u* O2 r if ( !spDoc ) continue;
. V, ], B; G$ x( k$ B* Q9 I
8 \; \0 j! ^1 L: L% Y' n // 程序运行到此,已经找到了 IHTMLDocument2 的接口指针, q" v) K8 z* V4 D
}3 ^$ s8 ~# h7 b( z8 h
}
3 ^: w7 t: n1 z
* q7 Q; j" p5 T. M$ f7 A- L: I <6> IE 浏览器控件被一个进程包装在一个子窗口中。那么你首先要得到那个进程的顶层窗口句柄(使用 FindWindow() 函数,或其它任何可行的方法),然后枚举所有子窗口,通过判断窗口类名是否是“Internet Explorer_Server”,从而得到浏览器的窗口句柄,再向窗口发消息取得文档的接口指针。主要代码如下:
1 P7 g0 O& @+ \4 `( w6 D4 Z
) k8 ` }- {6 ]$ t9 X
% a4 u5 j$ T6 }4 A8 D/ X6 P#include < atlbase.h >
5 O3 x/ g( Q& m3 x+ O: I( I#include < mshtml.h >
7 v) q9 S& L+ q/ e+ ~7 Q#include < oleacc.h >
1 |# M7 h$ y2 l4 C#pragma comment ( lib, "oleacc" )$ @3 R2 ~1 b* {/ D: ]' Y
$ c# n6 O; g* f- k) OBOOL CALLBACK EnumChildProc(HWND hwnd,LPARAM lParam)
. O2 f; E3 U, C R9 N( @. t{
; N% p+ Q9 q9 ?6 H TCHAR szClassName[100];" P5 p5 k. S" e5 a8 {: Q; V# k/ q
4 |3 j4 a1 v/ e8 W8 _, I6 d ::GetClassName( hwnd, &szClassName, sizeof(szClassName) );% w; U0 ~" a1 V
if ( _tcscmp( szClassName, _T("Internet Explorer_Server") ) == 0 )
+ t' a2 `& \; l2 A# K, R" h {
; J1 b' [$ f4 ?, \. K! r *(HWND*)lParam = hwnd;' M& h- \2 y. k. n! d* r
return FALSE; // 找到第一个 IE 控件的子窗口就停止0 B& N) e4 R! u% y( o
}1 J7 ^) {' y* L/ O) K; @; |9 x
else return TRUE; // 继续枚举子窗口8 O T9 G. t6 H' @) U6 [: X0 d4 H
};+ G& T1 U7 `6 I, K7 }
1 S& Y( Y8 t4 o, h; ~% z5 U6 [
void FindFromHwnd(HWND hWnd) ( \! H$ l0 U9 b
{
6 ?. z1 O' T' G% K HWND hWndChild=NULL;
( j, s f$ L9 c' j ::EnumChildWindows( hWnd, EnumChildProc, (LPARAM)&hWndChild );5 J; a0 O' V- G
if(NULL == hWndChild) return;
- v2 V! Y2 s% l# M5 ^) G
! A$ {4 J, o% P: k4 S* m3 H UINT nMsg = ::RegisterWindowMessage( _T("WM_HTML_GETOBJECT") );) J. u! N2 h+ R) c
LRESULT lRes;
# W5 j4 Z0 O3 U ::SendMessageTimeout( hWndChild, nMsg, 0L, 0L, SMTO_ABORTIFHUNG, 1000, (DWORD*) &lRes );: U# y/ U4 Y; F' q8 g) n4 @
" I9 z: t# Z, ]1 ?- x6 T; S( o CComPtr < IHTMLDocument2 > spDoc;
' a5 x1 ?0 ~/ N! ]" J* {; K0 { HRESULT hr = ::ObjectFromLresult ( lRes, IID_IHTMLDocument2, 0 , (LPVOID *) &spDoc );
a2 g- t) o' Q3 F# q8 P. C if ( FAILED ( hr ) ) return;+ r* W3 k3 g. j5 c* F1 K! F+ T
( K: V3 Q) W) F! J& ]$ a
// 程序运行到此,已经找到了 IHTMLDocument2 的接口指针
0 X; V$ S, @. f, }1 m! d} |
|