|
根据IE浏览器的运行方式,有多种不同的方式可以获取文档指针。2 C0 E$ D, i/ L% X9 T9 k
4 }/ m. B/ W) J8 l" B! G! z$ U
<1> 如果你在程序中使用MFC的 CHtmlView 视来浏览网页。$ ?! b+ K7 C+ E1 w+ Z% D
取得文档的方法最简单,调用 CHtmlView::GetHtmlDocument() 函数。
% A$ ]+ b9 G4 H0 z <2> 如果你的程序中使用了“Web 浏览器” 的ActiveX 控件。. _5 B- }( D3 ^2 M4 d5 U
取得文档的方法也比较简单,调用 CWebBrowser2::GetDocument() 函数。
' l5 a w- C$ d c: b' B <3> 如果你的程序是用 ATL 写的 ActiveX 控件。& G- [9 g4 H1 k, {! K6 R! \$ s9 c
那么需要调用 IOleClientSite::GetContainer 得到 IOleContainer 接口,然后就可以通过 QueryInterface() 查询得到 IHTMLDocument2 的接口。主要代码如下:
$ t4 E0 e5 K( H* C) h; ~3 R
+ z# x) g' I0 e2 y+ E! uCComPtr < IOleContainer > spContainer;
- @8 C, K2 z5 e# d* N; Qm_spClientSite->GetContainer( &spContainer );
0 ~, o6 g2 Y; O- @0 u9 H! G3 U) qCComQIPtr < IHTMLDocument2 > spDoc = spContainer;
- q' z% S) u- D* eif ( spDoc )
7 X- v2 e9 I- l: g4 Z{
3 I. z6 H$ b# p/ k E // 已经得到了 IHTMLDocument2 的接口指针1 w% R3 c8 }. q' s: m+ J. d+ x3 o5 P
}- J6 a6 [0 n) i9 h R8 w
% g% J! [- u1 f: K0 ~
<4> 如果你的程序是用 MFC 写的 ActiveX 控件。
# r6 w! h6 J% K 那么需要调用 COleControl::GetClientSite() 得到 IOleContainer 接口,然后的操作和<3>是一致的了。
& }9 o/ w1 q a/ T <5> IE 浏览器作为独立的进程正在运行。
& ~ {7 }# s' {# i. a 每个运行的浏览器(IE 和 资源浏览器)都会在 ShellWindows 中进行登记,因此我们要通过 IShellWindows 取得实例(示例程序中使用的就是这个方法)。主要代码如下:
2 Y) i- Z( x9 o# Q) U$ D* I9 J& b. r& l! ?
#include < atlbase.h >- D+ K/ H# h4 M. s
#include < mshtml.h >; E3 ^! w/ q3 D$ b# G* |' c
) |& a5 M8 V( m2 k, _; s/ g
void FindFromShell()
! v7 P/ z* k# ? E- A{
" h- C6 u8 H3 M M6 d$ g8 Q. y8 J- N CComPtr< IShellWindows > spShellWin;
( n9 I @" v7 i! B* z. X HRESULT hr = spShellWin.CoCreateInstance( CLSID_ShellWindows );/ d! G& z5 k2 V1 n+ X6 r
if ( FAILED( hr ) ) return;% _9 \7 }: W0 s; x+ G) ^5 k
0 H$ q; }* m$ ~" B
long nCount=0;
2 l4 E4 Q0 k B+ ~' ` h, K4 z spShellWin->get_Count(&nCount); // 取得浏览器实例个数- k: `: B9 z9 L- ~' X% r" [
- h5 G+ Y7 W1 g3 b2 w4 K4 @
for(long i=0; i<nCount; i++). u/ |. }1 _* V! g. |5 s. y
{
! ]* @; Q; q( o6 t CComPtr< IDispatch > spDisp;1 L" Q) w" E% @% K* {+ Y
hr=spShellWin->Item(CComVariant( i ), &spDisp );+ }) |+ s v/ C; h, f# f7 ~9 D A
if ( FAILED( hr ) ) continue;
" N0 b$ D- r9 ^6 t) b: ]. O+ t+ a5 S) [7 L% x3 k' F8 P+ N! n
CComQIPtr< IWebBrowser2 > spBrowser = spDisp;
& ]# L$ ?; M, f) j2 E6 \/ P- I if ( !spBrowser ) continue;
5 S7 X: T. h$ b
5 `6 k+ D( n' H8 A# Y spDisp.Release();% _1 r) Q3 j" Z3 G% R
hr = spBrowser->get_Document( &spDisp );
0 I* Y3 ^: C! { if ( FAILED ( hr ) ) continue;
' }" b% d0 X, r/ F( t: U2 E
& T7 r5 e" q G8 n% ]2 f: M4 z CComQIPtr< IHTMLDocument2 > spDoc = spDisp;8 N& y. z" g& B2 s3 N
if ( !spDoc ) continue;
& c% R5 Q# m8 I- ~8 N( E2 B0 D- h m
// 程序运行到此,已经找到了 IHTMLDocument2 的接口指针" q2 L7 ~* d0 v2 o- _- l: E; U
}5 `* n& U9 P/ }4 b: P, d
}, p6 o7 e* p4 M4 Z. S) m& W
. W3 B) r) d" J, J
<6> IE 浏览器控件被一个进程包装在一个子窗口中。那么你首先要得到那个进程的顶层窗口句柄(使用 FindWindow() 函数,或其它任何可行的方法),然后枚举所有子窗口,通过判断窗口类名是否是“Internet Explorer_Server”,从而得到浏览器的窗口句柄,再向窗口发消息取得文档的接口指针。主要代码如下: 1 g# U) b/ K+ y, f* ?& s
4 I1 Q$ Y( g( j, `) Q `
/ X$ E. `. W$ ~* k/ |0 u3 @
#include < atlbase.h >" \8 B7 D" D& b1 v; C! d' y2 W# o8 g
#include < mshtml.h >
1 h6 y# x4 p+ n) W& ^' k+ f1 m b#include < oleacc.h >
, ~7 a4 d& c0 Y: o. a, R; I/ C3 k. l#pragma comment ( lib, "oleacc" )& k6 [8 p/ {" d) g
- H# L2 J: b* ]2 y! A& f( `. m8 z* FBOOL CALLBACK EnumChildProc(HWND hwnd,LPARAM lParam)
: |1 E' _0 i3 ?- a* c2 c0 ?4 a9 L. h{
i; [$ P7 k; }. w( } TCHAR szClassName[100];7 O9 \) N2 ?+ }) N3 z
# D: J. {2 X3 K: M5 E, t
::GetClassName( hwnd, &szClassName, sizeof(szClassName) );2 M1 P, L/ u* k: Z
if ( _tcscmp( szClassName, _T("Internet Explorer_Server") ) == 0 )
: z0 n4 S% h" E l2 F {9 p7 j' M: `9 D3 l6 j
*(HWND*)lParam = hwnd;
* ~0 w, k: d% T% W return FALSE; // 找到第一个 IE 控件的子窗口就停止) I; \8 ^9 B& L2 u
}
( y; _ r% N4 o- Z& d& U; u7 }" F3 G( Z else return TRUE; // 继续枚举子窗口
5 B) [- ~7 R% g/ t- I, ^};* ^4 {2 w6 G6 i
/ Q% H, ^' [. f; J0 v3 B2 Y! hvoid FindFromHwnd(HWND hWnd) & a3 r( h0 _" v+ D: _8 u
{6 c8 q% {! F9 B) V9 N( D6 [# e
HWND hWndChild=NULL;
) y9 o3 r7 ?" c. o0 ~+ q ::EnumChildWindows( hWnd, EnumChildProc, (LPARAM)&hWndChild );6 h/ G" `! n4 V; h+ B
if(NULL == hWndChild) return;0 v7 F D0 @- R" ?5 `
4 @+ C+ T& k- E, ?7 D( S) X
UINT nMsg = ::RegisterWindowMessage( _T("WM_HTML_GETOBJECT") );$ K/ n, Y7 Y) o) {
LRESULT lRes;' ^" _* R7 q" B. U: Z0 t
::SendMessageTimeout( hWndChild, nMsg, 0L, 0L, SMTO_ABORTIFHUNG, 1000, (DWORD*) &lRes );9 O/ O* s! p' g6 k* Q4 O: I
! X% z$ K& R1 F+ R CComPtr < IHTMLDocument2 > spDoc;; q1 s8 c& c" r/ \: [
HRESULT hr = ::ObjectFromLresult ( lRes, IID_IHTMLDocument2, 0 , (LPVOID *) &spDoc );
$ k% e2 [6 b# F1 x# {, p; A- \2 i$ q if ( FAILED ( hr ) ) return;
- G1 c, c4 a/ }5 v m+ s1 Q: X* ^: R; @5 D* I9 U& m0 N4 |
// 程序运行到此,已经找到了 IHTMLDocument2 的接口指针9 i/ [& |. Q" S( ?# w2 b1 m
} |
|