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

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

[复制链接]
发表于 2005-4-20 17:46:13 | 显示全部楼层 |阅读模式
  根据IE浏览器的运行方式,有多种不同的方式可以获取文档指针。
' u8 B/ ~4 A* r3 t9 F$ |2 {" o5 |1 |7 [7 r' V4 T' }
  <1> 如果你在程序中使用MFC的 CHtmlView 视来浏览网页。
3 e  v. [( }' Z) w" Q! U# s        取得文档的方法最简单,调用 CHtmlView::GetHtmlDocument() 函数。
$ f. F6 h% @% H. Z5 V. ^  <2> 如果你的程序中使用了“Web 浏览器” 的ActiveX 控件。1 Z  ]$ R. z6 d) D4 E
       取得文档的方法也比较简单,调用 CWebBrowser2::GetDocument() 函数。
7 D6 h2 _$ {) G9 K. @! E* |  <3> 如果你的程序是用 ATL 写的 ActiveX 控件。! |: ^! ?8 ]; o0 v/ K$ l
       那么需要调用 IOleClientSite::GetContainer 得到 IOleContainer 接口,然后就可以通过 QueryInterface() 查询得到 IHTMLDocument2 的接口。主要代码如下:
- L/ a; Q. L2 H- D9 H/ q% t( R. T8 }; v" g/ W) n
CComPtr < IOleContainer > spContainer;
- ^: ~, G4 S% I8 E) E! Am_spClientSite->GetContainer( &spContainer );5 d6 D7 S2 c2 Z8 h; C
CComQIPtr < IHTMLDocument2 > spDoc = spContainer;) r% ?# c2 p  i
if ( spDoc )* O; N) V9 w5 F( f! C
{
2 ~$ E7 @& ^; \! z     // 已经得到了 IHTMLDocument2 的接口指针
& R$ [" c. E! x& j}
4 q9 h! s9 u+ D9 E+ }' C$ X9 C9 k! Q
  <4> 如果你的程序是用 MFC 写的 ActiveX 控件。
* N  E; C) F2 |: e  i/ Y        那么需要调用 COleControl::GetClientSite() 得到 IOleContainer 接口,然后的操作和<3>是一致的了。
5 s: u! s; V) k' M. n  <5> IE 浏览器作为独立的进程正在运行。
+ r4 l# R& d4 Y& G. O" K        每个运行的浏览器(IE 和 资源浏览器)都会在 ShellWindows 中进行登记,因此我们要通过 IShellWindows 取得实例(示例程序中使用的就是这个方法)。主要代码如下:( |8 I0 W+ k( Y/ u4 r  C
! K, g: c' F1 B5 h- R4 J. P
#include < atlbase.h >
: f  R: n1 ~. M* G( _1 j0 v( Q. @6 r#include < mshtml.h >1 _& d' j) P* @
; F. O2 S" r7 l, D6 `4 X
void FindFromShell() 5 {+ w* V. }- L8 c8 o
{
& D! b( j/ V9 _  h2 R: q5 q4 z   CComPtr< IShellWindows > spShellWin;7 T: W( k2 o  V3 V" `1 U+ V
  HRESULT hr = spShellWin.CoCreateInstance( CLSID_ShellWindows );  U8 _. S( _$ ]7 T1 A
  if ( FAILED( hr ) )    return;
# `. l  t5 {9 S: ^! O' s, b7 C7 Y) B8 }
  long nCount=0;
5 M4 ~: g3 \: x   spShellWin->get_Count(&nCount);   // 取得浏览器实例个数
2 o$ Q0 O0 M1 @3 A  V
) G* ]% n" z) y  ]4 F   for(long i=0; i<nCount; i++)
2 s& u2 ^3 I. q4 m: V2 i9 c       {: e& i' I7 r8 A$ N& q6 c. B
               CComPtr< IDispatch > spDisp;
+ y( F0 a. Z9 {7 n# L      hr=spShellWin->Item(CComVariant( i ), &spDisp );
3 Z; h/ s" K! p      if ( FAILED( hr ) )   continue;
" j- ?6 R" v. z7 ]8 |- J, N$ O" v" T) G- X* c
     CComQIPtr< IWebBrowser2 > spBrowser = spDisp;* d/ l# u7 K0 n4 H" Q
     if ( !spBrowser )     continue;
, d, H8 c, R! ]: s% Q6 w, y
9 C6 V# F3 A' E. Y      spDisp.Release();# T5 ~8 n* a; s" E4 `  j. h
     hr = spBrowser->get_Document( &spDisp );. V8 z. T- h& }( j" K; \
     if ( FAILED ( hr ) )  continue;- T: L7 s3 ~' v3 `$ D6 E) y

  i" Y5 R# f- Q0 H2 H& h7 w0 u      CComQIPtr< IHTMLDocument2 > spDoc = spDisp;
6 P# A- e$ p: w0 j( k- n8 s      if ( !spDoc )         continue;
% K0 J! ?  w1 g) ~' k$ w3 |
  `: m4 o4 z& `  y0 K. L9 w. s. w      // 程序运行到此,已经找到了 IHTMLDocument2 的接口指针
& y& L; I) X' s6 z9 M" A   }
  K; `0 c8 N; C6 s) n}7 x; |8 P3 Z8 r, Z, p
4 l% V: Y, g6 m4 O; r7 H* R5 `
  <6> IE 浏览器控件被一个进程包装在一个子窗口中。那么你首先要得到那个进程的顶层窗口句柄(使用 FindWindow() 函数,或其它任何可行的方法),然后枚举所有子窗口,通过判断窗口类名是否是“Internet Explorer_Server”,从而得到浏览器的窗口句柄,再向窗口发消息取得文档的接口指针。主要代码如下: + g( ]6 t  Q& {& ]0 o+ [

" Y- |+ l" u# k' B
2 g5 A, T; X5 j! H+ J#include < atlbase.h >
2 g2 p9 u8 H1 Q( q' V# J#include < mshtml.h >
! G) `, d4 @* T; K8 P. p4 _- u#include < oleacc.h >! G: t1 }6 A. w0 K  ?+ g0 t0 O
#pragma comment ( lib, "oleacc" )3 s# a0 a: S; ]  I: f: E9 y( @

( U$ M; m" M+ E" Q; v6 yBOOL CALLBACK EnumChildProc(HWND hwnd,LPARAM lParam)  ~# v* r& W: P( ]; H' c5 d
{9 ~" C' L6 [/ A! ]
  TCHAR szClassName[100];* e% N0 U( Z4 f3 e; @, n6 V3 X7 W

# B+ F- Y7 G, w6 o6 x1 M3 h& i- g   ::GetClassName( hwnd,  &szClassName,  sizeof(szClassName) );3 Q' J4 `/ G1 }& p$ [; c  x
  if ( _tcscmp( szClassName,  _T("Internet Explorer_Server") ) == 0 )4 K& o3 @3 z* z" T
  {% b3 E' h$ U/ ]4 x- Y, r: D
     *(HWND*)lParam = hwnd;0 l0 \( u1 H6 ~9 t/ t# y
     return FALSE;      // 找到第一个 IE 控件的子窗口就停止
  i' i  y$ M0 y   }* I. H0 N; ?; \0 u' v2 X5 X
  else   return TRUE;      // 继续枚举子窗口0 I8 J, Y+ e; i3 F6 k& G4 V3 W2 N
};
5 a3 C- a, b1 b& n! F7 R( q4 d/ K
void FindFromHwnd(HWND hWnd)
1 i- v9 M/ \& U; U" V, m{( z# a1 j# _1 R6 ^1 F$ M" `
  HWND hWndChild=NULL;+ D) a0 ]% M4 p3 L* X$ H. }
  ::EnumChildWindows( hWnd, EnumChildProc, (LPARAM)&hWndChild );* [) n" Y# Q* n/ d
  if(NULL == hWndChild)   return;5 a" O+ H3 [2 B& A
2 L6 }) e0 }: J
  UINT nMsg = ::RegisterWindowMessage( _T("WM_HTML_GETOBJECT") );
: q( ?- v9 _  m5 h   LRESULT lRes;8 g. G2 O# W% {+ c0 M
  ::SendMessageTimeout( hWndChild, nMsg, 0L, 0L, SMTO_ABORTIFHUNG, 1000, (DWORD*) &lRes );
3 Q- w  l/ y3 t- \" \1 W+ g
% X9 Y, j% _# S3 a/ d% }   CComPtr < IHTMLDocument2 > spDoc;
( i9 N0 t4 }; i5 H   HRESULT hr = ::ObjectFromLresult ( lRes, IID_IHTMLDocument2, 0 , (LPVOID *) &spDoc );, g1 z4 S# d- A
  if ( FAILED ( hr ) )   return;
4 ~/ `0 A) p% ~# a4 u/ a! A
7 w- F* F0 m- S( u' Z6 u, o: G   // 程序运行到此,已经找到了 IHTMLDocument2 的接口指针7 |% W% }$ p: F8 ~5 J
}
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2025-8-9 07:04 , Processed in 0.034429 second(s), 14 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

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