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

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

[复制链接]
发表于 2005-4-20 17:46:13 | 显示全部楼层 |阅读模式
  根据IE浏览器的运行方式,有多种不同的方式可以获取文档指针。0 z# R' W/ Q' k
0 j3 j- \' \' R1 ~6 ?# s/ x' d
  <1> 如果你在程序中使用MFC的 CHtmlView 视来浏览网页。
2 k) t$ n, X$ F& @6 N( X        取得文档的方法最简单,调用 CHtmlView::GetHtmlDocument() 函数。2 l4 p* Y, B  ?3 a0 R, f
  <2> 如果你的程序中使用了“Web 浏览器” 的ActiveX 控件。! C9 b7 b3 C6 k$ g
       取得文档的方法也比较简单,调用 CWebBrowser2::GetDocument() 函数。" e% e* `' j; C% }2 E, i
  <3> 如果你的程序是用 ATL 写的 ActiveX 控件。  x6 a, s5 ^; z8 o" q9 i; T2 L+ Q5 I% V
       那么需要调用 IOleClientSite::GetContainer 得到 IOleContainer 接口,然后就可以通过 QueryInterface() 查询得到 IHTMLDocument2 的接口。主要代码如下:
+ e6 {' o$ Q9 I1 p+ Z- ^
5 E4 Y5 e# l- s( Y! X5 ?0 N5 v: mCComPtr < IOleContainer > spContainer;2 p: H* s  _( l* a4 H! @. w
m_spClientSite->GetContainer( &spContainer );
; B; A1 _! B3 F: S3 jCComQIPtr < IHTMLDocument2 > spDoc = spContainer;% o" E8 V0 ~' O* K
if ( spDoc )% u7 J. ?$ t9 c
{
* s: y: R3 z/ n$ M% c* {     // 已经得到了 IHTMLDocument2 的接口指针" b/ V  U2 ]" G! k
}
8 f1 a& Z! j: w/ Y: s% W5 D6 D( B0 K- Z6 L  N: V+ ~
  <4> 如果你的程序是用 MFC 写的 ActiveX 控件。3 q7 I3 T' I# s* _6 `" y9 E. R
       那么需要调用 COleControl::GetClientSite() 得到 IOleContainer 接口,然后的操作和<3>是一致的了。* T* X. j# ^$ B6 l5 R
  <5> IE 浏览器作为独立的进程正在运行。
: \3 ^! e1 L% T/ P& v, B4 G5 @        每个运行的浏览器(IE 和 资源浏览器)都会在 ShellWindows 中进行登记,因此我们要通过 IShellWindows 取得实例(示例程序中使用的就是这个方法)。主要代码如下:+ K, Z# U( a, X  W' ~! Z

) Z' r6 u, D% j7 D9 U2 E0 {+ g& t#include < atlbase.h >: C9 _- b! W* M& l# C: |' B5 F
#include < mshtml.h >0 {5 }. y# v% F  K$ X& ^) _
# @7 `# a* c( K5 y$ T2 ~. g+ T
void FindFromShell() ( G" i/ y. x% Y$ q' E/ @
{- E6 _% {1 g; l5 R7 x# D; l. M
  CComPtr< IShellWindows > spShellWin;
7 w6 Q7 d5 P: r" p2 n, j2 ?, q  |( r' X# ]  Q   HRESULT hr = spShellWin.CoCreateInstance( CLSID_ShellWindows );
( r& F: t' b; s+ \5 F# f* ~   if ( FAILED( hr ) )    return;
1 T0 h0 D( C, X% \0 j: H* B5 f: M7 E5 @' B: b  Q% R% K4 t
  long nCount=0;
+ `) i4 W/ \. U. a) a/ G   spShellWin->get_Count(&nCount);   // 取得浏览器实例个数8 D. ?( S+ n4 m5 M# f  |' m
  _5 R  H$ a. Y" e' d2 S- n5 H0 B# f
  for(long i=0; i<nCount; i++)
! }/ ?6 U5 h5 ]( K# j       {
4 b  O, ~& {8 H9 F2 c( s9 z! S# k                CComPtr< IDispatch > spDisp;) {8 E' _& G1 G" D' [9 R" f0 H0 F
     hr=spShellWin->Item(CComVariant( i ), &spDisp );% M0 r+ \: s: B: ?& n. x' q8 ~
     if ( FAILED( hr ) )   continue;
% u9 p8 B5 {$ c; Q! Q# u
# V' c2 V0 i' u) |+ T      CComQIPtr< IWebBrowser2 > spBrowser = spDisp;
1 t1 f: o6 m1 d* P8 f6 t      if ( !spBrowser )     continue;
, }8 }7 w8 R: A/ ^
* Q, U8 k+ ?6 j0 K. m' _$ K5 Q      spDisp.Release();, c3 X5 |7 l  W2 u- i  C& N
     hr = spBrowser->get_Document( &spDisp );
: f1 U& A" k6 |. P( g6 p      if ( FAILED ( hr ) )  continue;
8 @" g  f" W# G1 ?: U/ w, i. s
2 ]0 Z; ]0 _9 Y5 i; r1 P' g      CComQIPtr< IHTMLDocument2 > spDoc = spDisp;
4 ?; y$ M1 c/ [/ c      if ( !spDoc )         continue;: M1 D/ F6 O+ k1 ?" Y: s

5 v( n4 I& _( n" R8 _      // 程序运行到此,已经找到了 IHTMLDocument2 的接口指针" g) v; u# A! }9 a& Q1 l- C
  }
+ g; ~. L# o3 C: B7 \$ s}
6 X# W' }. C  D
2 V& r6 [2 K/ {4 X; V& l( `+ S- ~; R  <6> IE 浏览器控件被一个进程包装在一个子窗口中。那么你首先要得到那个进程的顶层窗口句柄(使用 FindWindow() 函数,或其它任何可行的方法),然后枚举所有子窗口,通过判断窗口类名是否是“Internet Explorer_Server”,从而得到浏览器的窗口句柄,再向窗口发消息取得文档的接口指针。主要代码如下:
; e1 D4 \& c/ W3 }% P$ r" v
3 n- ~* X1 |% d5 L4 H9 t& s0 y4 w5 d7 i# |/ F$ V* r  `
#include < atlbase.h >- r  e6 t4 V; Q% A  A& T
#include < mshtml.h >
8 h( B8 j) t5 ~; Z( ^* H, ]0 |4 I; [#include < oleacc.h >! y7 O( G: R8 E' k# q
#pragma comment ( lib, "oleacc" )5 {3 B: N0 m* D' k, ?
1 ^9 G. W4 l0 ?4 A( _# `9 D
BOOL CALLBACK EnumChildProc(HWND hwnd,LPARAM lParam)
5 s1 ?+ C" p) V0 `/ M9 R{
, e1 C. T$ i& f. b2 J   TCHAR szClassName[100];. e1 T6 K, F) ?% T+ m0 H
0 k- ^2 R9 Z+ e1 ]
  ::GetClassName( hwnd,  &szClassName,  sizeof(szClassName) );2 g! g- a2 L5 Q! l  y  c3 R7 S3 ^
  if ( _tcscmp( szClassName,  _T("Internet Explorer_Server") ) == 0 )( x' k- d  I+ O
  {
9 T9 B- w6 }3 o$ e; ]      *(HWND*)lParam = hwnd;8 m/ l% @4 d1 p) d: ~" h5 v
     return FALSE;      // 找到第一个 IE 控件的子窗口就停止2 ]1 x0 j- ~8 p8 d
  }
( d! i+ @3 x( ~* k2 |" Y# X) O. Q   else   return TRUE;      // 继续枚举子窗口
  T+ y9 s& ~0 _7 t+ N};* |: h" L/ u' Y+ _7 r+ }( q/ Z& x

. Q3 x4 ?$ _. L0 Tvoid FindFromHwnd(HWND hWnd)
3 t3 y3 e8 z/ z0 g. V! ~% R{1 E2 t' u4 `8 n& b  ^, X  m8 ~! I
  HWND hWndChild=NULL;) A: q8 U: s' _) E7 Y
  ::EnumChildWindows( hWnd, EnumChildProc, (LPARAM)&hWndChild );
6 r( N# g* [1 j/ v' ~' ]   if(NULL == hWndChild)   return;$ d- T1 J# v( k& O0 U2 s- i9 ~

: G) w1 j$ K! G9 i+ i! t   UINT nMsg = ::RegisterWindowMessage( _T("WM_HTML_GETOBJECT") );
4 Z+ M" w5 X* z& J7 T   LRESULT lRes;
6 K1 j0 A" B; ]' b   ::SendMessageTimeout( hWndChild, nMsg, 0L, 0L, SMTO_ABORTIFHUNG, 1000, (DWORD*) &lRes );  Y4 e3 }$ k8 [/ t9 |+ ?/ N+ n
8 \- B; \: r: y4 @
  CComPtr < IHTMLDocument2 > spDoc;
0 r4 T! y' _) a2 `   HRESULT hr = ::ObjectFromLresult ( lRes, IID_IHTMLDocument2, 0 , (LPVOID *) &spDoc );
# t) E) e; @+ ]' {: ~: \   if ( FAILED ( hr ) )   return;
! f. ~, U2 {8 w- x, j5 [* {7 n$ q' H2 Z% Z; ~# V
  // 程序运行到此,已经找到了 IHTMLDocument2 的接口指针
! e; f. `' r4 f* X( B+ _- R  |! m1 [1 n}
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2026-5-4 16:50 , Processed in 0.019859 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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