|
|
根据IE浏览器的运行方式,有多种不同的方式可以获取文档指针。& b% Z4 Y- |$ E% A- k7 T& N2 v2 Z$ F# U
3 h/ U. O3 @7 K. o
<1> 如果你在程序中使用MFC的 CHtmlView 视来浏览网页。
/ y# l' b2 R) {2 q5 B 取得文档的方法最简单,调用 CHtmlView::GetHtmlDocument() 函数。
& Z8 F, Q" F" U& G <2> 如果你的程序中使用了“Web 浏览器” 的ActiveX 控件。; J. U) p; v9 i
取得文档的方法也比较简单,调用 CWebBrowser2::GetDocument() 函数。' |: H/ U, W: `3 i2 e6 j7 G* _
<3> 如果你的程序是用 ATL 写的 ActiveX 控件。
' b9 S0 b- _! e% i 那么需要调用 IOleClientSite::GetContainer 得到 IOleContainer 接口,然后就可以通过 QueryInterface() 查询得到 IHTMLDocument2 的接口。主要代码如下:
; R3 [7 G" ~6 L% Y u1 c# e8 h
CComPtr < IOleContainer > spContainer;) {: r: m' `7 t* s" I: d: Q+ [ f
m_spClientSite->GetContainer( &spContainer );
0 Y1 p7 t* L, ?1 M) n/ T8 CCComQIPtr < IHTMLDocument2 > spDoc = spContainer;, |# `2 Q, v, g
if ( spDoc )9 X2 Y J/ \8 q* S& C# z% q. y
{
/ {- c# D- j7 q/ u- u0 H9 Z // 已经得到了 IHTMLDocument2 的接口指针
" Q( d2 ` ^, @4 p}" W/ J9 G- S+ S# t3 J- k" H
F3 ~" n j+ x <4> 如果你的程序是用 MFC 写的 ActiveX 控件。( B6 V1 T6 t6 Y* O. k
那么需要调用 COleControl::GetClientSite() 得到 IOleContainer 接口,然后的操作和<3>是一致的了。
& m; B0 ~) N0 l <5> IE 浏览器作为独立的进程正在运行。
0 t) C: Z B3 S 每个运行的浏览器(IE 和 资源浏览器)都会在 ShellWindows 中进行登记,因此我们要通过 IShellWindows 取得实例(示例程序中使用的就是这个方法)。主要代码如下:1 l7 ]% A* w! o1 w; D* d9 F
9 A8 g% ]4 K7 u% `( I
#include < atlbase.h >3 k: y/ } I+ ~/ i. `0 K
#include < mshtml.h >( x" P H9 }; [' Y4 X+ h- v
/ ~8 X4 D* t) r& ]) g; d
void FindFromShell() / B+ u( L& |) G v0 g
{& X$ y8 d8 c1 x% P
CComPtr< IShellWindows > spShellWin;
, U7 G; [9 I' S& p( P9 z* Y7 k HRESULT hr = spShellWin.CoCreateInstance( CLSID_ShellWindows );
3 S2 D9 M7 ?+ y" \9 r+ @2 j/ i if ( FAILED( hr ) ) return;
0 O0 ^: f4 H4 a. u4 q' _
3 F: l( q. l6 I# R long nCount=0;, m+ r% \- K& S
spShellWin->get_Count(&nCount); // 取得浏览器实例个数+ h. L: u+ {* {8 M7 g) O. S
) |1 a2 a6 \" b* t for(long i=0; i<nCount; i++)- m* W* b) r5 W: U: Z
{) B; }( l6 t n
CComPtr< IDispatch > spDisp;
. m. Q* ]4 }$ y1 F. @ hr=spShellWin->Item(CComVariant( i ), &spDisp );
0 L% g) L" r5 b" ? if ( FAILED( hr ) ) continue;
1 S" C% i( ]. ?6 O; k3 M* [; i0 U' J$ f) t
CComQIPtr< IWebBrowser2 > spBrowser = spDisp;8 ]! J0 S5 a' m+ b7 y0 @
if ( !spBrowser ) continue;
9 g% {2 U9 z5 Q# r' s4 d/ r1 c2 o
' U+ U R0 f' Y4 ^& ] spDisp.Release();
2 q5 O$ R6 G7 o( a5 X hr = spBrowser->get_Document( &spDisp );/ g4 Y1 d; Y) D% p& D" L2 G; o
if ( FAILED ( hr ) ) continue;
+ G# c5 ^. C$ Z% @" T9 @ h5 L( ^: O) Z- e# T7 e
CComQIPtr< IHTMLDocument2 > spDoc = spDisp;
: ?% R) Q$ v+ x; J6 ?7 H$ x if ( !spDoc ) continue; K! j4 i! E) T7 ?5 P5 \6 ^
( l1 z- M& m( U8 k% {7 f) _ // 程序运行到此,已经找到了 IHTMLDocument2 的接口指针
! ]. Q; e1 N7 X5 r }3 ^, h* P, c; b
}5 w7 z+ z, P2 O& J/ P* Q
: R* Y7 l: }! m \
<6> IE 浏览器控件被一个进程包装在一个子窗口中。那么你首先要得到那个进程的顶层窗口句柄(使用 FindWindow() 函数,或其它任何可行的方法),然后枚举所有子窗口,通过判断窗口类名是否是“Internet Explorer_Server”,从而得到浏览器的窗口句柄,再向窗口发消息取得文档的接口指针。主要代码如下:
- y9 S$ W9 H( S# z
! i f4 V+ c$ x: ^
& k- O4 Y2 k' v#include < atlbase.h >8 H7 F9 I" Q1 m9 h
#include < mshtml.h >
$ E$ J& n; e( i* z$ y; ^" O2 K#include < oleacc.h >$ Y, ?; Q) q) l% ~7 E4 N3 J
#pragma comment ( lib, "oleacc" )- v2 @7 I9 F/ J+ ?; f
3 M' e" m5 l4 Z5 f
BOOL CALLBACK EnumChildProc(HWND hwnd,LPARAM lParam)' Y4 v/ w# ]( S: I) S
{( R! m! z6 E6 \# A2 v6 J9 _
TCHAR szClassName[100];
8 e' ~0 z. I$ y( h% A) i% `# R3 u
::GetClassName( hwnd, &szClassName, sizeof(szClassName) );
3 Y- ?6 s% J, ]# R5 c if ( _tcscmp( szClassName, _T("Internet Explorer_Server") ) == 0 )+ V1 B. ]6 _6 M' N- M. o6 V9 l
{0 P# l' M2 _8 n) y2 _ j
*(HWND*)lParam = hwnd;* {5 @; o# t G4 g' _1 o5 R! S
return FALSE; // 找到第一个 IE 控件的子窗口就停止5 p" H, {* [# ?% w1 j% {* [
}5 k; J! o8 H+ N
else return TRUE; // 继续枚举子窗口; X" X, l" G( n0 l# b
};! P9 { ^) K) ?7 s; {2 q7 O
. t: L5 V& ?2 r! ~void FindFromHwnd(HWND hWnd)
5 C! ^7 U) r0 f9 e+ k& Q f{
4 W) R; Y4 T6 S' F6 g HWND hWndChild=NULL;6 _6 J3 `9 F* u0 ~8 t: Q* Q8 X8 H/ S
::EnumChildWindows( hWnd, EnumChildProc, (LPARAM)&hWndChild );! h" `" ?" L7 c* c
if(NULL == hWndChild) return;
3 {/ j$ l/ ?- ^! d' W w' D: f2 x# Y& l% I' [! U# M; P* @
UINT nMsg = ::RegisterWindowMessage( _T("WM_HTML_GETOBJECT") );
! v6 W* G7 f/ N+ ^1 F LRESULT lRes;' z, m& _: I( E
::SendMessageTimeout( hWndChild, nMsg, 0L, 0L, SMTO_ABORTIFHUNG, 1000, (DWORD*) &lRes );
6 \. T0 k# G1 Q3 Y2 X5 g6 R* w9 A; ?7 M& Z6 V: z
CComPtr < IHTMLDocument2 > spDoc;2 T; [( E. @9 g' g# P
HRESULT hr = ::ObjectFromLresult ( lRes, IID_IHTMLDocument2, 0 , (LPVOID *) &spDoc );0 e( n0 V0 G& h* B7 ]% s
if ( FAILED ( hr ) ) return;6 C# {" J3 v7 _! G& n
. H% x3 V' r- _ d* z) J3 ^
// 程序运行到此,已经找到了 IHTMLDocument2 的接口指针8 l" f4 I7 W. o) ?
} |
|