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

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

[复制链接]
发表于 2005-4-20 17:46:13 | 显示全部楼层 |阅读模式
  根据IE浏览器的运行方式,有多种不同的方式可以获取文档指针。" g+ g# Q; j( e) w8 b: h6 c
. G( {" `3 w' V
  <1> 如果你在程序中使用MFC的 CHtmlView 视来浏览网页。' J9 r6 S9 ~7 j! X
       取得文档的方法最简单,调用 CHtmlView::GetHtmlDocument() 函数。% G# M& g8 y  z3 m6 u2 R
  <2> 如果你的程序中使用了“Web 浏览器” 的ActiveX 控件。
0 z% [& i; E7 ~+ u! g        取得文档的方法也比较简单,调用 CWebBrowser2::GetDocument() 函数。: E( ]- ~! a% q; C" z
  <3> 如果你的程序是用 ATL 写的 ActiveX 控件。$ _+ K% u) S  G* s( a
       那么需要调用 IOleClientSite::GetContainer 得到 IOleContainer 接口,然后就可以通过 QueryInterface() 查询得到 IHTMLDocument2 的接口。主要代码如下:
: o! i4 G- o$ f
5 y* d/ e/ W, L. OCComPtr < IOleContainer > spContainer;
9 x6 m. ]5 p9 ^( A2 R0 Rm_spClientSite->GetContainer( &spContainer );: N5 E" K2 a% ~. b) d8 W
CComQIPtr < IHTMLDocument2 > spDoc = spContainer;2 b! Z- b$ @: [! R" |# n
if ( spDoc )# F& A! V+ K1 W6 R
{3 K& F# Q* s( k" b
    // 已经得到了 IHTMLDocument2 的接口指针( l( |$ E& s4 k) N0 d7 j$ _8 Q
}
  {/ I) j" C0 B# e# ^& J
: k" |6 K* L' r7 c. s  <4> 如果你的程序是用 MFC 写的 ActiveX 控件。
/ _: g& \4 U' v6 Z% f' E! X        那么需要调用 COleControl::GetClientSite() 得到 IOleContainer 接口,然后的操作和<3>是一致的了。
/ X8 r% K  H; a& B0 B" o" ^  <5> IE 浏览器作为独立的进程正在运行。
9 W8 }( x+ ~6 \  j! I* s: i        每个运行的浏览器(IE 和 资源浏览器)都会在 ShellWindows 中进行登记,因此我们要通过 IShellWindows 取得实例(示例程序中使用的就是这个方法)。主要代码如下:
- m0 J( T! B0 v% o4 s; g
* E9 \4 V- V# J, p3 G" N/ Q#include < atlbase.h >
0 H$ T3 C# d4 q" m* J% W#include < mshtml.h >
" E1 \! l9 X2 k# R
& [4 Q8 ~( u- z4 t7 `' d; ]% E6 Mvoid FindFromShell() - r  s, i& P0 t* @
{
6 W( c: ]2 |7 a0 x) b8 ?# F   CComPtr< IShellWindows > spShellWin;
. k) r. j% l7 \0 c6 h   HRESULT hr = spShellWin.CoCreateInstance( CLSID_ShellWindows );
" U  `, p2 u) P9 s$ Y# |$ C; T3 u   if ( FAILED( hr ) )    return;
+ I: h9 h4 l0 {- o  P' Z( `9 {+ r/ n  C' ?& d/ ^8 J7 g
  long nCount=0;. k& I! y- G8 W: Y6 ?
  spShellWin->get_Count(&nCount);   // 取得浏览器实例个数
, \  ~% i1 L" M8 z6 M6 x  P
, Q8 p7 q" W* b" D' d" B4 y   for(long i=0; i<nCount; i++)% q5 m+ N, j. V/ l+ x8 Q
      {
9 |! m: [* F$ \# A. D                CComPtr< IDispatch > spDisp;& @  l/ Z5 ]" `* R! Y  y, i
     hr=spShellWin->Item(CComVariant( i ), &spDisp );
) m5 W6 Z' d8 v: B% t. z      if ( FAILED( hr ) )   continue;# J( N8 v! E: E

( F/ K5 z+ H8 @+ B1 O; ?  y$ X% F3 |      CComQIPtr< IWebBrowser2 > spBrowser = spDisp;8 f' o" |3 ~# J: B3 j
     if ( !spBrowser )     continue;7 W6 x% _# Y6 t! B

  A8 b% G3 z3 M3 b" Y- D      spDisp.Release();5 P/ V* z$ Z$ E/ @- E+ }+ Y9 m. B
     hr = spBrowser->get_Document( &spDisp );' h8 t) y* {, K- m7 U
     if ( FAILED ( hr ) )  continue;
' I% e/ T. P+ ^( V( E8 e# l2 u$ W* s, r2 o" {. q8 t! X) }
     CComQIPtr< IHTMLDocument2 > spDoc = spDisp;' n+ h& P, n* C. R, {
     if ( !spDoc )         continue;% U% B1 ~. _( _, L5 V; O
8 T  x" e( e9 _
     // 程序运行到此,已经找到了 IHTMLDocument2 的接口指针- c# V5 l0 V' j3 \' o: X. @7 X9 c' {2 X
  }9 o" ?# b+ T: \. \; k3 f
}& R1 ^- D+ x, h
" P% y: h8 {2 k. Y! j
  <6> IE 浏览器控件被一个进程包装在一个子窗口中。那么你首先要得到那个进程的顶层窗口句柄(使用 FindWindow() 函数,或其它任何可行的方法),然后枚举所有子窗口,通过判断窗口类名是否是“Internet Explorer_Server”,从而得到浏览器的窗口句柄,再向窗口发消息取得文档的接口指针。主要代码如下:
' D  T" k$ S. a
7 K0 X3 E+ J8 @+ {% x1 Q1 ~9 Q. `& R3 A8 }
#include < atlbase.h >
0 H" S& X$ d2 A: F6 Q+ E#include < mshtml.h >
3 h% E( t  h$ t5 T: @# a+ K#include < oleacc.h >
9 l; O3 ~( r4 A( W- o& C#pragma comment ( lib, "oleacc" )0 n/ J/ f1 d% Y# k! e2 s% ^; D

4 O3 B/ {  T- bBOOL CALLBACK EnumChildProc(HWND hwnd,LPARAM lParam)
- b; P! h9 W+ m! }{
$ J9 e, Z6 \2 {( p# r* q( i   TCHAR szClassName[100];* F& e1 k( O( K: D/ {9 q
8 R- ?7 i5 J2 w% Q5 }8 x4 n+ O
  ::GetClassName( hwnd,  &szClassName,  sizeof(szClassName) );
# _9 ^+ {* ?- E, U; Z9 D& r   if ( _tcscmp( szClassName,  _T("Internet Explorer_Server") ) == 0 )
9 _! N& K- C# T. ~   {
) c8 S6 P; S3 ?" P* ?8 F3 @      *(HWND*)lParam = hwnd;# S) g: b! x7 F) D$ m
     return FALSE;      // 找到第一个 IE 控件的子窗口就停止
& x# N* d, O% W   }
7 c* {5 \3 q7 j" S   else   return TRUE;      // 继续枚举子窗口
2 H8 r7 t* F  W& @" c};
# a2 H7 \, s3 l6 v- d- T
) n  o4 e2 O6 p  Nvoid FindFromHwnd(HWND hWnd)
5 c: v2 U# ]. u8 \{, y" l5 O" J; @1 H! H
  HWND hWndChild=NULL;# S6 J  V0 n/ B; ?* e
  ::EnumChildWindows( hWnd, EnumChildProc, (LPARAM)&hWndChild );
0 ~" B9 ^3 o$ F   if(NULL == hWndChild)   return;  G+ l( Q( N1 w& h' {
( n* @" s' f% S  x
  UINT nMsg = ::RegisterWindowMessage( _T("WM_HTML_GETOBJECT") );
$ h- q) u6 N9 \  }: O. m% c   LRESULT lRes;
0 z- k1 N! G7 G+ l" A9 w   ::SendMessageTimeout( hWndChild, nMsg, 0L, 0L, SMTO_ABORTIFHUNG, 1000, (DWORD*) &lRes );
2 D* j) B/ Q$ ~# U- |* E: P/ g6 N/ J& V* j" |0 u
  CComPtr < IHTMLDocument2 > spDoc;
7 y" t1 \: f5 r$ H, l5 V/ v   HRESULT hr = ::ObjectFromLresult ( lRes, IID_IHTMLDocument2, 0 , (LPVOID *) &spDoc );1 a  y/ J* b+ @! I3 W5 ?
  if ( FAILED ( hr ) )   return;
* o" v& U& V$ m* X2 C9 z
6 ^8 E* T- P0 X7 D: V! F   // 程序运行到此,已经找到了 IHTMLDocument2 的接口指针
+ n. v2 x2 {( ?. _+ }1 ~}
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2025-11-14 18:06 , Processed in 0.016966 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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