找回密码
 注册
搜索
查看: 4348|回复: 0

[收藏]千方百计得到IHTMLDocument2的接口指针

[复制链接]
发表于 2005-4-20 17:46:13 | 显示全部楼层 |阅读模式
  根据IE浏览器的运行方式,有多种不同的方式可以获取文档指针。
' _( I8 V! E" V8 y  A7 u+ c# r$ G7 E
  <1> 如果你在程序中使用MFC的 CHtmlView 视来浏览网页。+ [! j& D! ~: D% f; l. O+ m$ x; Z
       取得文档的方法最简单,调用 CHtmlView::GetHtmlDocument() 函数。
' X) t! ~8 m3 k5 j+ R5 S: H# R1 j  <2> 如果你的程序中使用了“Web 浏览器” 的ActiveX 控件。
& A8 [  r- I1 S' @4 ~' _1 E        取得文档的方法也比较简单,调用 CWebBrowser2::GetDocument() 函数。
8 j" n* u) q! y6 Q& @& c0 j  <3> 如果你的程序是用 ATL 写的 ActiveX 控件。( f# e: g4 f1 V& j  Q, N# H
       那么需要调用 IOleClientSite::GetContainer 得到 IOleContainer 接口,然后就可以通过 QueryInterface() 查询得到 IHTMLDocument2 的接口。主要代码如下:
! l- {1 X3 ?8 K+ N* j, @9 B
# ?) i; J4 @( L$ Y9 N9 nCComPtr < IOleContainer > spContainer;
7 A( \  ^. h8 a/ d5 m! b& vm_spClientSite->GetContainer( &spContainer );: Z8 H/ p- I: K5 u  N- b9 n, ~
CComQIPtr < IHTMLDocument2 > spDoc = spContainer;
/ i$ Z) C4 S" i$ y6 ]: xif ( spDoc )
% w( p1 w% c( Z3 b5 L{
' B. W8 |" {1 C- i; I' z' j4 f     // 已经得到了 IHTMLDocument2 的接口指针
- v4 |1 i' B1 N}: ~" q/ s& L( V; p. D2 P: u

& D0 H8 A" F3 m5 j' y: s  <4> 如果你的程序是用 MFC 写的 ActiveX 控件。
+ L! ?% r1 ~3 }9 ]/ q1 D  I0 Q        那么需要调用 COleControl::GetClientSite() 得到 IOleContainer 接口,然后的操作和<3>是一致的了。: N( f: s1 f4 }
  <5> IE 浏览器作为独立的进程正在运行。
- e" B6 p# t+ C3 R* P$ k" g! e        每个运行的浏览器(IE 和 资源浏览器)都会在 ShellWindows 中进行登记,因此我们要通过 IShellWindows 取得实例(示例程序中使用的就是这个方法)。主要代码如下:
; ^+ i% A, R; x% `0 X7 C+ E, l. t  `! l( _; @& i2 ~
#include < atlbase.h >
7 j$ M9 R. Q# a. l2 T* S& _* }1 [#include < mshtml.h >3 k% W, s/ Q4 S* h
, ?0 u" y; @- D% C. E- _, ]. V
void FindFromShell() & f( c1 T( j: z) E
{
  I# K6 V8 h7 u% b+ R   CComPtr< IShellWindows > spShellWin;
! V& A0 {, v/ W+ l- m' b/ ?  V& d/ ?   HRESULT hr = spShellWin.CoCreateInstance( CLSID_ShellWindows );- t7 [) B' n: G$ }  l3 G+ u, W* N2 o
  if ( FAILED( hr ) )    return;
" _% D4 }* h8 y' a) z! L
% r  L+ e1 O4 p1 J$ y$ X+ Q   long nCount=0;
  Z; S6 v8 A2 k. _8 ?9 T6 }% @   spShellWin->get_Count(&nCount);   // 取得浏览器实例个数, F$ ?  G/ ?! m, |0 _' d9 ^

; c, B( P% q9 l, e, I; ^. T5 i   for(long i=0; i<nCount; i++)
: J/ d# o" Z, r  Y. U4 i2 U6 B* J       {
  c4 T2 s" R2 E8 \/ w$ `' p' R                CComPtr< IDispatch > spDisp;* o+ M& ]) r9 J9 k+ R6 B
     hr=spShellWin->Item(CComVariant( i ), &spDisp );
% w; W* Y3 ]6 V7 k; _9 X0 W      if ( FAILED( hr ) )   continue;: q% r3 K3 K8 b; G  A4 v5 z7 l

8 o& @% k$ f4 b$ P      CComQIPtr< IWebBrowser2 > spBrowser = spDisp;
- |8 o& l+ [/ }( D8 S' P      if ( !spBrowser )     continue;
$ `3 T( ?2 M  j( H; l8 ^6 u" i8 }
" H" I4 W1 ?* M8 G. @) G; u      spDisp.Release();
5 l9 b# x( H6 E# q7 t# l  D0 U      hr = spBrowser->get_Document( &spDisp );* J8 N$ N2 A  [6 T* h( s2 O
     if ( FAILED ( hr ) )  continue;
% u7 z4 t0 \: ]# m- J- P' |
. _( D6 W1 J* Q+ n% ]& j      CComQIPtr< IHTMLDocument2 > spDoc = spDisp;0 O6 _. N% H. x, Z) {
     if ( !spDoc )         continue;. Q9 i3 V$ w; k% y! r0 u
1 F/ g' e8 g& s  @5 ^+ I. r- |" o
     // 程序运行到此,已经找到了 IHTMLDocument2 的接口指针
$ v. q  T, j0 D1 O) z; d   }6 A5 H$ b4 h- O, m: o
}
. o' p  v: \/ ^- \& U1 w; o4 j. @+ V3 ?- ~6 V  p
  <6> IE 浏览器控件被一个进程包装在一个子窗口中。那么你首先要得到那个进程的顶层窗口句柄(使用 FindWindow() 函数,或其它任何可行的方法),然后枚举所有子窗口,通过判断窗口类名是否是“Internet Explorer_Server”,从而得到浏览器的窗口句柄,再向窗口发消息取得文档的接口指针。主要代码如下: $ ?( W& Q- ?2 @" E1 r

7 m. B$ Z' A8 D  L- `, D8 D$ s( q: H8 ^
#include < atlbase.h >
% d* p+ M% J6 ^0 m#include < mshtml.h >
! V6 T0 x' t0 S% B8 @. f' A#include < oleacc.h >
( v- p* S+ V6 i7 U0 }4 {5 D3 b#pragma comment ( lib, "oleacc" )
: ^4 V3 W. }, f; I* G& v
/ ?1 c: q" P  h0 EBOOL CALLBACK EnumChildProc(HWND hwnd,LPARAM lParam)
! w  s  I8 \$ q9 Q{
  l4 N) r+ j4 ]$ k1 R   TCHAR szClassName[100];0 {- D. |6 c' x

; X/ h" I1 J5 {+ k( h& ^   ::GetClassName( hwnd,  &szClassName,  sizeof(szClassName) );" U, R+ h7 @. Z4 x- {2 i
  if ( _tcscmp( szClassName,  _T("Internet Explorer_Server") ) == 0 )
6 {& r) ]) |+ U3 S2 m% ~! w   {
5 N  w! g+ z8 S9 j, K      *(HWND*)lParam = hwnd;
) Y' Q: z8 N, l0 A* O3 d2 H$ R      return FALSE;      // 找到第一个 IE 控件的子窗口就停止) K+ ]: C% H% [8 \
  }0 O) @7 a# I, ?6 b
  else   return TRUE;      // 继续枚举子窗口6 \6 [% K+ P3 O+ I  h8 N/ K5 j8 G
};
: j) d( {7 b; e9 r* k9 X; I
) g7 W9 p  b! @void FindFromHwnd(HWND hWnd)
0 r: l- Q# E# a* ]5 {7 U{; }$ [6 U" n  W
  HWND hWndChild=NULL;1 N' p6 \+ r- W0 S/ s2 G/ n2 ^
  ::EnumChildWindows( hWnd, EnumChildProc, (LPARAM)&hWndChild );
% E1 _; A+ G7 z   if(NULL == hWndChild)   return;- M% i+ ^* d7 O
0 j  `& @' }% V9 b
  UINT nMsg = ::RegisterWindowMessage( _T("WM_HTML_GETOBJECT") );% h- H7 V' p$ J' d
  LRESULT lRes;! f" z' G  z$ [+ z) o
  ::SendMessageTimeout( hWndChild, nMsg, 0L, 0L, SMTO_ABORTIFHUNG, 1000, (DWORD*) &lRes );
5 e; D/ |7 R& i% c  a0 {
- B' t5 E! B/ A9 k) u: R   CComPtr < IHTMLDocument2 > spDoc;7 M& x: F: X+ u5 P) \& ?# w. G
  HRESULT hr = ::ObjectFromLresult ( lRes, IID_IHTMLDocument2, 0 , (LPVOID *) &spDoc );
9 b8 a) k+ T7 {* |0 d   if ( FAILED ( hr ) )   return;
7 ^  G4 ~% K# o+ }: ^  ]7 Q( q/ D: R5 y) H" j
  // 程序运行到此,已经找到了 IHTMLDocument2 的接口指针
1 }$ z$ o# u2 h8 G  \, [' d; E}
您需要登录后才可以回帖 登录 | 注册

本版积分规则

Archiver|手机版|小黑屋|宁德市腾云网络科技有限公司 ( 闽ICP备2022007940号-5|闽公网安备 35092202000206号 )

GMT+8, 2025-6-19 11:37 , Processed in 0.014975 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表