|
|
根据IE浏览器的运行方式,有多种不同的方式可以获取文档指针。
3 J) j3 x4 o$ H. T V2 I4 w, f# S
$ e4 t0 r% ^$ [; i3 Z4 j4 ] <1> 如果你在程序中使用MFC的 CHtmlView 视来浏览网页。
$ }! p, M* b9 N) m& e* } 取得文档的方法最简单,调用 CHtmlView::GetHtmlDocument() 函数。8 t3 P6 m% e+ Z
<2> 如果你的程序中使用了“Web 浏览器” 的ActiveX 控件。7 A4 M$ m: u! k
取得文档的方法也比较简单,调用 CWebBrowser2::GetDocument() 函数。
+ |) D$ Z: @6 A) y <3> 如果你的程序是用 ATL 写的 ActiveX 控件。 a* N- ]/ w* ^1 \# q; a" R% d
那么需要调用 IOleClientSite::GetContainer 得到 IOleContainer 接口,然后就可以通过 QueryInterface() 查询得到 IHTMLDocument2 的接口。主要代码如下: 7 F! w9 W; i( C$ ^$ {: m8 D0 |; N6 `5 b
' N1 ^7 L+ |3 G" cCComPtr < IOleContainer > spContainer;
6 q( H" f: i8 T; Zm_spClientSite->GetContainer( &spContainer );
2 M2 r" C: ^2 W; \) i2 w) G- ]CComQIPtr < IHTMLDocument2 > spDoc = spContainer;
2 {" g T7 O) H/ T( V; ^- Aif ( spDoc )
# a' i! F/ d9 p9 Y1 n7 _5 b{
; o" K8 B) ]$ @. a // 已经得到了 IHTMLDocument2 的接口指针
/ H! i7 T& m7 S, m" {4 l2 D9 O' r}
! @) O2 B; _. |) M1 f$ m4 _- J( e2 G. c' m- @
<4> 如果你的程序是用 MFC 写的 ActiveX 控件。
, \( O7 |# ]5 W3 Z# G. ~. Y 那么需要调用 COleControl::GetClientSite() 得到 IOleContainer 接口,然后的操作和<3>是一致的了。0 B% I5 G3 w) q7 P- l& A3 M2 C" C
<5> IE 浏览器作为独立的进程正在运行。
: G3 M) n2 W( z$ B 每个运行的浏览器(IE 和 资源浏览器)都会在 ShellWindows 中进行登记,因此我们要通过 IShellWindows 取得实例(示例程序中使用的就是这个方法)。主要代码如下:
; Y3 i V8 v: n' z, F5 c) t* o2 ] d. Q9 o
#include < atlbase.h >! B+ L x9 d8 s, [
#include < mshtml.h >$ f1 t. d" M( Q* f
( X+ a! L/ d/ ~. X1 Z
void FindFromShell() - [8 o( B+ j0 ~+ U7 N
{
# b# }' v* E% i- E* ~4 A CComPtr< IShellWindows > spShellWin;* [- f- O' U( E2 P# s) T( j4 r
HRESULT hr = spShellWin.CoCreateInstance( CLSID_ShellWindows );1 u* J: @. w. ^1 \% U5 w+ B" a" w
if ( FAILED( hr ) ) return;" E$ l8 `9 v& l- D( s* O! T9 |$ m
4 h6 G# u0 ?' I- g: s# j" v
long nCount=0;/ v. ?4 Z7 T) k' \: o
spShellWin->get_Count(&nCount); // 取得浏览器实例个数- G0 V/ ]) a* p, V
( l; I' Y# \$ G, z
for(long i=0; i<nCount; i++)
2 x$ q, t6 T0 { {
$ T) M2 B7 b* u9 n! W5 r8 \ CComPtr< IDispatch > spDisp;
, ]3 i/ v' C* J hr=spShellWin->Item(CComVariant( i ), &spDisp );0 P, L7 Y% S% @! P
if ( FAILED( hr ) ) continue;
$ H( n1 x1 N" t9 x/ ~) R9 V) s, j, D& F, p, C* o
CComQIPtr< IWebBrowser2 > spBrowser = spDisp;( C9 A- m6 M5 Y0 f; B' n0 S) i! {6 v+ e
if ( !spBrowser ) continue;. \( @# d1 L& t% s
' d" A' Q+ W4 T9 Q2 L* ^
spDisp.Release();
1 K+ L/ Z1 [* u& C hr = spBrowser->get_Document( &spDisp );
9 M4 R2 {0 R; u1 C+ h2 q if ( FAILED ( hr ) ) continue;
7 M8 b3 n( @9 A; E! j" y' g( R' z& H* N2 U0 |& ~. y
CComQIPtr< IHTMLDocument2 > spDoc = spDisp;$ w1 E6 q- C6 [" r/ o5 X/ _; L6 ~
if ( !spDoc ) continue;; |2 y4 h; f2 K) j
$ A. W6 Z9 N( n" t5 x
// 程序运行到此,已经找到了 IHTMLDocument2 的接口指针
' H% _( H+ n' [) ] }* u6 o( y! P* W' _
}
; b" t% O4 Z2 r- }* u7 q! n
0 l* c0 l0 J8 d+ q <6> IE 浏览器控件被一个进程包装在一个子窗口中。那么你首先要得到那个进程的顶层窗口句柄(使用 FindWindow() 函数,或其它任何可行的方法),然后枚举所有子窗口,通过判断窗口类名是否是“Internet Explorer_Server”,从而得到浏览器的窗口句柄,再向窗口发消息取得文档的接口指针。主要代码如下: 0 E3 i q8 ], C3 U1 ?' c
9 ?" C0 J2 S: A, p' R% j; Z5 n. V+ m* V1 i8 x
#include < atlbase.h >
; y: R! I7 e4 h: H6 g3 m3 d3 o#include < mshtml.h >+ m; j# h& {2 F$ W) k
#include < oleacc.h >. Q8 k8 K' |& F$ @& a" P
#pragma comment ( lib, "oleacc" )4 O& X# E ?& f$ @
, V: Y6 J+ H% g2 x. tBOOL CALLBACK EnumChildProc(HWND hwnd,LPARAM lParam)
3 W1 h. X6 z# g! q{
' K. E( u" F @) t5 B# q5 v% _2 | TCHAR szClassName[100];
! E3 z: M6 P9 O# J) }% Y: v
2 }$ K/ I! Q3 a8 ~2 Z0 | ::GetClassName( hwnd, &szClassName, sizeof(szClassName) );
; A3 t6 D1 H) i3 k; j% @1 i1 I0 A if ( _tcscmp( szClassName, _T("Internet Explorer_Server") ) == 0 )
# c0 ]/ |( I- z1 M; p# K% s {
4 q3 A# {% U @0 R7 e% P1 I: _+ f *(HWND*)lParam = hwnd; a# {5 H; Y, D' j2 `$ S' O
return FALSE; // 找到第一个 IE 控件的子窗口就停止. v& j3 o% s; y1 O
}, z# I8 S8 S, z* x9 u9 b6 P; B
else return TRUE; // 继续枚举子窗口
X M0 x7 T3 M7 T3 _6 O* }! H};
" G6 E0 x6 I+ T; O/ m* A1 s" g% C# H! |
void FindFromHwnd(HWND hWnd)
) `. k8 m4 J+ A{6 [6 ?6 m X" c- G- v
HWND hWndChild=NULL;
Y! J: ?; C/ e# r D/ [. M% v ::EnumChildWindows( hWnd, EnumChildProc, (LPARAM)&hWndChild );
* O/ {" J. E' Q if(NULL == hWndChild) return;" w6 f- W( m$ p$ l1 |
5 b) Z ?" _4 k2 Z, H
UINT nMsg = ::RegisterWindowMessage( _T("WM_HTML_GETOBJECT") ); n9 C1 d- N* L% I$ v9 h+ I, a) R
LRESULT lRes;" t9 H5 F4 ]/ ^7 ~, m2 S- _
::SendMessageTimeout( hWndChild, nMsg, 0L, 0L, SMTO_ABORTIFHUNG, 1000, (DWORD*) &lRes );
1 D9 D& q" @' h) O6 t1 G, ^, r; r0 Y/ S
CComPtr < IHTMLDocument2 > spDoc;
2 ^- W {& Y g HRESULT hr = ::ObjectFromLresult ( lRes, IID_IHTMLDocument2, 0 , (LPVOID *) &spDoc );
4 ~! {' }) J* Z if ( FAILED ( hr ) ) return;
4 B8 E0 Y5 W$ Y; V& d8 D) I8 d' g4 r' |. j5 u Y
// 程序运行到此,已经找到了 IHTMLDocument2 的接口指针8 }7 v8 \ }7 J% _' m, D! c" b
} |
|