导航

<2005年4月>
272829303112
3456789
10111213141516
17181920212223
24252627282930
1234567

随笔分类

随笔档案

文章档案

相册

根据IE浏览器的运行方式,有多种不同的方式可以获取文档指针。

  <1> 如果你在程序中使用MFC的 CHtmlView 视来浏览网页。
        取得文档的方法最简单,调用 CHtmlView::GetHtmlDocument() 函数。
  <2> 如果你的程序中使用了“Web 浏览器” 的ActiveX 控件。
        取得文档的方法也比较简单,调用 CWebBrowser2::GetDocument() 函数。
  <3> 如果你的程序是用 ATL 写的 ActiveX 控件。
        那么需要调用 IOleClientSite::GetContainer 得到 IOleContainer 接口,然后就可以通过 QueryInterface() 查询得到 IHTMLDocument2 的接口。主要代码如下:
CComPtr < IOleContainer > spContainer;
m_spClientSite->GetContainer( &spContainer );
CComQIPtr < IHTMLDocument2 > spDoc = spContainer;
if ( spDoc )
{
     // 已经得到了 IHTMLDocument2 的接口指针
}
  <4> 如果你的程序是用 MFC 写的 ActiveX 控件。
        那么需要调用 COleControl::GetClientSite() 得到 IOleContainer 接口,然后的操作和<3>是一致的了。
  <5> IE 浏览器作为独立的进程正在运行。
        每个运行的浏览器(IE 和 资源浏览器)都会在 ShellWindows 中进行登记,因此我们要通过 IShellWindows 取得实例(示例程序中使用的就是这个方法)。主要代码如下:
#include < atlbase.h >
#include < mshtml.h >

void FindFromShell() 
{
	CComPtr< IShellWindows > spShellWin;
	HRESULT hr = spShellWin.CoCreateInstance( CLSID_ShellWindows );
	if ( FAILED( hr ) )    return;

	long nCount=0;
	spShellWin->get_Count(&nCount);   // 取得浏览器实例个数

	for(long i=0; i<nCount; i++)
       {
                CComPtr< IDispatch > spDisp;
		hr=spShellWin->Item(CComVariant( i ), &spDisp );
		if ( FAILED( hr ) )   continue;

		CComQIPtr< IWebBrowser2 > spBrowser = spDisp;
		if ( !spBrowser )     continue;

		spDisp.Release();
		hr = spBrowser->get_Document( &spDisp );
		if ( FAILED ( hr ) )  continue;

		CComQIPtr< IHTMLDocument2 > spDoc = spDisp;
		if ( !spDoc )         continue;

		// 程序运行到此,已经找到了 IHTMLDocument2 的接口指针
	}
}

  <6> IE 浏览器控件被一个进程包装在一个子窗口中。那么你首先要得到那个进程的顶层窗口句柄(使用 FindWindow() 函数,或其它任何可行的方法),然后枚举所有子窗口,通过判断窗口类名是否是“Internet Explorer_Server”,从而得到浏览器的窗口句柄,再向窗口发消息取得文档的接口指针。主要代码如下:

#include < atlbase.h >
#include < mshtml.h >
#include < oleacc.h >
#pragma comment ( lib, "oleacc" )

BOOL CALLBACK EnumChildProc(HWND hwnd,LPARAM lParam)
{
	TCHAR szClassName[100];

	::GetClassName( hwnd,  &szClassName,  sizeof(szClassName) );
	if ( _tcscmp( szClassName,  _T("Internet Explorer_Server") ) == 0 )
	{
		*(HWND*)lParam = hwnd;
		return FALSE;		// 找到第一个 IE 控件的子窗口就停止
	}
	else	return TRUE;		// 继续枚举子窗口
};

void FindFromHwnd(HWND hWnd) 
{
	HWND hWndChild=NULL;
	::EnumChildWindows( hWnd, EnumChildProc, (LPARAM)&hWndChild );
	if(NULL == hWndChild)	return;

	UINT nMsg = ::RegisterWindowMessage( _T("WM_HTML_GETOBJECT") );
	LRESULT lRes;
	::SendMessageTimeout( hWndChild, nMsg, 0L, 0L, SMTO_ABORTIFHUNG, 1000, (DWORD*) &lRes );

	CComPtr < IHTMLDocument2 > spDoc;
	HRESULT hr = ::ObjectFromLresult ( lRes, IID_IHTMLDocument2, 0 , (LPVOID *) &spDoc );
	if ( FAILED ( hr ) )	return;

	// 程序运行到此,已经找到了 IHTMLDocument2 的接口指针
}
posted on 2005-04-20 01:12 杨老师的茅屋 阅读(3504) 评论(9)  编辑 收藏
评论
  • # re: 千方百计得到IHTMLDocument2的接口指针
    杨老师崇拜者:Diviner(SevenCat)
    Posted @ 2005-04-20 08:42
    posted on 2005-04-20 01:12 杨老师的茅屋 阅读(6) 评论(0)  编辑 收藏 

    收藏
  • # re: 千方百计得到IHTMLDocument2的接口指针
    lostpencil
    Posted @ 2005-04-20 12:49
    不错不错,我说的是:
















    今天中午吃的葱爆羊肉,哈哈哈
  • # re: 千方百计得到IHTMLDocument2的接口指针
    Ghostex
    Posted @ 2005-06-15 23:14
    看了你写的东西,我比较有收获。
    但同时也有一个大问题要问你的: 
    我也做了一个东西可以取网页中所选中的内容。 

    当代码执行到: 
    hr = frameOut.pdispVal->QueryInterface(IID_IHTMLWindow2, (void**)&pRightFrameWindow);
    hr = pRightFrameWindow->get_document(&pRightDoc);//就是这里 
    时,hr返回E_ACCESSDENIED,也就是说无权获取网页中的内容,请问一下你是怎么办到取得网页上各种元素及文字或HTML代码的? 

    我的MSN:orma_charf@hotmail.com 

    十分感谢!万分火急啊~~~~ 

    在线等。谢谢!!!
  • # re: 千方百计得到IHTMLDocument2的接口指针
    Ghostex
    Posted @ 2005-06-15 23:16
    Sorry,我的问题有点跑题,但是看您这么强,所以也就斗胆地问一下,千万不要见怪啊,呵呵~~~~
  • # to Ghostex 你的问题,请参考
    杨老师
    Posted @ 2005-06-15 23:35
    http://www.vckbase.com/document/viewdoc/?id=1446
  • # re: 千方百计得到IHTMLDocument2的接口指针
    Ghostex
    Posted @ 2005-06-17 00:05
    嗯,你的文章我看过了。我应该是<1.3> 的情况。

    如果你的程序是用 ATL 写的 ActiveX 控件。
    那么需要调用 IOleClientSite::GetContainer 得到 IOleContainer 接口,然后就可以通过 QueryInterface() 查询得到 IHTMLDocument2 的接口。主要代码如下: 
    CComPtr < IOleContainer > spContainer;
    m_spClientSite->GetContainer( &spContainer );
    CComQIPtr < IHTMLDocument2 > spDoc = spContainer;
    if ( spDoc )
    {
         // 已经得到了 IHTMLDocument2 的接口指针
    }
    //------------------
    我是在我的类成员方法函数SetSite()中获取IWebBroswer2接口的。但在同样的地方,我查询不到IOleClientSite相关的接口(MSDN上查了一下,这个接口好像是WINCE5.0的。
    请问如何获取IOleClientSite的接口,并进而获取spContainer指针?在任意地方都可以么?还是要在某个特定的地址才可以??

    谢谢!静等回音。
  • # re: 千方百计得到IHTMLDocument2的接口指针
    Ghostex
    Posted @ 2005-06-17 01:11
    历尽千辛万苦,在MSDN找到这种用法的出处:
    http://msdn.microsoft.com/library/default.asp?url=/workshop/components/activex/buildax.asp

    All the capabilities of the object model are available to the control, allowing it to both read and modify the document content. If a control supports either the IObjectWithSite or IOleObject interface, accessing the object model is very simple and consists of the following two steps: 

    Call IOleClientSite::GetContainer. This returns the IOleContainer interface of the host of the control. 
    Call QueryInterface on the IOleContainer interface for the IHTMLDocument2 interface;
    // Get the document.
    CComPtr<IOleContainer> spContainer; 
    m_spClientSite->GetContainer(&spContainer); 
    CComQIPtr<IHTMLDocument2, &IID_IHTMLDocument2> spDoc(spContainer); 
    if (spDoc)
        spDoc->put_bgColor(CComBSTR(_T("pink")));

    其中,有这么一句“If a control supports either the IObjectWithSite or IOleObject interface, accessing the object model is very simple ”,而我的头文件中是这样写的,
    class  CStockBar : 
    public CComObjectRootEx<CComSingleThreadModel>,
    public CComCoClass<CStockBar, &CLSID_StockBar>,
    public IDeskBand,
    public IObjectWithSite,
    public IInputObject,
    //public IPersistStream,
    public IDispatchImpl<IStockBar, &IID_IStockBar, &LIBID_BOCAITOOLBARLib>
    {
    public:.......
    }
    难道说这样还不行么,我这里有IObjectWithSite接口啊?
    m_spClientSite还是没有办法获得~~~唉~~~
  • # re: 千方百计得到IHTMLDocument2的接口指针
    Shaoqing Yu
    Posted @ 2007-02-28 14:03
    Sample to get browser's URL
    ref to "http://blog.csdn.net/shanhe/archive/2005/07/17/427559.aspx"



    // LyIPCtl.cpp : Implementation of CLyIPCtl

    #include "stdafx.h"
    #include "LyIPCamer.h"
    #include "LyIPCtl.h"

    #define IPC_DEBUG
    #ifdef IPC_DEBUG
    //for _com_util::ConvertBSTRToString
    #pragma comment( lib, "comsupp.lib")
    #include <comutil.h>
    #endif

    //for OLE to get IE interface
    #include <ExDisp.h>
    #include <shlguid.h>
    /////////////////////////////////////////////////////////////////////////////
    // CLyIPCtl


    STDMETHODIMP CLyIPCtl::StartView()
    {
    HRESULT hr = E_FAIL;

    if (m_spClientSite)

    {
    CComPtr<IOleContainer> spContainer;

    hr = m_spClientSite->GetContainer(&spContainer);

    ATLASSERT(SUCCEEDED(hr));

    if (SUCCEEDED(hr))

    {
    CComQIPtr<IServiceProvider, &IID_IServiceProvider>
    spServiceProvider(spContainer);
    ATLASSERT(spServiceProvider);
    if (!spServiceProvider)
    hr = E_FAIL;
    else
    {
    CComPtr<IWebBrowser2> spWebBrowser;
    hr = spServiceProvider->QueryService(SID_SInternetExplorer,
    IID_IWebBrowser2,
    (void**)&spWebBrowser);
    ATLASSERT(SUCCEEDED(hr));

    if (SUCCEEDED(hr))
    {         
    BSTR bstrURL;
    spWebBrowser->get_LocationURL(&bstrURL);

    #ifdef IPC_DEBUG
    char *buf = (char *)_com_util::ConvertBSTRToString(bstrURL);
    MessageBox(buf,"title",MB_OK);
    delete(buf); 
    /*spWebBrowser->ExecWB(OLECMDID_PRINT, 
    OLECMDEXECOPT_PROMPTUSER,
    NULL, NULL);*/
    #endif
    }
    }
    }
    }

    return hr;
    }

    STDMETHODIMP CLyIPCtl::StopView()
    {
    #ifdef IPC_DEBUG
    // TODO: Add your implementation code here
    MessageBox("Stop","title",MB_OK);
    #endif

    return S_OK;
    }
  • # re: 千方百计得到IHTMLDocument2的接口指针
    Shaoqing Yu
    Posted @ 2007-02-28 14:07
    1、创建ATL工程LyIPCamer
    2、插入ATL object,LyIPCtl
    3、添加方法StartView、StopView
    4、添加
    #define IPC_DEBUG
    #ifdef IPC_DEBUG
    //for _com_util::ConvertBSTRToString
    #pragma comment( lib, "comsupp.lib")
    #include <comutil.h>
    #endif

    //for OLE to get IE interface
    #include <ExDisp.h>
    #include <shlguid.h> 

    5、修改HTML如下
    <HTML>
    <HEAD>
    <TITLE>ATL 3.0 test page for object LyIPCtl</TITLE>
       <SCRIPT LANGUAGE="VBS">
          Sub btnStart_onclick
             LyIPCtl.StartView
          End Sub
          Sub btnStop_onclick
             LyIPCtl.StopView
          End Sub</SCRIPT>
    </HEAD>
    <BODY>
    <OBJECT ID="LyIPCtl" CLASSID="CLSID:39A2AAE4-9DA7-47AA-90F8-477167CCEA84"></OBJECT>
    <P>
    <BUTTON ID="btnStart">Start View</BUTTON>
    <P>
    <BUTTON ID="btnStop">Stop View</BUTTON>
    </BODY>
    </HTML>
标题  
姓名  
主页
验证码 *
内容   
  登录  使用高级评论  Top
[使用Ctrl+Enter键可以直接提交]

统计