|
根据IE浏览器的运行方式,有多种不同的方式可以获取文档指针。
$ K" C7 }" Z* o) [% U: `
2 Y2 d/ f* F' W2 V <1> 如果你在程序中使用MFC的 CHtmlView 视来浏览网页。
# H) `7 Y- b5 k 取得文档的方法最简单,调用 CHtmlView::GetHtmlDocument() 函数。
( ~, K* J, w. u% j" U; S, V2 m7 D <2> 如果你的程序中使用了“Web 浏览器” 的ActiveX 控件。 l$ _" [- ?; b0 ?) @) v% z
取得文档的方法也比较简单,调用 CWebBrowser2::GetDocument() 函数。
4 X$ K3 `2 |- }# A <3> 如果你的程序是用 ATL 写的 ActiveX 控件。
( o0 T F+ p# N9 y 那么需要调用 IOleClientSite::GetContainer 得到 IOleContainer 接口,然后就可以通过 QueryInterface() 查询得到 IHTMLDocument2 的接口。主要代码如下: ; N( J8 N6 T2 ~4 _3 i
9 C+ Z& N7 Y: v+ BCComPtr < IOleContainer > spContainer;
& g5 A. g6 q, p3 l j e+ Gm_spClientSite->GetContainer( &spContainer );9 w" J0 b" H* `/ h8 a7 {
CComQIPtr < IHTMLDocument2 > spDoc = spContainer;* P( _' C' a0 g) `
if ( spDoc )
* s7 `9 f+ O( C; o{
5 q: x6 O4 f* | // 已经得到了 IHTMLDocument2 的接口指针
& q8 g1 u1 \. O4 v s$ l}) S2 K5 t" m& w" @
; J, f$ W9 W' w; R' i5 {5 Y
<4> 如果你的程序是用 MFC 写的 ActiveX 控件。* q0 q- d# _) |1 x2 d- B
那么需要调用 COleControl::GetClientSite() 得到 IOleContainer 接口,然后的操作和<3>是一致的了。3 w6 b/ @: x9 r" c
<5> IE 浏览器作为独立的进程正在运行。
% I2 i- m z, z. G 每个运行的浏览器(IE 和 资源浏览器)都会在 ShellWindows 中进行登记,因此我们要通过 IShellWindows 取得实例(示例程序中使用的就是这个方法)。主要代码如下:
+ J$ g7 s o ~* `" @4 O: `6 g, {6 g
9 z" [$ P0 T, L4 s2 [#include < atlbase.h >; C1 y8 h: `1 ?* T, i! i7 v2 h6 @
#include < mshtml.h >
. N, V/ e5 ~3 \* h! X6 E, z% ]* w$ @3 P7 u" X
void FindFromShell()
1 z! W( {* h" q' Q0 e" j7 ]{( Z2 z3 t5 ?) n
CComPtr< IShellWindows > spShellWin;1 r( ?/ z. n9 n) [; X
HRESULT hr = spShellWin.CoCreateInstance( CLSID_ShellWindows );
# P! C/ m7 |+ f1 x7 `# a, I7 E if ( FAILED( hr ) ) return;
) I. r Y6 @4 |2 X. s5 Q- h3 _" ?1 C, A$ O w. W2 Y
long nCount=0;
: N% E! E d8 Z8 e* s spShellWin->get_Count(&nCount); // 取得浏览器实例个数
9 q4 H+ {& p7 H0 `6 n* M8 E
- K: ~; _3 j* }3 n) Q7 M' t for(long i=0; i<nCount; i++)
5 n" A( G& Y- }) F {
, @% h, z6 w+ J3 q: g! ?. V1 ] T CComPtr< IDispatch > spDisp;' `; X9 m4 T$ F5 u# Q2 `/ V
hr=spShellWin->Item(CComVariant( i ), &spDisp );
4 F4 j9 U8 I+ E* L3 E% } if ( FAILED( hr ) ) continue;
$ d2 C& K% q' P/ `3 N: h/ b9 h" T$ n. r# r
CComQIPtr< IWebBrowser2 > spBrowser = spDisp;3 h2 ?8 ^, D, m2 H6 ]7 j
if ( !spBrowser ) continue;
& G) U# O6 B( R( l5 Z7 r
/ t2 I2 D' W+ s3 y) i6 F spDisp.Release();
5 x% U8 M; q+ \$ k hr = spBrowser->get_Document( &spDisp );
$ E+ X* ~; p" V2 P6 B if ( FAILED ( hr ) ) continue;, t1 o2 t7 v3 }& w5 v5 m1 S
$ r* e7 U" k, O3 a
CComQIPtr< IHTMLDocument2 > spDoc = spDisp;
1 l1 x/ v% j7 x+ E0 U+ \& @0 I8 R if ( !spDoc ) continue;4 o9 s0 R/ Q' h" h
, o8 D: r p4 S // 程序运行到此,已经找到了 IHTMLDocument2 的接口指针
, u6 K6 G- x- c) z8 E }
3 D& y& J- H7 e" d/ s" I}
( D k/ ~5 h5 W- M" W! z
+ Q. m) O$ s$ d E+ h# } <6> IE 浏览器控件被一个进程包装在一个子窗口中。那么你首先要得到那个进程的顶层窗口句柄(使用 FindWindow() 函数,或其它任何可行的方法),然后枚举所有子窗口,通过判断窗口类名是否是“Internet Explorer_Server”,从而得到浏览器的窗口句柄,再向窗口发消息取得文档的接口指针。主要代码如下:
) J. J2 t z- `
8 J( v. p! O3 d' t
! z' \$ Z# ]7 e- Z/ O#include < atlbase.h >
* a/ M. ]! z t: e' \#include < mshtml.h >: I' x* W" n0 O6 k5 v# x' i1 M0 ^, H
#include < oleacc.h >
7 Z" N% f. l: q D0 D4 x, X#pragma comment ( lib, "oleacc" )
* W9 R( i, F, d# ~, g( i! i+ T; i9 N5 M
BOOL CALLBACK EnumChildProc(HWND hwnd,LPARAM lParam)( v, m5 y* Z& \
{
* O% P! v( f, Z6 K- T$ \$ { TCHAR szClassName[100];$ [7 T3 K2 r4 Q( Q9 z; b
: g1 @9 h/ v; i6 Q" n
::GetClassName( hwnd, &szClassName, sizeof(szClassName) );! o$ z0 b6 \# A1 e5 M, V! R
if ( _tcscmp( szClassName, _T("Internet Explorer_Server") ) == 0 )$ G- y: w! V# y# B" A# r8 B
{6 |, G* S7 H/ S
*(HWND*)lParam = hwnd; ~4 N! K7 U O0 `% ~
return FALSE; // 找到第一个 IE 控件的子窗口就停止8 `; [* u' ?+ p5 [2 |2 E
}
" I1 M5 H F; C) I' j' M7 M: h3 ^ else return TRUE; // 继续枚举子窗口
7 Z: w0 E( x; n7 a6 d1 [};
7 @" u. h0 m0 J/ ~, r5 v( Y5 W$ i0 [; ~, |: e! u+ X3 k1 T/ T
void FindFromHwnd(HWND hWnd) ( w6 L4 Z6 p1 U& R9 J
{9 d2 t* O5 u( b" T, s) Q1 W
HWND hWndChild=NULL;
6 a& |' U+ @+ n. i& a ::EnumChildWindows( hWnd, EnumChildProc, (LPARAM)&hWndChild );
7 Z3 z8 s( y* n if(NULL == hWndChild) return;
+ ?) {+ E! b$ L3 f4 V$ x5 U* O/ [$ e3 u7 z, D
UINT nMsg = ::RegisterWindowMessage( _T("WM_HTML_GETOBJECT") );
. T6 j5 j' i% p$ F% B LRESULT lRes;; K1 y# l; J* V/ d) E2 Z
::SendMessageTimeout( hWndChild, nMsg, 0L, 0L, SMTO_ABORTIFHUNG, 1000, (DWORD*) &lRes );
) X2 \9 T/ L0 `) F
2 S( l0 J! k# W2 {: t( R2 f CComPtr < IHTMLDocument2 > spDoc;
( h# P& g$ @ {: Z; p HRESULT hr = ::ObjectFromLresult ( lRes, IID_IHTMLDocument2, 0 , (LPVOID *) &spDoc );6 z# y/ @1 ?- L4 S2 _. s7 n
if ( FAILED ( hr ) ) return;
$ }. B, b. Z2 D* x
+ y0 l7 ?8 D/ V! v+ I) p( H // 程序运行到此,已经找到了 IHTMLDocument2 的接口指针' _; _7 I: v. {) A
} |
|