|
|
根据IE浏览器的运行方式,有多种不同的方式可以获取文档指针。
6 D" b1 j/ T/ X" r+ E
' M+ D) Q/ H8 n& O8 j) t <1> 如果你在程序中使用MFC的 CHtmlView 视来浏览网页。
! `+ M) \! I* S: |; `9 m/ `$ D 取得文档的方法最简单,调用 CHtmlView::GetHtmlDocument() 函数。+ ^. \; w+ U0 r: }( Y
<2> 如果你的程序中使用了“Web 浏览器” 的ActiveX 控件。; K5 w* u! R# n, ]
取得文档的方法也比较简单,调用 CWebBrowser2::GetDocument() 函数。
2 t* w$ c M8 X- \# Q4 l) E <3> 如果你的程序是用 ATL 写的 ActiveX 控件。/ J9 h: h' L8 ^
那么需要调用 IOleClientSite::GetContainer 得到 IOleContainer 接口,然后就可以通过 QueryInterface() 查询得到 IHTMLDocument2 的接口。主要代码如下:
9 {6 G3 O! h8 H
9 F; Z1 V1 W: QCComPtr < IOleContainer > spContainer;
6 p+ _4 ?6 Q8 g% \, \# `' Rm_spClientSite->GetContainer( &spContainer );% c/ \( F1 M' H; T: S" C! |: {
CComQIPtr < IHTMLDocument2 > spDoc = spContainer;2 M. `9 L+ V0 t, P* W! w* N$ B
if ( spDoc )/ f& Y6 n: D4 L5 M) }
{
( Q7 ^6 E7 H/ z+ A$ s# n! q // 已经得到了 IHTMLDocument2 的接口指针
/ T* e N9 I' K$ \+ y( z. z}
3 A; }2 f/ ^5 z2 [) h5 \; K$ w! E4 N6 y- j
<4> 如果你的程序是用 MFC 写的 ActiveX 控件。
$ P+ W4 {: \3 i4 [- \ 那么需要调用 COleControl::GetClientSite() 得到 IOleContainer 接口,然后的操作和<3>是一致的了。
% V: V5 H, w! `% o <5> IE 浏览器作为独立的进程正在运行。
2 L9 n4 Q% B `4 } 每个运行的浏览器(IE 和 资源浏览器)都会在 ShellWindows 中进行登记,因此我们要通过 IShellWindows 取得实例(示例程序中使用的就是这个方法)。主要代码如下:7 x# z4 {: x( `+ f, O; |
$ u, [9 i! Z/ F; c( ~* G' Q0 R8 u3 M#include < atlbase.h >
# M d8 b( @, A% e. p3 o6 T$ ]#include < mshtml.h >' w2 F0 J+ ?; h; K% s6 \
: q/ c% a0 o% v; Mvoid FindFromShell()
- Q: P0 j- T: U, k{
( b F. I, K& i+ F; L CComPtr< IShellWindows > spShellWin;
! I+ y7 B3 r3 j/ f0 o3 z7 Z" F HRESULT hr = spShellWin.CoCreateInstance( CLSID_ShellWindows );4 G, f7 I. q/ l1 j( A
if ( FAILED( hr ) ) return;3 j- _. j/ v0 w. p% X
, L$ \6 Z2 y; p8 X; I' V/ d long nCount=0;
5 a) J& M. t9 U; D% b' V/ } spShellWin->get_Count(&nCount); // 取得浏览器实例个数1 n+ \2 F$ Q% ]+ N1 I' A
/ [+ L ~' }' @
for(long i=0; i<nCount; i++)6 U, D, }, @; k8 O4 E! j# l
{& E$ \/ D5 P* O7 ?) g c
CComPtr< IDispatch > spDisp;
6 c3 P- v# [! C; A: J hr=spShellWin->Item(CComVariant( i ), &spDisp );. X. q! c( H) j* g$ y3 P8 c
if ( FAILED( hr ) ) continue;
C2 H7 _8 g# U2 E! _% a% _
* r+ w4 q0 N8 Y$ Q N% o' C CComQIPtr< IWebBrowser2 > spBrowser = spDisp;
5 o Y% Z* Q* | if ( !spBrowser ) continue;
4 j' _) F! o, R( w9 }
" m/ f7 W2 `' D0 f; u1 R N spDisp.Release();+ x# h; q/ k# `. |4 Q
hr = spBrowser->get_Document( &spDisp );& Q- b4 {& ]* Z. H
if ( FAILED ( hr ) ) continue; s+ \6 L+ ^3 K. e: _
8 Q! b# O; a2 I3 R CComQIPtr< IHTMLDocument2 > spDoc = spDisp;
9 u) e B" g2 \4 L0 L2 j if ( !spDoc ) continue;
) B$ u) v6 K: W; B
. c' S$ t: U# R2 P' U2 _: d // 程序运行到此,已经找到了 IHTMLDocument2 的接口指针 [! @4 v/ Q8 m7 L- f# @9 S
}0 S7 `/ d7 n( d% p. k* y0 @7 i6 l
}' b' }$ y$ H J8 M; m. a: B3 ^: G
) q% S! m2 x7 v- u- i
<6> IE 浏览器控件被一个进程包装在一个子窗口中。那么你首先要得到那个进程的顶层窗口句柄(使用 FindWindow() 函数,或其它任何可行的方法),然后枚举所有子窗口,通过判断窗口类名是否是“Internet Explorer_Server”,从而得到浏览器的窗口句柄,再向窗口发消息取得文档的接口指针。主要代码如下:
1 x' i- }5 O0 `# P2 @6 \# u" L% A1 N
8 I8 }7 ]/ Y! Q- @
#include < atlbase.h >
+ f% i4 I B) y& T#include < mshtml.h >9 V0 j" @, i8 ^2 k0 J- i
#include < oleacc.h >1 D+ r8 D J$ J( o4 x& A9 t
#pragma comment ( lib, "oleacc" )3 q9 c' S" R0 q. o
( q5 |" G9 D5 sBOOL CALLBACK EnumChildProc(HWND hwnd,LPARAM lParam)
0 v5 a F( N1 H- |+ e{
i- {! k2 d! ?' @ TCHAR szClassName[100];
4 B. f" `- P+ _! W6 j* |$ L
# h" B, D* O, M4 b ::GetClassName( hwnd, &szClassName, sizeof(szClassName) );, J; q- Q$ W& h6 q
if ( _tcscmp( szClassName, _T("Internet Explorer_Server") ) == 0 )- I" X c, w' U. `1 s( P' ]3 D
{
% k# {% Y1 L* _5 f *(HWND*)lParam = hwnd;6 U: q5 E- F( O. X/ P) ]* ]
return FALSE; // 找到第一个 IE 控件的子窗口就停止6 U9 i( s6 A" Q( r& h. u, M
}* S) W* o* H; y' M! g1 h1 d5 ^
else return TRUE; // 继续枚举子窗口
: R, \+ d" I: I j};
: h, j3 B- V$ [! m" Y
2 z6 B, K4 i( Q; P4 G% }void FindFromHwnd(HWND hWnd) & D, u* d% f \# w- k/ K
{
j1 f! h, ]# M+ V- @ HWND hWndChild=NULL;
( K% Y, G1 T9 J* X1 B0 D8 ~0 B ::EnumChildWindows( hWnd, EnumChildProc, (LPARAM)&hWndChild );
3 _$ n3 s& [1 [' `/ r. _9 Z* ]$ b if(NULL == hWndChild) return;
7 @- N* R5 t/ g7 D1 y7 \2 i" M/ [$ c
UINT nMsg = ::RegisterWindowMessage( _T("WM_HTML_GETOBJECT") );
. w( D+ _4 Q/ V LRESULT lRes;
) H1 b7 o$ G% ^ ::SendMessageTimeout( hWndChild, nMsg, 0L, 0L, SMTO_ABORTIFHUNG, 1000, (DWORD*) &lRes );6 F% i4 j0 w! R% f
8 g0 x2 _) G! @ q CComPtr < IHTMLDocument2 > spDoc;3 P* \ T! W+ O `1 k: c* j
HRESULT hr = ::ObjectFromLresult ( lRes, IID_IHTMLDocument2, 0 , (LPVOID *) &spDoc );( ^8 x, Y; _0 n" \
if ( FAILED ( hr ) ) return;0 u M& n! K* T: Y
2 {9 M$ C! [! b( F% ^3 S/ x // 程序运行到此,已经找到了 IHTMLDocument2 的接口指针
1 ]" C6 h) z& _5 m' S0 C} |
|