??xml version="1.0" encoding="utf-8" standalone="yes"?>久久夜色精品国产www,久久久久久久97,国产精品久久久久免费a∨http://m.shnenglu.com/mydriverc/category/4795.html如果想飞得高Q就该把地^U忘?/description>zh-cnMon, 19 May 2008 13:36:41 GMTMon, 19 May 2008 13:36:41 GMT60ATL 实现定制?IE 览器栏、工h和桌面工h http://m.shnenglu.com/mydriverc/articles/29017.html旅?/dc:creator>旅?/author>Mon, 30 Jul 2007 08:00:00 GMThttp://m.shnenglu.com/mydriverc/articles/29017.htmlhttp://m.shnenglu.com/mydriverc/comments/29017.htmlhttp://m.shnenglu.com/mydriverc/articles/29017.html#Feedback0http://m.shnenglu.com/mydriverc/comments/commentRss/29017.htmlhttp://m.shnenglu.com/mydriverc/services/trackbacks/29017.htmlATL 实现定制?IE 览器栏、工h和桌面工h

作者:(x)杨老师

下蝲源代?/font>

关键?/strong>QBandQDesk BandQExplorer BandQTool BandQ浏览器栏,工具栏,桌面工具?br>
一、引a
  最q,׃工作的要求,我需要在 IE 上做一些开发工作。于是在 MSDN 上翻阅了一些资料,Ҏ(gu) MSDN 上的说明我用 ATL 胜利完成?#8220;资本家老板”分配的Q务?br>Qƈ且在白天睡觉的过E中梦到了老板l我加工资啦......Q?br>现在Q我?MSDN 上的原文资料Q经q翻译整理ƈ把一?ATL 的实现奉贤给 VCKBASE 上的朋友们?/p>


  在翻译的q程中,有两个词汇非怸好理解。第一个词?Band 对象Q词怸译?#8220;镶边、裙子边、带子、乐?.....”我的英文水^有限Q实在不知道应该译Z么词汇更合适。于是我毅然决然地决定:(x)在如下的中,依然使用 band q个词!Q什么?没听明白Q我的意思就是说Q我不翻译这个词了)但到?Band 对象应该如何理解那?L(fng)图一Q?br>

图一

  图一中画U圈的地方,分别UC“垂直的浏览器?#8221;?#8220;水^的浏览器?#8221;?#8220;工具?#8221;?#8220;桌面工具?#8221;。这?#8220;?#8221;Q都可以?IE ?#8220;查看”菜单中或鼠标右键的上下文快捷方式菜单中显C或隐藏h。这些界面窗口的实现Q其实就是实CU?COM 接口对象Q而这个对象叫 band。这个概念实在是只能意会(x)而无法言传的Q我M能在文章中把它翻译ؓ(f)“L靠在 IE ȝ口边上的对象”吧?^_^
  另外Q还有一个词?site。这个很好翻译,?#8220;站点”Q。呵呵,我敢打包,如果你要能理解这个翻译在计算机类文章中的含义Q那只能恭喜你了,你的智慧太高了。(都是学计机软g的hQ做人的差距咋就q么大呢Q)在本文章中Qsite 可以q样理解QIE 的主框架四周Q就好比?#8220;汽R?#8221;Q那?band 对象Q就好比?#8220;汽R”。band 汽RL可以停靠?#8220;汽R?#8221;上。所以,site 是“站点”Q它也是 COM 接口的对象(IObjectWithSite、IInputObjectSiteQ?br>


3.1 基本 band 对象
  Band 对象Q从 Shell 4.71(IE 5.0) 开始提供支持。Band 是一?COM 对象Q必L在一个容器中M用,当然使用它们好象用普通窗口是一L(fng)。IE 是一个容器,桌面 Shell 也是一个容器,它们提供不同的函数功能,但基本的实现是相似的?br>  Band 对象分三U类型,览器栏 bandQExplorer bandsQ、工h bandQTool BandsQ和桌面工具?Desk bands)Q而浏览器?band 又有两种表现形式Q垂直和水^的。那?IE ?Shell 如何区分q加载这?bands 对象呢?Ҏ(gu)是:(x)你要对不同的 band 对象Q在注册表中注册不同的组件类型(CATIDQ?br>

Band 样式

lgcd

CATID

垂直的浏览器?/td> CATID_InfoBand 00021493-0000-0000-C000-000000000046
水^的浏览器?/td> CATID_CommBand 00021494-0000-0000-C000-000000000046
桌面的工h CATID_DeskBand 00021492-0000-0000-C000-000000000046

  IE 工具栏不使用lgcd注册Q而是使用在注册进?CLSID 的登记方式。详l情况见 3.3?br>  在例子程序中Q实C全部四个cd?band 对象Q垂直浏览器?CVerticalBar)昄了一?HTML 文gQƈ且实C?IE ȝ口浏览网늚D{功能;水^的浏览器?CHorizontalBar)是一个编辑窗Q它同步昄当前|页?BODY 源文件内容;IE 工具?CToolBar)最单,只是d了一个空的工hQ桌面工h(CDeskBar)实现了一个单行编辑窗口,你可以在上面输入命o(h)行或文g名称Q回车后它会(x)执行 Shell 的打开动作?br>
3.2 必须实现?COM 接口
  Band 对象?IE ?Shell 的进E内服务器,所以它被包装在 DLL 中。而作?COM 对象Q它必须要实?IUnknown ?IClassFactory 接口。(大家可以不同操心Q因为我们用 ATL 写程序,q两个接口是不用我们自己写代码的。)另外QBand 对象q必d?IDeskBand、IObjectWithSite ?IPersistStream 三个接口Q?br>  IPersistStream 是持l性接口的一U。当 IE 加蝲 band 对象的时候,它通过q个接口?Load Ҏ(gu)传递属性值给对象Q让其进行初始化Q而当卸蝲前,IE 则调用这个接口的 Save Ҏ(gu)保存对象的属性。用 ATL 实现q个接口很简单:(x)

class ATL_NO_VTABLE Cxxx : 	......	public IPersistStreamInitImpl, // dl承	......{public:	BOOL m_bRequiresSave; // IPersistStreamInitImpl 所必须的变?.....BEGIN_COM_MAP(CVerticalBar)	......	COM_INTERFACE_ENTRY2(IPersist, IPersistStreamInit)	COM_INTERFACE_ENTRY2(IPersistStream, IPersistStreamInit)	COM_INTERFACE_ENTRY(IPersistStreamInit)	......END_COM_MAP()BEGIN_PROP_MAP(Cxxx)...... // d需要持l性的属性END_PROP_MAP()		
  上面的代码,其实实现的是 IPersistStreamInit 接口Q不q没有关p,因ؓ(f) IPersistStreamInit z?IPersistStreamQ实例化了派生类Q自然就实例化了基类。在例子E序中,我只在桌面工h对象中添加了持箋性属性,用来保存和初始化“命o(h)?#8221;。另?COM_INTERFACE_ENTRY2(AQB)表示的含义是Q如果想查询A接口的指针,则提供B接口指针来代ѝؓ(f)什么可以这样那Q因为B接口z自A接口Q那么B接口的前几个函数必然是A接口的函CQ自然B接口的地址其实和A接口的地址是一L(fng)了?br>  IObjectWithSite ?IE 用来Ҏ(gu)件进行管理和通讯用的一个接口。必要实现q个接口?个函敎ͼ(x)SetSite() ?GetSite()。当 IE 加蝲 band 对象和释?band 对象的时候,都要调用 SetSite()函数Q那么在q个函数里正好是写初始化和释放操作代码的地方Q?
STDMETHODIMP Cxxx::SetSite(IUnknown *pUnkSite){	if( NULL == pUnkSite )	// 释放 band 的时?{		// 如果加蝲的时候,保存了一些接?	// 那么现在Q释攑֮	}	else	// 加蝲 band 的时?{		m_hwndParent = NULL;	// 装蝲 band 的父H口(是带有标题的那个框架窗?		// q个H口的句柄,是调?IUnknown::QueryInterface() 得到 IOleWindow		// 然后调用 IOleWindow::GetWindow() 而获得的?	CComQIPtr< IOleWindow, &IID_IOleWindow > spOleWindow(pUnkSite);		if( spOleWindow )	spOleWindow->GetWindow(&m_hwndParent);		if( !m_hwndParent )	return E_FAIL;				// 现在Q正好是建立子窗口的时机?	// 注意Q子H口建立的时候,不要使用 WS_VISIBLE 属?	... ...		// 在例子程序中Q用 CAxWindow 实现了一个能包容ActiveX的容器窗?垂直览器栏)		// 在例子程序中Q用 WIN API 函数 CreateWindow 实现了标准窗?水^览器栏、工h)		// 在例子程序中Q用 CWindowImpl 实现了一个包容窗?桌面工具?		/*********************************************************/		   以下部分Q根?band 对象Ҏ(gu)的功能,是可以选择实现?	**********************************************************/				// 如果子窗口实C用户输入Q那么必d?IInputObject 接口Q?	// 而该接口是被 IE ?IInputObjectSite 调用的,因此在你的对?	// 中,应该保存 IInputObjectSite 的接口指针?	// 在类的头文g中,定义Q?	// CComQIPtr< IInputObjectSite, &IID_IInputObjectSite > m_spSite;		m_spSite = pUnkSite;	// 保存 IInputObjectSite 指针		if( !m_spSite )		return E_FAIL;		// 你需要控?IE 的主框架吗?		// 那么在类的头文g中,定义Q?	// CComQIPtr< IWebBrowser2, &IID_IWebBrowser2 > m_spFrameWB;		// 然后Q先取得 IServiceProvider,再取?IWebBrowser2		CComQIPtr < IServiceProvider, &IID_IServiceProvider> spSP(pUnkSite);		if( !spSP )	return E_FAIL;		spSP->QueryService( SID_SWebBrowserApp, &m_spFrameWB );		if( !m_spFrameWB)	return E_FAIL;		// 如果你取得了 IE L架的 IWebBrowser2 指针		// 那么Q当它发生了什么事情,你难道不想知道吗Q?	// 定义QCComPtr m_spCP;		CComQIPtr< IConnectionPointContainer,			&IID_IConnectionPointContainer> spCPC( m_spFrameWB );		if( spCPC )		{			spCPC->FindConnectionPoint( DIID_DWebBrowserEvents2, &m_spCP );			if( m_spCP )			{				m_spCP->Advise( reinterpret_cast< IDispatch * >( this ), &m_dwCookie );			}		}		// 咳~~~ 不说了,看源码去吧。这里能q的事情太多?.. ...	}	return S_OK;}		
IDeskBand 是一个特D的 band 对象接口Q有一个方法函敎ͼ(x)GetBarInfo()Q?br>IDockingWindow ?IDeskBank 的基c,?个方法函敎ͼ(x)ShowDW()、CloseDW()、ResizeBorderDW()Q?br>IOleWindow 又是 IDockingWindow 的基c,?个方法函敎ͼ(x)GetWindow()、ContextSensitiveHelp()Q?

  首先声明 IDeskBand ,然后要实?IDeskBand 接口的共6个函敎ͼq些函数比较单,不同cd?band 对象Q其实现Ҏ(gu)也都基本一_(d)(x)
class ATL_NO_VTABLE Cxxx : 	......	public IDeskBand,	......{......BEGIN_COM_MAP(Cxxx)	......	COM_INTERFACE_ENTRY_IID(IID_IDeskBand, IDeskBand)	......END_COM_MAP()// IOleWindowSTDMETHODIMP Cxxx::GetWindow(HWND * phwnd){	// 取得 band 对象的窗口句?// m_hWnd 是徏立窗口时候保存的	*phwnd = m_hWnd;		return S_OK;}STDMETHODIMP Cxxx::ContextSensitiveHelp(BOOL fEnterMode){	// 上下文帮助,参?IContextMenu 接口	return E_NOTIMPL;}// IDockingWindowSTDMETHODIMP CVerticalBar::ShowDW(BOOL bShow){	// 昄或隐?band H口	if( m_hWnd )		::ShowWindow( m_hWnd, bShow ? SW_SHOW : SW_HIDE);	return S_OK;}STDMETHODIMP CVerticalBar::CloseDW(DWORD dwReserved){	// 销?band H口	if( ::IsWindow( m_hWnd ) )		::DestroyWindow( m_hWnd );	m_hWnd = NULL;    return S_OK;}STDMETHODIMP CVerticalBar::ResizeBorderDW(LPCRECT prcBorder, IUnknown* punkToolbarSite, BOOL fReserved){	// 当框架窗口的Ҏ(gu)大小改变?return E_NOTIMPL;}// IDeskBandSTDMETHODIMP CVerticalBar::GetBandInfo(DWORD dwBandID, DWORD dwViewMode,  DESKBANDINFO* pdbi){	         // 取得 band 的基本信息,你需要填?pdbi 参数作ؓ(f)q回	if( NULL == pdbi )		return E_INVALIDARG;	// 如果来需要调?IOleCommandTarget::Exec() 则需要保存这2个参?m_dwBandID = dwBandID;	m_dwViewMode = dwViewMode;	if(pdbi->dwMask & DBIM_MINSIZE)	{	// 最尺?	pdbi->ptMinSize.x = 10;		pdbi->ptMinSize.y = 10;	}	if(pdbi->dwMask & DBIM_MAXSIZE)	{	// 最大尺?(-1 表示 4G)		pdbi->ptMaxSize.x = -1;		pdbi->ptMaxSize.y = -1;	}	if(pdbi->dwMask & DBIM_INTEGRAL)	{		pdbi->ptIntegral.x = 1;		pdbi->ptIntegral.y = 1;	}	if(pdbi->dwMask & DBIM_ACTUAL)	{		pdbi->ptActual.x = 0;		pdbi->ptActual.y = 0;	}	if(pdbi->dwMask & DBIM_TITLE)	{	// H口标题		wcscpy(pdbi->wszTitle,L"H口标题");	}	if(pdbi->dwMask & DBIM_MODEFLAGS)	{		pdbi->dwModeFlags = DBIMF_VARIABLEHEIGHT;	}	if(pdbi->dwMask & DBIM_BKCOLOR)	{	// 如果使用默认的背景色Q则U除该标?	pdbi->dwMask &= ~DBIM_BKCOLOR;	}	return S_OK;}		
3.3 选择实现?COM 接口
  有两个接口不是必d现的Q但也许很有用:(x)IInputObject ?IContextMenu。如?band 对象需要接收用L(fng)输入Q那么必d?IInputObject 接口。IE 实现?IInputObjectSite 接口Q当容器中有多个输入H口Ӟ它调?IInputObject 接口Ҏ(gu)去负责管理用L(fng)输入焦点?br>在浏览器栏中需要实?个函敎ͼ(x)UIActivateIO()、HasFocusIO()、TranslateAcceleratorIO()?br>当浏览器栏激zL失去zL的时候,IE 调用 UIActivateIO 函数Q当Ȁzȝ时候,览器栏一般调?SetFocus 去设|它自己H口的焦炏V当 IE 需要判断哪个窗口有焦点的时候,它调?HasFocusIO 。当览器栏的窗口或其子H口有输入焦Ҏ(gu)Q则应返?S_OKQ否则返?S_FALSE。TranslateAcceleratorIO 允许对象处理加速键Q例子程序中没有实现Q所以直接返?S_FALSE?
STDMETHODIMP CExplorerBar::UIActivateIO(BOOL fActivate, LPMSG pMsg){    if(fActivate)        SetFocus(m_hWnd);    return S_OK;}STDMETHODIMP CExplorerBar::HasFocusIO(void){    if(m_bFocus)        return S_OK;    return S_FALSE;}STDMETHODIMP CExplorerBar::TranslateAcceleratorIO(LPMSG pMsg){    return S_FALSE;}      
  Band 对象能够通过包容器的 IOleCommandTarget::Exec() 调用执行命o(h)。?IOleCommandTarget 接口指针Q则可以通过调用包容器的 IInputOjbectSite::QueryInterfaceQIID_IOleCommandTarget,...Q?函数得到。CGID_DeskBand 是命令组Q当一?band 对象?GetBandInfo 被调用的时候,包容器通过 dwBandID 参数指定一?ID l?band 对象Q对象要保存住这个IDQ以便调?IOleCommandTarget::Exec()的时候用。ID 的命令有Q?
  • DBID_BANDINFOCHANGED
    Band 的信息变化。设|参?pvaIn ?band IDQ??ID 是最q一ơ调?GetBandInfo 所得到的|容器?x)调?band 对象?GetBandInfo 函数来更新请求信息?
  • DBID_MAXIMIZEBAND
    最大化 band。设|参?pvaIn ?band IDQ该 ID 是最q一ơ调??GetBandInfo ?所得到的倹{?
  • DBID_SHOWONLY
    打开或关闭容器中其它?bands?讄参数 pvaIn 为VT_UNKNOWN cdQ它可以是如下的|(x)
     
    ?/font> 描述
    pUnk band 对象?IUnknown 指针Q其它的桌面 bands 被隐藏
    0 隐藏所有的桌面 bands
    1 昄所有的桌面 bands

  • DBID_PUSHCHEVRON
    在菜单项左边昄“v”的选择标志。容器发送一?RB_PUSHCHEVRON 消息Q当 band 对象接收到通知消息 RBN_CHEVRONPUSHED 提示它显CZ?v"的标志。设|?IOleCommandTarget::Exec 函数?nCmdExecOpt 参数?band IDQ该 ID 是最q一ơ调?GetBandInfo ?所得到的|讄 IOleCommandTarget::Exec 函数?pvaIn 参数?VT_I4 cdQ这是应用程序定义的一个|它通过通知消息 RBN_CHEVRONPUSHED 中lAppValue 回传l?band 对象?

3.4 Band 对象注册
  Band 对象必须注册Z?OLE q程内的服务器,q且支持 apartment U程公寓。注册表中默认键的值是表示菜单的文字。对于浏览器栏,它加?IE 菜单?#8220;查看\览器栏”中;对于工具?band Q它加到 IE 菜单?#8220;查看\工具?#8221;中;对于桌面 bandQ?它加到系lQ务栏的快捯单中。在菜单资源中,可以使用“&”指明加速键?br>
通常Q一个基本的 band 对象的注册表目是:(x)

HKEY_CLASSES_ROOT
CLSID
{你的 band 对象?CLSID}

  (Default) = 菜单的文?
  InProcServer32
   (Default) = DLL 的全路径文g?
   ThreadingModel= Apartment

工具?bands q必L它们?CLSID 注册?IE 的注册表中?br>
?HKEY_LOCAL_MACHINE\Software\Microsoft\Internet Explorer\Toolbar 下给?CLSID 作ؓ(f)键名Q而其键值是被忽略的?br>
HKEY_LOCAL_MACHINE
Software
Microsoft
Internet Explorer
Toolbar

  {你的 band 对象?CLSID}

  q有几个可选的注册表项?例子E序q不是这样实现的)。比如,你想让浏览器栏显C?HTML 的话Q必要如下讄注册表:(x)

HKEY_CLASSES_ROOT
CLSID
{你的 Band 对象?CLSID}
Instance
CLSID
  
(Default) = {4D5C8C2A-D075-11D0-B416-00C04FB90376}

同时Q如果要指定一个本地的 HTML 文gQ那么要如下讄Q?

HKEY_CLASSES_ROOT
CLSID
{你的 Band 对象?CLSID}
Instance
InitPropertyBag
  
Url

  另外Q还可以指定览器栏的宽和高Q当Ӟ它是依赖于这个栏是纵向还是横向的。其实这个项目无所谓,因ؓ(f)当用戯整了览器栏的大后Q会(x)自动保存在注册表中的?br>
HKEY_CURRENT_USER
Software
Microsoft
Internet Explorer
Explorer Bars
{你的 Band 对象?CLSID}
  
BarSize

  BarSize 键的cd必须?REG_BINARY cdQ它?个字节。左起前4个字节,是用16q制表示的像素宽度或高度Q后4个字节保留,你应该设|ؓ(f)0。下面是一个可以在览器栏上显C?HTML 文g的全部注册表目的例子,默认宽度?91Q?x123Q个像素点:(x)

HKEY_CLASSES_ROOT
CLSID
{你的 Band 对象?CLSID}

 (Default) = 菜单文字
 InProcServer32
  (Default) = DLL 的全路径文g?
  ThreadingModel= Apartment
Instance
CLSID

  (Default) = {4D5C8C2A-D075-11D0-B416-00C04FB90376}
InitPropertyBag
  Url= 你的 HTML 文g?br>
HKEY_CURRENT_USER
Software
Microsoft
Internet Explorer
Explorer Bars
{你的 Band 对象?CLSID}

  BarSize= 23 01 00 00 00 00 00 00

  对于注册表的讄Q用 ATL 实现其实是异常简单的。打开工程?xxx.rgs 文gQƈ手工~辑一下就可以了?下面q个文g源码Q是例子E序?IE 工具栏的注册表样式,HKLM 是需要手工添加的Q因为它不用组件类型方式注册。而对于其它类型的 band 对象只要在类声明中添加:(x)

BEGIN_CATEGORY_MAP(Cxxx)			// 向注册表中注?COM cd	IMPLEMENTED_CATEGORY(CATID_InfoBand)	// 垂直样式的浏览器栏END_CATEGORY_MAP()		
IE 工具栏类?band 对象?#8220;.rgs”文g
HKCR	// q个目?ATL 帮你生成的,你只要手工修?#8220;菜单上的文字”可以了{	Bands.ToolBar.1 = s ''ToolBar Class''	{		CLSID = s ''{ 你的 CLSID }''	}	Bands.ToolBar = s ''ToolBar Class''	{		CLSID = s ''{ 你的 CLSID }''		CurVer = s ''Bands.ToolBar.1''	}	NoRemove CLSID	{		ForceRemove { 你的 CLSID } = s ''用在菜单上的文字(&T)''		{			ProgID = s ''Bands.ToolBar.1''			VersionIndependentProgID = s ''Bands.ToolBar''			ForceRemove ''Programmable''			InprocServer32 = s ''%MODULE%''			{				val ThreadingModel = s ''Apartment''			}			''TypeLib'' = s ''{xxxx-xxxx-xxxxxxxxxxxxxxx}''		}	}}HKLM	// q个目是手工添加的IE工具栏所Ҏ(gu)的{	Software	{		Microsoft		{			''Internet Explorer''			{				NoRemove Toolbar				{					ForceRemove val { 你的 CLSID } = s ''随便l个说明性文字串''				}			}		}	}}		
四?ATL 实现
  下蝲代码?VC 6.0 工程)Q请参照前面的说明仔l阅读,代码中也有一些关键点的注释。如果想q行Q则可以?regsvr32.exe q行注册Q然后打开 IE 览器或资源览器就可以看到效果了。如果想自己实践一下,可以按照如下的步骤构造工E:(x)

4.1 建立一?ATL DLL 工程
4.2 d New ATL Object...Q选择 Internet Explorer ObjectQ选这个类型的目的是让向导l我们添?IObjectWithSite 的支持。如果你使用的是 .net 环境Q则不要忘记选择支持q个接口?br>


4.3 输入对象名称Q比如我惛_立一个垂直的览器栏Q不妨叫?VerBar



4.4 U程模型必须选择 ApartmentQ接口类型的选择无所谓,看你想不x?IDispatch 接口功能了。在例子E序中的垂直览器栏中,׃x单的操纵 IE 和从 IE 中接受事Ӟq接点)Q选择 Dual 是必要的。聚合选项Q你只要别选择 Only 可以了?br>


4.5 展现你无IL(fng)智慧Q开始输入程序吧。如果是 Debug 方式~译Q可能会(x)出现一个连接错误,报告找不到_AtlAxCreateControlQ那么你要在菜单 Project\Settings...\Link 中增加对 Atl.lib 的连接。或者?#pragma comment ( lib, "atl" )加入q接库?br>4.6 如果惌试代码,在菜?Project\Settings...\Debug 中输?IE 的\径名Uͼ比如Q?#8220;C:\Program Files\Internet Explorer\IEXPLORE.EXE”Q然后就可以跟踪断点调试了?~译和调试桌面工h?band 对象Q是非常ȝ的,因ؓ(f)计算机启动时自动q行 ShellQ?Shell ׃(x)加蝲zd的桌面对象?br>
五、结束语
好了Q到q里Q就到这里了。祝大家学习(fn)快乐^_^ 


]]>
Internet Explorer ~程qͼ十一Q实现完的Inplace Drag & Drop——“超U拖䏀?/title><link>http://m.shnenglu.com/mydriverc/articles/28966.html</link><dc:creator>旅?/dc:creator><author>旅?/author><pubDate>Sun, 29 Jul 2007 07:40:00 GMT</pubDate><guid>http://m.shnenglu.com/mydriverc/articles/28966.html</guid><wfw:comment>http://m.shnenglu.com/mydriverc/comments/28966.html</wfw:comment><comments>http://m.shnenglu.com/mydriverc/articles/28966.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://m.shnenglu.com/mydriverc/comments/commentRss/28966.html</wfw:commentRss><trackback:ping>http://m.shnenglu.com/mydriverc/services/trackbacks/28966.html</trackback:ping><description><![CDATA[<div style="margin: 0in; font-size: 10pt;"><font face="Courier New"><font size="3"><strong> 关键?/strong> Q超U拖放,GetDropTargetQondragoverQIHTMLDataTransfer</font></font></div> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New"> </font></div> <div style="margin: 0in; font-weight: bold; font-size: 10pt;"><font face="Courier new" size="3">1、概q?/font></div> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New">许多多窗口浏览器都提供了一U被UCؓ(f)“拖放”Q或“拖拽”?#8220;随心拖放”{等Q不一而Q的功能。作为对IE拖拽行ؓ(f)Ҏ(gu)展,“拖放”实现了一些非常实用的功能Q?/font></div> <ul style="margin-top: 0in; margin-bottom: 0in; margin-left: 0.5in; direction: ltr; unicode-bidi: embed;" type="disc"> <li style="margin-top: 0px; font-size: 10pt; margin-bottom: 0px; vertical-align: middle;"><font face="Courier New">拖放|页链接Q通常是在新窗口中打开 </font></li> <li style="margin-top: 0px; font-size: 10pt; margin-bottom: 0px; vertical-align: middle;"><font face="Courier New">拖放选中的文字:(x)保存文字、作为关键字通过搜烦引擎搜烦|络、作为Url打开{?</font></li> <li style="margin-top: 0px; font-size: 10pt; margin-bottom: 0px; vertical-align: middle;"><font face="Courier New">拖放囄Q通常是保存图片到指定文g?</font></li> <li style="margin-top: 0px; font-size: 10pt; margin-bottom: 0px; vertical-align: middle;"><font face="Courier New">当然Q还有很关键的一点:(x)拖动对象旉标指针反馈不同的拖拽效果 </font></li> </ul> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New">在?/font><a target="_blank" ><font face="Courier New">Internet Explorer ~程qͼ十)响应来自HTML Element的事仉知——几个好用的c?/font></a><font face="Courier New">》中曾提刎ͼ管许多览器都提供了超U拖攄功能Q但与IE的缺省实现相比,除了具备鼠标指针拖拽效果外,q没有哪个浏览器的实现能够实玎ͼ(x)</font></div> <ul style="margin-top: 0in; margin-bottom: 0in; margin-left: 0.5in; direction: ltr; unicode-bidi: embed;" type="disc"> <li style="margin-top: 0px; font-size: 10pt; margin-bottom: 0px; vertical-align: middle;"><font face="Courier New">文字在页面内与输入框之间的交互拖放(q一Ҏ(gu)为重要) </font></li> <li style="margin-top: 0px; font-size: 10pt; margin-bottom: 0px; vertical-align: middle;"><font face="Courier New">来自外部的文字与|页输入框之间的交互拖放 </font></li> <li style="margin-top: 0px; font-size: 10pt; margin-bottom: 0px; vertical-align: middle;"><font face="Courier New">拖拽时滚动页面(q一Ҏ(gu)被忽略了Q?</font></li> </ul> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New"> </font></div> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New">本文的目的,一是介l实现超U拖攄两种Ҏ(gu)Q二是说明如何实?#8220;完美”的拖䏀—即扩展IE拖拽行ؓ(f)的同Ӟ保留IE默认的拖拽行为。三是给Z个最为直接和z的实现Q至于拖放不同的对象以实C同的功能Q不在本文讨论的范围Q略厅R?/font></div> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New"> </font></div> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New"> </font></div> <div style="margin: 0in; font-weight: bold; font-size: 10pt;"><font face="Courier new" size="3">2、标准的实现Ҏ(gu)</font></div> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New">标准Ҏ(gu)即通过IDocHostUIHandler的GetDropTarget成员函数来实玎ͼ在MSDNq样说到Q?/font></div> <blockquote dir="ltr" style="margin-right: 0px;"> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New">IDocHostUIHandler::GetDropTarget Method——Called by MSHTML when it is used as a drop target. This method enables the host to supply an alternative IDropTarget interface.</font></div> </blockquote> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New">? 在适当的时候,MSHTML引擎?x)调用IDocHostUIHandler的GetDropTargetҎ(gu)Qؓ(f)应用E序提供一个机?x)来替换MSHTML ~省的DropTarget实现。我们就可以通过q个自定义的DropTarget实现来完成上q的“拖放”功能。方法示例如?其中略去的部分可? 考MFC中CHtmlControlSite和CHtmlView的源代码Q?/font></div> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New"> </font></div> <blockquote dir="ltr" style="margin-right: 0px;"> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New">STDMETHODIMP CHtmlControlSite::XDocHostUIHandler::GetDropTarget(</font></div> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font face="Courier New">LPDROPTARGET pDropTarget, LPDROPTARGET* ppDropTarget)</font></div> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New">{</font></div> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font face="Courier New">METHOD_PROLOGUE_EX_(CHtmlControlSite, DocHostUIHandler)</font></div> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font face="Courier New">*ppDropTarget = g_pDropTarget;//<font style="background-color: #808080;" color="#ffffff">自定义的实现告知MSHTML引擎</font></font></div> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font face="Courier New"><strong> return</strong> S_OK;</font></div> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New">}</font></div> </blockquote> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New"> </font></div> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New">? 中g_pDropTarget指向某个全局的IDropTarget接口的实玎ͼ我们假定为CIEDropTargetQCIEDropTarget实现 了IDropTarget的几个成员函数DragEnter、DragOver、DragLeave和Drop。在DragEnter中可以决定是否接? 一个Drop以及如果接受q个Drop的话该提供怎样的鼠标拖拽反馈,在持l触发的DragOver中同样可以设定鼠标拖拽反馈,从而实现在拖放不同的对 象(文字、链接、图像等Q时提供不同的拖拽视觉效果,实现相当单,此处不再赘述?/font></div> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New">? 上面的实现存在一些问题。首先是选中的文字在面内与输入框之间交互的拖放没有了。这是自然的Q既然我们用自定义的DropTarget替换掉了IE的缺 省实玎ͼ那这U交互的拖放理应由我们自己实现。难处ƈ非在于不能实玎ͼ而是在于实现h比较ȝ——光是得到鼠标下的HTML Element够我们烦了Q当输入框中有文字的时候,光标q应该随着鼠标的移动而移动——所以这个费力还不一定讨好的功能g没有哪个览器去做。其 ơ,作ؓ(f)输入框文字拖攄衍生物,拖拽滚动没有了。当鼠标向某个方向拖拽时Q网应该随着不可见的部分滚动出来,比如某个输入框,让我们有Z(x)文字拖 拽过厅R这个Feature的实现ƈ不困难,不过一来是被忽略了Q注意到拖拽滚动的hq不多)Q二来主要Feature都没有实玎ͼq个滚动也意义不? 了?/font></div> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New"> </font></div> <div style="margin: 0in; font-weight: bold; font-size: 10pt;"><font face="Courier new" size="3">3、打入MSHTML内部</font></div> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New">既然从GetDropTarget提供外部实现难以得到与输入框的交互式拖放Q那换个角度来考虑问题Q让我们打入MSHTML的内部?/font></div> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New">着 手点是IHTMLDocumentX接口——操UIE的DOM的法宝。我们注意到IHTMLDocument2有个ondragstart事gQ进而想? 应该也有诸如ondragenter、ondragover、ondrop之类的事Ӟ事实上也是有的)Q如果响应这些事Ӟ处理同输入框的交互式拖放? 该就能够解决。因些拖攑֜MSHTML的缺省DropTarget实现中发生,因而当鼠标拖拽到某个输入框上时Q肯定会(x)触发一个ondragover 事gQ而在IHTMLEventObj的辅助下我们能轻村־到相关的HTML ElementQ其它的操作容易进行了。再l心一点,我们q发现IHTMLEventObj2接口有个dataTransfer属性——可以得C? IHTMLDataTransfer的指针,而IHTMLDataTransfer接口正是览器内部用于数据交换的重要手段之一Q看看它的属性就知道? 很有用了Q:(x)</font></div> <blockquote dir="ltr" style="margin-right: 0px;"> <div style="margin: 0in; font-weight: bold; font-size: 10pt;"><font face="Courier New">IHTMLDataTransfer Members</font></div> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font face="Courier New">clearData——Removes one or more data formats from the clipboard through dataTransfer or clipboardData object.</font></div> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font face="Courier New">dropEffect——Sets or retrieves the type of drag-and-drop operation and the type of cursor to display.</font></div> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font face="Courier New">effectAllowed——Sets or retrieves, on the source element, which data transfer operations are allowed for the object.</font></div> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font face="Courier New">getData——Retrieves the data in the specified format from the clipboard through the dataTransfer or clipboardData objects.</font></div> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font face="Courier New">setData——Assigns data in a specified format to the dataTransfer or clipboardData object.</font></div> </blockquote> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New"> </font></div> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New">更进一步,从IHTMLDataTransfer接口q可以访问到IDataObject接口Q在q行Ole拖放Ӟ数据是通过IDataObject接口来传递的。具体用法稍后讨论?/font></div> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New"> </font></div> <div style="margin: 0in; font-weight: bold; font-size: 10pt;"><font face="Courier new" size="3">4、打入MSHTML内部——思\</font></div> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New">? 供鼠标反馈效果与实现GetDropTarget的方法类|有了IHTMLDataTransfer接口Q便可在ondragstart? ondragover事g触发旉过dropEffect属性设|拖拽的效果Q可Ҏ(gu)需要自行设定,不设|的话用默认的效果Q。再者,“?#8221;?#8220;?#8221;? 在MSHTML的缺省实C发生Q我们从IHTMLEventObj的SrcElement卛_得知鼠标所位置的HTML Element是否是输入框?/font></div> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New"> </font></div> <div style="margin: 0in; font-weight: bold; font-size: 10pt;"><font face="Courier new" size="3">5、打入MSHTML内部——实?/font></div> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New">要接收到ondragstart之类的事Ӟ可以采用?/font><a target="_blank" ><font face="Courier New">Internet Explorer ~程qͼ十)响应来自HTML Element的事仉知——几个好用的c?/font></a><font face="Courier New">》中提到的CHtmlObjcdCHtmlElementsc,q在适当的地方连接到DocumentQ示例代码如下所C:(x)</font></div> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New"> </font></div> <blockquote dir="ltr" style="margin-right: 0px;"> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New">HRESULT CHtmlDocument2::OnInvoke(DISPID dispidMember, REFIID riid, LCID lcid, WORD wFlags,</font></div> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font face="Courier New">DISPPARAMS * pdispparams, VARIANT * pvarResult,EXCEPINFO * pexcepinfo, </font></div> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font face="Courier New">UINT * puArgErr)</font></div> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New">{</font></div> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font face="Courier New">......</font></div> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font style="background-color: #808080;" color="#ffffff" face="Courier New">//如果只是要设|鼠标拖拽效果的话,q个事g可以不处?/font></div> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font face="Courier New"><strong> case</strong> DISPID_HTMLELEMENTEVENTS_ONDRAGSTART :</font></div> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font face="Courier New">{</font></div> <div style="margin: 0in 0in 0in 1in; font-size: 10pt;"><font face="Courier New">OnDragStart();</font></div> <div style="margin: 0in 0in 0in 1in; font-size: 10pt;"><font face="Courier New"><strong> break</strong> ;</font></div> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font face="Courier New">}</font></div> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font style="background-color: #808080;" color="#ffffff" face="Courier New">//重点在这?/font></div> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font face="Courier New"><strong> case</strong> DISPID_HTMLELEMENTEVENTS_ONDRAGOVER :</font></div> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font face="Courier New">{</font></div> <div style="margin: 0in 0in 0in 1in; font-size: 10pt;"><font face="Courier New">OnDragOver();</font></div> <div style="margin: 0in 0in 0in 1in; font-size: 10pt;"><font face="Courier New"><strong> break</strong> ;</font></div> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font face="Courier New">}</font></div> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font face="Courier New"><strong> case</strong> DISPID_HTMLELEMENTEVENTS_ONDROP :</font></div> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font face="Courier New">{</font></div> <div style="margin: 0in 0in 0in 1in; font-size: 10pt;"><font face="Courier New">OnDrop();</font></div> <div style="margin: 0in 0in 0in 1in; font-size: 10pt;"><font face="Courier New"><strong> break</strong> ;</font></div> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font face="Courier New">}</font></div> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font face="Courier New">......</font></div> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New">}</font></div> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New"> </font></div> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New"><strong> void</strong> CHtmlDocument2::OnDragOver(<strong> void</strong> )</font></div> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New">{</font></div> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font face="Courier New">SetDragEffect();               <font style="background-color: #808080;" color="#ffffff">//</font><font style="background-color: #808080;" color="#ffffff">讄鼠标拖拽效果</font></font></div> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New">}</font></div> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New"> </font></div> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New"><strong> void</strong> CHtmlDocument2::SetDragEffect(<strong> void</strong> )</font></div> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New">{</font></div> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font face="Courier New">CComQIPtr<IHTMLWindow2>  </font><font face="Courier New">pWindow;</font></div> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font face="Courier New">CComQIPtr<IHTMLEventObj>  </font><font face="Courier New">pEventObj;</font></div> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font face="Courier New">CComQIPtr<IHTMLEventObj2>  </font><font face="Courier New">pEventObj2;</font></div> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font face="Courier New">CComQIPtr<IHTMLElement>  </font><font face="Courier New">pElement;</font></div> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New"> </font></div> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font face="Courier New">HRESULT hr = m_spHtmlObj->get_parentWindow( &pWindow );</font></div> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font face="Courier New">hr = pWindow->get_event( &pEventObj );</font></div> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New"> </font></div> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font style="background-color: #808080;" color="#ffffff" face="Courier New">//ondragover发生时IE的默认行为是“没有鼠标拖拽效果”?/font></div> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font style="background-color: #808080;" color="#ffffff" face="Courier New">//IHTMLEventObj的返回D为false卛_取消该事件的默认行ؓ(f)Q所以执行完下面q句话,拖拽效果出C?/font></div> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font face="Courier New">AllowDisplayDragCursor(pEventObj, FALSE);   </font></div> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New"> </font></div> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font face="Courier New">CComBSTR bstrTagName;</font></div> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font face="Courier New">pEventObj->get_srcElement(&pElement);    <font style="background-color: #808080;" color="#ffffff">//</font><font style="background-color: #808080;" color="#ffffff">获得当前HTML Element</font></font></div> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font face="Courier New">pElement->get_tagName(&bstrTagName);     </font></div> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font face="Courier New"><strong> if</strong> ( IsEditArea(bstrTagName) ) <font style="background-color: #808080;" color="#ffffff">//Ҏ(gu)Tag Name判断是否鼠标位于输入框,以便讄焦点使得光标随鼠标移?/font></font></div> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font face="Courier New">{</font></div> <div style="margin: 0in 0in 0in 1in; font-size: 10pt;"><font face="Courier New">CComQIPtr<IHTMLElement2>  </font><font face="Courier New">pElement2;</font></div> <div style="margin: 0in 0in 0in 1in; font-size: 10pt;"><font face="Courier New"><strong> if</strong> ( SUCCEEDED(pElement->QueryInterface(IID_IHTMLElement2, (void **) &pElement2 )) </font></div> <div style="margin: 0in 0in 0in 1.5in; font-size: 10pt;"><font face="Courier New">&& pElement2 )</font></div> <div style="margin: 0in 0in 0in 1in; font-size: 10pt;"><font face="Courier New">{</font></div> <div style="margin: 0in 0in 0in 1.5in; font-size: 10pt;"><font face="Courier New">pElement2->focus();</font></div> <div style="margin: 0in 0in 0in 1in; font-size: 10pt;"><font face="Courier New">}</font></div> <div style="margin: 0in 0in 0in 1in; font-size: 10pt;"><font style="background-color: #808080;" color="#ffffff" face="Courier New">//默认情况下,当拖拽文档到输入框时Q鼠标会(x)变成拖拽的光标,所以这里用IE的默认行为?/font></div> <div style="margin: 0in 0in 0in 1in; font-size: 10pt;"><font face="Courier New">AllowDisplayDragCursor(pEventObj, TRUE);</font></div> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font face="Courier New">}</font></div> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New">}</font></div> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New"> </font></div> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New">BOOL CHtmlDocument2::IsEditArea(CComBSTR bstrTagName)</font></div> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New">{</font></div> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font face="Courier New"><strong> return</strong> bstrTagName == "INPUT" || bstrTagName == "TEXTAREA";</font></div> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New">}</font></div> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New"> </font></div> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New"><strong> void</strong> CHtmlDocument2::AllowDisplayDragCursor(CComQIPtr<IHTMLEventObj> pEventObj, BOOL bAllow)</font></div> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New">{</font></div> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font face="Courier New">VARIANT v;</font></div> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font face="Courier New">v.vt = VT_BOOL;</font></div> <div style="margin: 0in 0in 0in 1in; font-size: 10pt;"><font face="Courier New"> </font></div> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font face="Courier New">v.boolVal = !bAllow ? VARIANT_FALSE : VARIANT_TRUE;</font></div> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font face="Courier New">pEventObj->put_returnValue(v);</font></div> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New">}</font></div> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New"> </font></div> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New"><strong> void</strong> CHtmlDocument2::OnDrop(<strong> void</strong> )</font></div> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New">{</font></div> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font face="Courier New">CComQIPtr<IHTMLWindow2>  </font><font face="Courier New">pWindow;</font></div> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font face="Courier New">CComQIPtr<IHTMLEventObj>  </font><font face="Courier New">pEventObj;</font></div> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font face="Courier New">CComQIPtr<IHTMLEventObj2>  </font><font face="Courier New">pEventObj2;</font></div> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font face="Courier New">CComQIPtr<IHTMLElement>  </font><font face="Courier New">pElement;</font></div> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font face="Courier New">CComQIPtr<IHTMLDataTransfer>   pdt; <font style="background-color: #808080;" color="#ffffff">//此处演示如何使用IHTMLDataTransfer</font></font></div> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New"> </font></div> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font face="Courier New">HRESULT hr = m_spHtmlObj->get_parentWindow( &pWindow );</font></div> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font face="Courier New">hr = pWindow->get_event( &pEventObj );</font></div> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font face="Courier New">hr = pEventObj->QueryInterface(IID_IHTMLEventObj2, (void **) &pEventObj2 );</font></div> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font face="Courier New">hr = pEventObj2->get_dataTransfer(&pdt);</font></div> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New"> </font></div> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font face="Courier New">CComBSTR bstrFormat = "URL"; <font style="background-color: #808080;" color="#ffffff">//首先试获取URL</font></font></div> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font face="Courier New">VARIANT Data;</font></div> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font face="Courier New">hr = pdt->getData(bstrFormat, &Data);</font></div> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font face="Courier New"><strong> if</strong> ( Data.vt != VT_NULL )</font></div> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font face="Courier New">{     <font style="background-color: #808080;" color="#ffffff">//</font><font style="background-color: #808080;" color="#ffffff">获取成功Q拖攄对象是Url</font></font></div> <div style="margin: 0in 0in 0in 1in; font-size: 10pt;"><font face="Courier New">DoOpenUrl(CString(Data.bstrVal));</font></div> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font face="Courier New">}</font></div> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font face="Courier New">else</font></div> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font face="Courier New">{     <font style="background-color: #808080;" color="#ffffff">//</font><font style="background-color: #808080;" color="#ffffff">否则试获取选中的文?/font></font></div> <div style="margin: 0in 0in 0in 1in; font-size: 10pt;"><font face="Courier New">bstrFormat = "Text";</font></div> <div style="margin: 0in 0in 0in 1in; font-size: 10pt;"><font face="Courier New">hr = pdt->getData(bstrFormat, &Data); </font></div> <div style="margin: 0in 0in 0in 1in; font-size: 10pt;"><font face="Courier New"><strong> if</strong> ( Data.vt != VT_NULL )</font></div> <div style="margin: 0in 0in 0in 1in; font-size: 10pt;"><font face="Courier New">{     <font style="background-color: #808080;" color="#ffffff">//</font><font style="background-color: #808080;" color="#ffffff">获取成功Q拖攄内容是文?/font></font></div> <div style="margin: 0in 0in 0in 1.5in; font-size: 10pt;"><font face="Courier New">CComBSTR bstrTagName;</font></div> <div style="margin: 0in 0in 0in 1.5in; font-size: 10pt;"><font face="Courier New">pEventObj->get_srcElement(&pElement);</font></div> <div style="margin: 0in 0in 0in 1.5in; font-size: 10pt;"><font face="Courier New">pElement->get_tagName(&bstrTagName);</font></div> <div style="margin: 0in 0in 0in 1.5in; font-size: 10pt;"><font face="Courier New"><strong> if</strong> ( IsEditArea(bstrTagName) )</font></div> <div style="margin: 0in 0in 0in 1.5in; font-size: 10pt;"><font face="Courier New">{</font></div> <div style="margin: 0in 0in 0in 2in; font-size: 10pt;"><font style="background-color: #808080;" color="#ffffff" face="Courier New">//Drop target是输入框Q不做Q何操作,由IEq行默认处理</font></div> <div style="margin: 0in 0in 0in 2in; font-size: 10pt;"><font face="Courier New"><strong> return</strong> ;</font></div> <div style="margin: 0in 0in 0in 1.5in; font-size: 10pt;"><font face="Courier New">}</font></div> <div style="margin: 0in 0in 0in 1.5in; font-size: 10pt;"><font face="Courier New"><strong> else</strong> </font></div> <div style="margin: 0in 0in 0in 1.5in; font-size: 10pt;"><font face="Courier New">{     <font style="background-color: #808080;" color="#ffffff">//</font><font style="background-color: #808080;" color="#ffffff">否则我们自己处理文本Q或保存Q或是否链接后打开Q等{?/font></font></div> <div style="margin: 0in 0in 0in 2in; font-size: 10pt;"><font face="Courier New">DoProcessText(CString(Data.bstrVal));</font></div> <div style="margin: 0in 0in 0in 2.5in; font-size: 10pt;"><font face="Courier New">//Process the text</font></div> <div style="margin: 0in 0in 0in 1.5in; font-size: 10pt;"><font face="Courier New">}</font></div> <div style="margin: 0in 0in 0in 1in; font-size: 10pt;"><font face="Courier New">}</font></div> <div style="margin: 0in 0in 0in 1in; font-size: 10pt;"><font face="Courier New"><strong> else</strong> </font></div> <div style="margin: 0in 0in 0in 1in; font-size: 10pt;"><font face="Courier New">{     <font style="background-color: #808080;" color="#ffffff">//</font><font style="background-color: #808080;" color="#ffffff">既不是链接,也不是文本,可认为是来自外部Q如Windows ShellQ的文g拖放</font></font></div> <div style="margin: 0in 0in 0in 1.5in; font-size: 10pt;"><font face="Courier New">DoOnDropFiles(pdt);</font></div> <div style="margin: 0in 0in 0in 1in; font-size: 10pt;"><font face="Courier New">}</font></div> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font face="Courier New">}</font></div> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New">}</font></div> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New"> </font></div> <div style="margin: 0in; font-size: 10pt;"><font style="background-color: #808080;" color="#ffffff" face="Courier New">//演示如何从IHTMLDataTransfer得到IDataObject</font></div> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New"> <p style="margin: 0in; font-size: 10pt; font-family: "Courier New";"><strong> void</strong> CHtmlDocument2::DoOnDropFiles(CComQIPtr<IHTMLDataTransfer> pDataTransfer)</p> </font></div> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New">{</font></div> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font face="Courier New">CComQIPtr<IServiceProvider>  </font><font face="Courier New">psp;</font></div> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font face="Courier New">CComQIPtr<IDataObject>  </font><font face="Courier New">pdo;</font></div> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font face="Courier New"><strong> if</strong> ( FAILED(pDataTransfer->QueryInterface(IID_IServiceProvider, (void **) &psp)) )</font></div> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font face="Courier New">{</font></div> <div style="margin: 0in 0in 0in 1in; font-size: 10pt;"><font face="Courier New"><strong> return</strong> ;</font></div> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font face="Courier New">}</font></div> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font face="Courier New"><strong> if</strong> ( FAILED(psp->QueryService(IID_IDataObject, IID_IDataObject, (void **) &pdo)) )</font></div> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font face="Courier New">{</font></div> <div style="margin: 0in 0in 0in 1in; font-size: 10pt;"><font face="Courier New"><strong> return</strong> ;</font></div> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font face="Courier New">}</font></div> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New"> </font></div> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font face="Courier New">COleDataObject DataObject;</font></div> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font face="Courier New">DataObject.Attach(pdo);</font></div> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font face="Courier New">......</font></div> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New">}</font></div> </blockquote> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New"> </font></div> <div style="margin: 0in; font-weight: bold; font-size: 10pt;"><font face="Courier new" size="3">6、再ơ回到标准方?/font></div> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New">? q通过Event Sink响应|页拖拽的方法已l能够很好地工作Q可?#8220;于完美”了,但仍有两?#8220;?#8221;问题Q第一Q必Mdocument建立q接才能工作Q而徏立连? 的时ZҎ(gu)掌握QMSDN中推荐的位置是DocumentCompleteQ但在NavigateComplete中也可,或者是到 WebBrowser的readystate变ؓ(f)READYSTATE_INTERACTIVE时进行连接)。第二,实现Ҏ(gu)q是略显复杂?/font></div> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New">有没有更单的Ҏ(gu)呢?我决定再ơ对GetDropTargetq行“调研”。所?#8220;t破铁鞋无觅处,得来全不费功?#8221;Q晃了一眼GetDropTargetҎ(gu)的声明后Q灵Z动,我忽然想C办法。事实证明,q是完美的解军_法?/font></div> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New"> </font></div> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New">? 我们再来看看GetDropTarget的声明,其中W一个参数指向MSHTML提供的缺省DropTarget实现Q而第二个参数用以q回应用E序的自 定义DropTarget实现Q如果在GetDropTarget中返回S_OKQMSHTML以应用E序提供的自定义DropTarget替换~省? DropTarget实现?/font></div> <div style="margin: 0in; font-size: 10pt;"><blockquote dir="ltr" style="margin-right: 0px;"> <p style="margin: 0in; font-size: 10pt;">HRESULT<font face="Courier New"> GetDropTarget( IDropTarget *pDropTarget, IDropTarget **ppDropTarget);</font></p> <p style="margin: 0in; font-weight: bold; font-size: 10pt; font-family: 宋体;"><font face="Courier New">参数说明</font></p> <p style="margin: 0in; font-size: 10pt; font-family: "Courier New";"><strong> pDropTarget</strong> </p> <p style="margin: 0in 0in 0in 0.5in; font-size: 10pt;">[in]<font face="Courier New"> Pointer to an IDropTarget interface for the current drop target object supplied by MSHTML. </font></p> <p style="margin: 0in; font-size: 10pt; font-family: "Courier New";"><strong> ppDropTarget</strong> </p> <p style="margin: 0in 0in 0in 0.5in; font-size: 10pt;">[out]<font face="Courier New"> Address of a pointer variable that receives an IDropTarget interface pointer for the alternative drop target object supplied by the host.</font></p> </blockquote></div> <div style="margin: 0in; font-size: 10pt;"> <p style="margin: 0in; font-size: 10pt;"><font face="Courier New">惛_了吗Q解决问题的关键在于第一个参数pDropTarget。相信很多浏览器在处理的时候都忽略掉了W一个参数而只是将自己的实现通过W二个参数告知MSHTMLQ因而丢׃IE~省的行为。既然如此,缺省的IDropTarget接口的指针保存下来,在适当的时候调用,不就能够保留IE的原始拖放行Z吗?</font></p> <p style="margin: 0in; font-size: 10pt;"><font face="Courier New"></font></p> <p style="margin: 0in; font-size: 10pt;"><font face="Courier New"></font></p> <p style="margin: 0in; font-size: 10pt;"><font face="Courier New"></font></p> <p style="margin: 0in; font-size: 10pt;"></p> </div> <div style="margin: 0in; font-weight: bold; font-size: 10pt;"><font face="Courier new" size="3"> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New"> </font></div> <div style="margin: 0in; font-weight: bold; font-size: 10pt;"><font face="Courier new" size="3">7、完实?/font></div> </font></div> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New">完整的代码就不再l出Q我们只列出关键的部分作为示例。假设我们用来实现IDropTarget接口的类叫做CBrowserDropTargetQ?/font></div> <blockquote dir="ltr" style="margin-right: 0px;"> <div style="margin: 0in; font-size: 10pt;"><font style="background-color: #808080;" color="#ffffff" face="Courier New">//构造函敎ͼ传入参数x从GetDropTarget得到的那个pDropTargetQ它是MSHTML的缺省实?/font></div> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New">CBrowserDropTarget::CBrowserDropTarget(IDropTarget *pOrginalDropTarget)</font></div> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New">:  </font><font face="Courier New">m_bDragTextToInputBox(FALSE)</font></div> <div style="margin: 0in 0in 0in 1in; font-size: 10pt;"><font style="background-color: #808080;" color="#ffffff" face="Courier New">//q个布尔变量用来判断是否正在向InputBox拖拽文字</font></div> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New">,  </font><font face="Courier New">m_pOrginalDropTarget(pOrginalDropTarget)</font></div> <div style="margin: 0in 0in 0in 1in; font-size: 10pt;"><font style="background-color: #808080;" color="#ffffff" face="Courier New">//m_pOrginalDropTarget用来保存MSHTML的缺省实?/font></div> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New">{</font></div> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New">}</font></div> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New"> </font></div> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New">STDMETHODIMP CBrowserDropTarget::DragEnter(/* [unique][in] */IDataObject __RPC_FAR *pDataObj,</font></div> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font face="Courier New">/* [in] */ DWORD grfKeyState,</font></div> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font face="Courier New">/* [in] */ POINTL pt,</font></div> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font face="Courier New">/* [out][in] */ DWORD __RPC_FAR *pdwEffect)</font></div> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New">{</font></div> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font style="background-color: #808080;" color="#ffffff" face="Courier New">//调用~省的行?/font></div> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font face="Courier New"><strong> return</strong> m_pOrginalDropTarget->DragEnter(pDataObj, grfKeyState, pt, pdwEffect);</font></div> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New">}</font></div> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New"> </font></div> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New">STDMETHODIMP CBrowserDropTarget::DragOver(/* [in] */ DWORD grfKeyState,</font></div> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font face="Courier New">/* [in] */ POINTL pt,</font></div> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font face="Courier New">/* [out][in] */ DWORD __RPC_FAR *pdwEffect)</font></div> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New">{</font></div> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font style="background-color: #808080;" color="#ffffff" face="Courier New">//在网内拖拽文字时这个值是DROPEFFECT_COPYQ拖拽的文字不属于输入框中)</font></div> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font style="background-color: #808080;" color="#ffffff" face="Courier New">//或DROPEFFECT_COPY | DROPEFFECT_MOVEQ拖拽的文字是输入框中的文字Q?/font></div> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font face="Courier New">DWORD dwTempEffect = *pdwEffect;</font></div> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font face="Courier New"> </font></div> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font style="background-color: #808080;" color="#ffffff" face="Courier New">//接下来调用IE的缺省行?/font></div> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font face="Courier New">HRESULT hr = m_pOrginalDropTarget->DragOver(grfKeyState, pt, pdwEffect);</font></div> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font face="Courier New"> </font></div> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font style="background-color: #808080;" color="#ffffff" face="Courier New">//判断是否是往输入框拖拽文?/font></div> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font face="Courier New">m_bDragTextToInputBox = IsDragTextToInputBox(dwOldEffect, *pdwEffect);</font></div> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font face="Courier New"><strong> if</strong> ( !m_bDragTextToInputBox )</font></div> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font face="Courier New">{</font></div> <div style="margin: 0in 0in 0in 1in; font-size: 10pt;"><font style="background-color: #808080;" color="#ffffff" face="Courier New">//不是往输入框拖拽文字,则用原始的拖拽效果。否则和IE的缺省效果一样——也是没有效果</font></div> <div style="margin: 0in 0in 0in 1in; font-size: 10pt;"><font face="Courier New">*pdwEffect = dwTempEffect;</font></div> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font face="Courier New">}</font></div> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font face="Courier New"><strong> return</strong> S_OK;</font></div> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New">}</font></div> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New"> </font></div> <div style="margin: 0in; font-size: 10pt;"><font style="background-color: #808080;" color="#ffffff" face="Courier New">//Ҏ(gu)调用~省行ؓ(f)前后的Effect值判断是否是往输入框拖拽文?/font></div> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New">BOOL CBrowserDropTarget::IsDragTextToInputBox(DWORD dwOldEffect, DWORD dwNewEffect)</font></div> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New">{</font></div> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font style="background-color: #808080;" color="#ffffff" face="Courier New">//如果是把非输入框中文字往输入框拖动,则dwOldEffect与dwNewEffect相等Q都是DROPEFFECT_COPY</font></div> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font face="Courier New">BOOL bTextSelectionToInputBox = ( dwOldEffect == DROPEFFECT_COPY )</font></div> <div style="margin: 0in 0in 0in 1in; font-size: 10pt;"><font face="Courier New">&& ( dwOldEffect == dwNewEffect );</font></div> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font face="Courier New"> </font></div> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font style="background-color: #808080;" color="#ffffff" face="Courier New">//如果是把文字从一个输入框拖到另一个输入框Q则dwOldEffect为DROPEFFECT_COPY | DROPEFFECT_MOVEQ?/font></div> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font style="background-color: #808080;" color="#ffffff" face="Courier New">//而dwNewEffect的值可能ؓ(f)DROPEFFECT_MOVEQ默认情况)Q也可能为DROPEFFECT_COPYQ按下Ctrl键时Q?/font></div> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font face="Courier New">BOOL bInputBoxToInputBox = ( dwOldEffect == (DROPEFFECT_COPY | DROPEFFECT_MOVE) )</font></div> <div style="margin: 0in 0in 0in 1in; font-size: 10pt;"><font face="Courier New">&& ( dwNewEffect == DROPEFFECT_MOVE || dwNewEffect == DROPEFFECT_COPY );</font></div> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font face="Courier New"> </font></div> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font style="background-color: #808080;" color="#ffffff" face="Courier New">//来自Microsoft Word的拖拽特D一些,dwOldEffect是所有效果的l合?/font></div> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font face="Courier New">BOOL bMSWordToInputBox = </font></div> <div style="margin: 0in 0in 0in 1in; font-size: 10pt;"><font face="Courier New">( dwOldEffect == (DROPEFFECT_COPY | DROPEFFECT_MOVE | DROPEFFECT_LINK) )</font></div> <div style="margin: 0in 0in 0in 1in; font-size: 10pt;"><font face="Courier New">&& ( dwNewEffect == DROPEFFECT_MOVE || dwNewEffect == DROPEFFECT_COPY );</font></div> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font face="Courier New"> </font></div> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font style="background-color: #808080;" color="#ffffff" face="Courier New">//来自Edit Plus的拖拽过也特D一些,dwOldEffect是个负数Q怀疑是Edit Plus的拖拽实现有问题Q?/font></div> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font face="Courier New">BOOL bEditPlusToInputBox = ( dwOldEffect < 0 )</font></div> <div style="margin: 0in 0in 0in 1in; font-size: 10pt;"><font face="Courier New">&& ( dwNewEffect == DROPEFFECT_MOVE || dwNewEffect == DROPEFFECT_COPY );</font></div> <div style="margin: 0in 0in 0in 1in; font-size: 10pt;"><font face="Courier New"> </font></div> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font style="background-color: #808080;" color="#ffffff" face="Courier New">//也许q有些例外,可再d</font></div> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font face="Courier New">......</font></div> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font face="Courier New"><strong> return</strong> bTextSelectionToInputBox || bInputBoxToInputBox || bMSWordToInputBox || bEditPlusToInputBox;</font></div> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New">}</font></div> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New"> </font></div> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New">STDMETHODIMP CBrowserDropTarget::DragLeave()</font></div> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New">{</font></div> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font style="background-color: #808080;" color="#ffffff" face="Courier New">//调用~省的行?/font></div> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font face="Courier New"><strong> return</strong> m_pOrginalDropTarget->DragLeave();</font></div> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New">}</font></div> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New"> </font></div> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New">STDMETHODIMP CBrowserDropTarget::Drop(/* [unique][in] */ IDataObject __RPC_FAR *pDataObj,</font></div> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font face="Courier New">/* [in] */ DWORD grfKeyState,</font></div> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font face="Courier New">/* [in] */ POINTL pt,</font></div> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font face="Courier New">/* [out][in] */ DWORD __RPC_FAR *pdwEffect)</font></div> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New">{</font></div> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font face="Courier New"><strong> if</strong> ( m_bDragTextToInputBox )</font></div> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font face="Courier New">{</font></div> <div style="margin: 0in 0in 0in 1in; font-size: 10pt;"><font style="background-color: #808080;" color="#ffffff" face="Courier New">//是文字拖放,调用IE的缺省行?/font></div> <div style="margin: 0in 0in 0in 1in; font-size: 10pt;"><font face="Courier New">return m_pOrginalDropTarget->Drop(pDataObj, grfKeyState, pt, pdwEffect);</font></div> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font face="Courier New">}</font></div> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New"> </font></div> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font style="background-color: #808080;" color="#ffffff" face="Courier New">//否则是拖N接、图片、文件等Q按常规的IDataObject处理方式</font></div> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font face="Courier New">......</font></div> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font face="Courier New"><strong> return</strong> S_OK;</font></div> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New">}</font></div> </blockquote> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New"> </font></div> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New">xQ我们就得到了一个完的“拖放”的基本框Ӟ它在扩展的同时保留了IE的默认行为:(x)</font></div> <ol style="margin-top: 0in; margin-bottom: 0in; margin-left: 0.5in; direction: ltr; unicode-bidi: embed;" type="1"> <li value="1" style="margin-top: 0px; font-size: 10pt; margin-bottom: 0px; vertical-align: middle;"><font face="Courier New">文字在页面内与输入框之间能够交互拖放?</font></li> <li style="margin-top: 0px; font-size: 10pt; margin-bottom: 0px; vertical-align: middle;" value="2"><font face="Courier New">来自外部的文字与|页输入框之间也能交互拖?</font></li> <li style="margin-top: 0px; font-size: 10pt; margin-bottom: 0px; vertical-align: middle;" value="3"><font face="Courier New">拖拽时能够自动滚动页?</font></li> </ol> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New"> </font></div> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New">其余的功能,如向不同的方向拖拽以完成不同的工作,左键右键拖放执行不同的功能,按住Alt保存文字{等Q可Ҏ(gu)需要自行实玎ͼ不再讨论?/font></div> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New"> <div style="margin: 0in; font-weight: bold; font-size: 10pt;"><font face="Courier new" size="3">8、修?/font></div> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New">今天?a target="_blank" >Stanley Xu</a>聊了几个钟头Q受益匪。根据Stanley的提议,毋须再作是否往输入框拖拽文字的判断Q因为我们需要的只是在IE的缺省行为没有鼠标拖拽效果的时候让它有拖拽效果Q因此只需要简单地判断调用IE~省行ؓ(f)后的Effect值是否ؓ(f)0卛_Q如下:(x)</font></div> <div style="margin: 0in; font-size: 10pt;"> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font style="background-color: #808080;" color="#ffffff" face="Courier New">//判断是否是往输入框拖拽文?/font></div> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font face="Courier New">m_bDragTextToInputBox = *pdwEffect != 0;</font></div> </div> <div style="margin: 0in; font-size: 10pt;">单而直接,当然更重要的是:(x)可用?/div>  </font></div> <div style="margin: 0in; font-weight: bold; font-size: 10pt;"><font face="Courier new" size="3">9、参考资?/font></div> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New">MSDN: <a target="_blank" >IHTMLEventObj Interface</a></font></div> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New">MSDN: <a target="_blank" >IHTMLDataTransfer Interface</a></font></div> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New">?/font><a target="_blank" ><font face="Courier New">Internet Explorer ~程qͼ十)响应来自HTML Element的事仉知——几个好用的c?/font></a><font face="Courier New">?/font></div> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New"> </font></div> <br><br> <p id="TBPingURL">Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=677425</p> <br><img src ="http://m.shnenglu.com/mydriverc/aggbug/28966.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://m.shnenglu.com/mydriverc/" target="_blank">旅?/a> 2007-07-29 15:40 <a href="http://m.shnenglu.com/mydriverc/articles/28966.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Internet Explorer ~程qͼ十)响应来自HTML Element的事仉知——几个好用的c?/title><link>http://m.shnenglu.com/mydriverc/articles/28965.html</link><dc:creator>旅?/dc:creator><author>旅?/author><pubDate>Sun, 29 Jul 2007 07:37:00 GMT</pubDate><guid>http://m.shnenglu.com/mydriverc/articles/28965.html</guid><wfw:comment>http://m.shnenglu.com/mydriverc/comments/28965.html</wfw:comment><comments>http://m.shnenglu.com/mydriverc/articles/28965.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://m.shnenglu.com/mydriverc/comments/commentRss/28965.html</wfw:commentRss><trackback:ping>http://m.shnenglu.com/mydriverc/services/trackbacks/28965.html</trackback:ping><description><![CDATA[<font face="Courier New">键字QHTML Element, Sink</font> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New"> </font></div> <div style="margin: 0in; font-weight: bold; font-size: 10pt;"><font face="Courier New">1、概q?/font></div> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New">实现了对Webbrowser的resuing之后我们便会(x)发现有时候我们还需要处理浏览器中的元素QHTML ElementQ。这U处理包括主动和被动两个斚wQ像?a target="_blank" >FAQQ如何访问WebBrowser的滚动条</a>?/font><font face="Courier New">、?a target="_blank" >FAQQ操U下拉列?/a>?/font><font face="Courier New">、?a target="_blank" >FAQQ两U方法访问多层嵌套的frame</a>?/font><font face="Courier New">{? 文章所演示的就是主动的处理。通常我们从Webbrowser获得一个Web文档接口QIHTMLDocumentxQ,从它出发便可讉K到浏览器所包含 的一切HTML元素。而被动的处理则是在COM技术中UCؓ(f)Sink的技术,我更喜欢的说法是事g通知。当文档的下载进度发生变化时Q我们可以获? ProgressChange通知Q当Webbrowser下蝲完HTML文档Ӟ我们可以获得DocumentComplete的通知Q而当链接被点 击,或图片被拖动Ӟ我们如何获得通知呢?本文希望能够l出部分的答案?/font></div> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New"> </font></div> <div style="margin: 0in; font-weight: bold; font-size: 10pt;"><font face="Courier New">2、HtmlObj Template</font></div> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New">如何Sink一个HTML Elementq不是本文的重点Q其理论我不是太了解Q也懒得L透彻Q所以用现成的库来实现。CodeProject上的一文章?a target="_blank" >CHtmlObj Template</a>》给出的一个模板类CHtmlObj非常好用。下面的例子是针对Html Anchor Element的一个实例化?/font></div> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New"> </font></div> <blockquote dir="ltr" style="margin-right: 0px;"> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New">#include "HtmlObj.h"</font></div> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New"> </font></div> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New">class CHtmlAnchorElement : public CHtmlObj<IHTMLAnchorElement, </font></div> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font face="Courier New">&DIID_HTMLAnchorEvents> </font></div> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New">{</font></div> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New">public:</font></div> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New">CHtmlAnchorElement(CHtmlDocument2* pParentDoc2);</font></div> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New">virtual ~CHtmlAnchorElement();</font></div> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New"> </font></div> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New">virtual HRESULT OnInvoke(DISPID dispidMember,REFIID riid, </font></div> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font face="Courier New">LCID lcid, WORD wFlags,</font></div> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font face="Courier New">DISPPARAMS * pdispparams, VARIANT * pvarResult, </font></div> <div style="margin: 0in 0in 0in 1in; font-size: 10pt;"><font face="Courier New">EXCEPINFO * pexcepinfo, </font></div> <div style="margin: 0in 0in 0in 1in; font-size: 10pt;"><font face="Courier New">UINT * puArgErr);</font></div> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New">};</font></div> <div style="margin: 0in; font-size: 10pt;"><br><font face="Courier New">HRESULT CHtmlAnchorElement::OnInvoke(DISPID dispidMember, </font></div> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font face="Courier New">REFIID riid, LCID lcid, WORD wFlags,</font></div> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font face="Courier New">DISPPARAMS * pdispparams, VARIANT * pvarResult,</font></div> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font face="Courier New">EXCEPINFO * pexcepinfo, </font></div> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font face="Courier New">UINT * puArgErr)</font></div> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New">{</font></div> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New">HRESULT hr = E_NOTIMPL;</font></div> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New">switch(dispidMember)</font></div> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New">{</font></div> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font face="Courier New">case DISPID_HTMLELEMENTEVENTS_ONMOUSEOVER :</font></div> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font face="Courier New">{<font style="background-color: #808080;" color="#ffffff">//当鼠标经q链接时Q我们在q里获得通知</font></font></div> <div style="margin: 0in 0in 0in 1in; font-size: 10pt;"><font face="Courier New">hr = S_OK;</font></div> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font face="Courier New">      // TODO: add code to handle on mouse over events</font></div> <div style="margin: 0in 0in 0in 1in; font-size: 10pt;"><font face="Courier New">break;</font></div> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font face="Courier New">}</font></div> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font face="Courier New">case DISPID_HTMLELEMENTEVENTS_ONMOUSEOUT :</font></div> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font face="Courier New">{<font style="background-color: #808080;" color="#ffffff">//当鼠标从链接上移开Ӟ我们在这里获得通知Q其它的Dispatch ID可根据需要添?/font></font></div> <div style="margin: 0in 0in 0in 1in; font-size: 10pt;"><font face="Courier New">hr = S_OK;</font></div> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font face="Courier New">      // TODO: add code to handle on mouse out events</font></div> <div style="margin: 0in 0in 0in 1in; font-size: 10pt;"><font face="Courier New">break;</font></div> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font face="Courier New">}</font></div> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font face="Courier New">default: </font></div> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font face="Courier New">{</font></div> <div style="margin: 0in 0in 0in 1in; font-size: 10pt;"><font face="Courier New">break;</font></div> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font face="Courier New">}</font></div> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New">}</font></div> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New"> </font></div> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New">return hr;</font></div> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New">}</font></div> </blockquote> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New"> </font></div> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New">? 我们得到某个链接的HTML接口指针Q便可调用CHtmlAnchorElementl承自CHtmlObj的SetSite(IUnknown *pUnkSite)成员函数传入该接口指针。在CHtmlObjcd部用一个智能指针m_spHtmlObj来保存相应的HTML Element接口指针Q所以当上面的ONMOUSEHOVER和ONMOUSEOUT两个事g通知到达Ӟ从m_spHtmlObj可以访? IHTMLAnchorElement的所有成员,如从href获得链接的Url{,此处不再赘述?/font></div> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New"> </font></div> <div style="margin: 0in; font-weight: bold; font-size: 10pt;"><font face="Courier New">3、CHtmlElementsc?/font></div> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New">? 了CHtmlObj之后我们又会(x)发现实践中常怼(x)需要多个相同类型的CHtmlObj。比如包含Frame的网中每个Frame的HTML Document都需要一个CHtmlObj来Sink其事件。所以我们还需要有效地理q些相同cd的CHtmlObj。下面是我写的一个简单的模板c? CHtmlElementsQ它通过CMap来管理多个CHtmlObj对象?/font></div> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New"> </font></div> <blockquote dir="ltr" style="margin-right: 0px;"> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New">template<class THtmlElement> <strong> class</strong> CHtmlElements</font></div> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New">{</font></div> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font face="Courier New"><strong> typedef</strong> CMap<LPDISPATCH, LPDISPATCH, THtmlElement*, THtmlElement*> CMapDispToHtmlElement;</font></div> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font face="Courier New">CMapDispToHtmlElement m_htmlElements;</font></div> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font face="Courier New">BOOL IsSiteConnected( LPDISPATCH pDisp )</font></div> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font face="Courier New">{</font></div> <div style="margin: 0in 0in 0in 1in; font-size: 10pt;"><font face="Courier New">THtmlElement *pElement;</font></div> <div style="margin: 0in 0in 0in 1in; font-size: 10pt;"><font face="Courier New"><strong> return </strong> m_htmlElements.Lookup( pDisp, pElement );</font></div> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font face="Courier New">}</font></div> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New"><strong> public</strong> :</font></div> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font face="Courier New">CHtmlElements(<strong> void</strong> )</font></div> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font face="Courier New">{</font></div> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font face="Courier New">}</font></div> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font face="Courier New">~CHtmlElements(<strong> void</strong> )</font></div> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font face="Courier New">{</font></div> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font face="Courier New">}</font></div> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New"><strong> public</strong> :</font></div> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font face="Courier New"><strong> void</strong> SetSite( LPDISPATCH pDisp )</font></div> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font face="Courier New">{</font></div> <div style="margin: 0in 0in 0in 1in; font-size: 10pt;"><font face="Courier New">if ( IsSiteConnected( pDisp ) ) </font><font style="background-color: #808080;" color="#ffffff" face="Courier New">//查以避免多余的Sink</font></div> <div style="margin: 0in 0in 0in 1in; font-size: 10pt;"><font face="Courier New">{</font></div> <div style="margin: 0in 0in 0in 1.5in; font-size: 10pt;"><font face="Courier New"><strong> return</strong> ;</font></div> <div style="margin: 0in 0in 0in 1in; font-size: 10pt;"><font face="Courier New">}</font></div> <div style="margin: 0in 0in 0in 1in; font-size: 10pt;"><font face="Courier New">THtmlElement *pElement = <strong> new</strong> THtmlElement; <font style="background-color: #808080;" color="#ffffff">//通过模板cd创徏相应的类的实例进行连?/font></font></div> <div style="margin: 0in 0in 0in 1in; font-size: 10pt;"><font face="Courier New">pElement->SetSite( pDisp );</font></div> <div style="margin: 0in 0in 0in 1in; font-size: 10pt;"><font face="Courier New">m_htmlElements.SetAt( pDisp, pElement );</font></div> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font face="Courier New">}</font></div> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New">  <p style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font color="#ffffff"><font style="background-color: #808080;">//在合适的地方调用Clear释放所理的内?/font></font></p> <p style="margin: 0in 0in 0in 0.5in; font-size: 10pt; font-family: "Courier New";">void Clear(void)</p> <p style="margin: 0in 0in 0in 0.5in; font-size: 10pt; font-family: "Courier New";">{</p> <p style="margin: 0in 0in 0in 1in; font-size: 10pt; font-family: "Courier New";">POSITION pos = m_htmlElements.GetStartPosition();</p> <p style="margin: 0in 0in 0in 1in; font-size: 10pt; font-family: "Courier New";">THtmlElement *pElement = NULL;</p> <p style="margin: 0in 0in 0in 1in; font-size: 10pt; font-family: "Courier New";">LPDISPATCH pDisp = NULL;</p> <p style="margin: 0in 0in 0in 1in; font-size: 10pt; font-family: "Courier New";">while (pos != NULL)</p> <p style="margin: 0in 0in 0in 1in; font-size: 10pt; font-family: "Courier New";">{</p> <p style="margin: 0in 0in 0in 1.5in; font-size: 10pt; font-family: "Courier New";">m_htmlElements.GetNextAssoc( pos, pDisp, pElement );</p> <p style="margin: 0in 0in 0in 1.5in; font-size: 10pt; font-family: "Courier New";">m_htmlElements.RemoveKey( pDisp );</p> <p style="margin: 0in 0in 0in 1.5in; font-size: 10pt; font-family: "Courier New";">delete pElement;</p> <p style="margin: 0in 0in 0in 1in; font-size: 10pt; font-family: "Courier New";">}</p> <p style="margin: 0in 0in 0in 0.5in; font-size: 10pt; font-family: "Courier New";">}</p> };</font></div> </blockquote> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New"> </font></div> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New">假设我们有一个象CHtmlAnchorElement那样z自CHtmlObj的类CHtmlDocument2Q用CHtmlElements时这样声明:(x)</font></div> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New"> </font></div> <blockquote dir="ltr" style="margin-right: 0px;"> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New"><strong> typedef</strong> CHtmlElements<CHtmlDocument2> CHtmlDocuments;</font></div> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New"><strong> typedef</strong> CHtmlElements<CHtmlAnchorElement> CHtmlAnchors;</font></div> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New"> </font></div> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New"><strong> class</strong> CMyView : <strong> public</strong> CHtmlView</font></div> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New">{</font></div> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New"><strong> private</strong> :</font></div> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font face="Courier New">CHtmlDocuments m_htmlDocs;</font></div> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font face="Courier New">CHtmlAnchors m_htmlAnchors;</font></div> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New">}</font></div> </blockquote> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New"> </font></div> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New">在DocumentComplete时就可以q样q接到浏览器的文档对象:(x)<br></font></div> <blockquote dir="ltr" style="margin-right: 0px;"> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New"><strong> void</strong> CMyView ::OnDocumentComplete(LPDISPATCH pDisp, LPCTSTR lpszURL)</font></div> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New">{</font></div> <div style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font face="Courier New">m_htmlDocs.SetSite(pDisp);</font></div> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New">}</font></div> </blockquote> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New"> </font></div> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New">? 果想一ơ性连接上文档中所有的Anchor ElementQ可以通过IHTMLDocument2::get_anchors获得包含所有IHTMLAnchorElement接口指针? IHTMLElementCollectionQ再遍历其中的每个元素,分别调用m_htmlAnchors.SetSite卛_。当Ӟ一ơ性的 Sink全部链接可能q不是个好注意,我更愿意在CHtmlDocument2中响应事件再通过其它手段来访问当前位|的HTML Element?/font></div> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New"> </font></div> <div style="margin: 0in; font-weight: bold; font-size: 10pt;"><font face="Courier New">4、结?/font></div> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New">? 应HTML Element的事仉知对于览器编E来说是一个非常强大的手段Q它可以更深入细化地控制览器中的文档及其HTML元素Q实现更为高U的功能Q比如所 谓的“拖放”Q许多多H口览器都提供了该功能Q但实际上没有哪个浏览器完美地实C对URL、文字及囄的拖放)?/font></div> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New"> </font></div> <div style="margin: 0in; font-weight: bold; font-size: 10pt;"><font face="Courier New">5、参考资?/font></div> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New"><a target="_blank" >Codeproject: HtmlObj Template</a></font></div> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New"> </font></div> <div style="margin: 0in; font-size: 10pt;"><font face="Courier New">引用地址Q?a >Internet Explorer ~程qͼ十)响应来自HTML Element的事仉知——几个好用的c?/a>?/font></div> <br><br> <p id="TBPingURL">Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=621961</p> <br><img src ="http://m.shnenglu.com/mydriverc/aggbug/28965.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://m.shnenglu.com/mydriverc/" target="_blank">旅?/a> 2007-07-29 15:37 <a href="http://m.shnenglu.com/mydriverc/articles/28965.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Internet Explorer ~程qͼ?ji))在自q览器中嵌入Google工具?/title><link>http://m.shnenglu.com/mydriverc/articles/28964.html</link><dc:creator>旅?/dc:creator><author>旅?/author><pubDate>Sun, 29 Jul 2007 07:25:00 GMT</pubDate><guid>http://m.shnenglu.com/mydriverc/articles/28964.html</guid><wfw:comment>http://m.shnenglu.com/mydriverc/comments/28964.html</wfw:comment><comments>http://m.shnenglu.com/mydriverc/articles/28964.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://m.shnenglu.com/mydriverc/comments/commentRss/28964.html</wfw:commentRss><trackback:ping>http://m.shnenglu.com/mydriverc/services/trackbacks/28964.html</trackback:ping><description><![CDATA[<p style="margin: 0in; font-size: 10pt;"><font face="Courier New">关键字:(x)Google Toolbar, Explorer Bars, ToolBands, IObjectWithSite, IDeskBand</font></p> <p style="margin: 0in; font-size: 10pt; font-family: "Courier New";"> </p> <p style="margin: 0in; font-weight: bold; font-size: 10pt;">1<font face="Courier New">、概q?/font></p> <p style="margin: 0in; font-size: 10pt;">  Internet Explorer<font face="Courier New">强大而方便的可编E能力和可扩展能力ؓ(f)其抢占浏览器市场可谓是立下了汗马功劳。可~程主要体现两方面:(x)</font></p> <ul style="margin-top: 0in; margin-bottom: 0in; margin-left: 0.5in; direction: ltr; unicode-bidi: embed;" type="disc"> <li style="margin-top: 0px; font-size: 10pt; margin-bottom: 0px; vertical-align: middle;"><font face="Courier New">实现览功能的部分被包装成一个控件——WebBrowser ControlQ开发h员可以在自己的应用程序中嵌入它从而ɽE序h讉KInternet上网늚能力Q同时WebBrowser Control也能够被灉|地自定义以满不同的需要?/font> </li> <li style="margin-top: 0px; font-size: 10pt; margin-bottom: 0px; vertical-align: middle;"><font face="Courier New">可对Microsoft Internet Explorer应用E序本n嵌入的浏览器控g~程Q一般通过BHOQBrowser Helper ObjectQ来实现?/font> </li> </ul> <p style="margin: 0in; font-size: 10pt; font-family: "Courier New";"> </p> <p style="margin: 0in; font-size: 10pt; font-family: 宋体;"><font face="Courier New">  可扩展能力则体现在几个方面:(x)</font></p> <ul style="margin-top: 0in; margin-bottom: 0in; margin-left: 0.5in; direction: ltr; unicode-bidi: embed;" type="disc"> <li style="margin-top: 0px; font-size: 10pt; margin-bottom: 0px; vertical-align: middle;"><font face="Courier New">嵌入式面板型扩展Q包括Explorer BarsQ如收藏夏V搜索、历史等嵌入IEȝ口的大型面板Q? Tool BandsQ如Google Toolbar、MSN Toolbar{嵌入IE的工hQ? 和Desk BandsQ如快速启动这cd入Q务栏的面板,实际上是Explorer外壳的扩展)。这几种面板的编写方法相差无几,不同之处主要在于向系l注册方式的不同?/font> </li> </ul> <p style="margin: 0in; font-size: 10pt; font-family: "Courier New";"> </p> <p style="margin: 0in; font-size: 10pt; font-family: "courier new";" align="center"><img alt="Explorer bars" src="http://blog.csdn.net/images/blog_csdn_net/cathyeagle/32965/o_ExplorerBar.jpg"></p> <p style="margin: 0in; font-size: 10pt; font-family: "Courier New";"> </p> <p style="margin: 0in;" align="center"><font face="Courier new" size="2"><img alt="Tool bands" src="http://blog.csdn.net/images/blog_csdn_net/cathyeagle/32965/o_ToolBand.jpg"></font></p> <p style="margin: 0in;" align="center"><font face="Courier new" size="2"><img alt="Desk band" src="http://blog.csdn.net/images/blog_csdn_net/cathyeagle/32965/o_DeskBand.jpg"></font></p> <p style="margin: 0in; font-size: 10pt; font-family: "Courier New";"> </p> <p style="margin: 0in; font-size: 10pt; font-family: "Courier New";"> </p> <ul style="margin-top: 0in; margin-bottom: 0in; margin-left: 0.5in; direction: ltr; unicode-bidi: embed;" type="disc"> <li style="margin-top: 0px; font-size: 10pt; margin-bottom: 0px; vertical-align: middle;"><font face="Courier New">是参数型扩展Q包括ؓ(f)览器增加上下文菜单(调用脚本Q、ؓ(f)览器主菜单增加菜单Vؓ(f)览?#8220;标准按钮”工具条添加按钮等?/font> </li> <li style="margin-top: 0px; font-size: 10pt; margin-bottom: 0px; vertical-align: middle;"><font face="Courier New">其他扩展Q如文g下蝲的扩展(Custom Download ManagerQ、地址栏扩展(搜烦扩展Q等?/font> </li> </ul> <p style="margin: 0in; font-size: 10pt; font-family: "Courier New";"> </p> <p style="margin: 0in; font-size: 10pt;"><font face="Courier New">  随着IE的发展,各种cd的扩展遍地开花,其中最为引人注目的Q当属地址栏扩展和工具条扩展(几乎成了兵家必争之地Q。本文讨论的主题Q正是工h的扩展?/font></p> <p style="margin: 0in; font-size: 10pt; font-family: "Courier New";"> </p> <p style="margin: 0in; font-weight: bold; font-size: 10pt;">2<font face="Courier New">、问题的提出</font></p> <p style="margin: 0in; font-size: 10pt;"><font face="Courier New">  两个原因促成了Google Toolbar的流行,一是广告窗口的泛滥、二是Google Search。Google“?#8221;Q实则一炚w不简单,没有搜烦引擎的强力支持,Toolbar的用途就大受限制Q地抓住了这两点Q迅速占领了市场?/font></p> <p style="margin: 0in; font-size: 10pt;"><font face="Courier New">  插g的一大好处在于可以不修改ȝ序,只需换一个样子差不多但功能更强的东西可以得整个应用程序功能增强,所以IE不升U大家也觉得Google Toobar来好用。于是利用WebBroser Control~写览器的开发h员就惻I如果能像IE一h持上q这些扩展,不就能把Google Toolbar拿过来用了吗Q其他的事交lGoogledp了。这是我们要讨论的问题Q?#8220;如何在自q览器中嵌入Google Toolbar”?/font></p> <p style="margin: 0in; font-size: 10pt; font-family: "Courier New";"> </p> <p style="margin: 0in; font-weight: bold; font-size: 10pt;">3<font face="Courier New">、分?/font></p> <p style="margin: 0in; font-size: 10pt;"><font face="Courier New">  微Yq未在MSDN中说明如何将Google Toolbarq类IE的工h插g嵌入自己的应用程序,但其ZCOM的设计方法实际上l予了我们这个能力(创徏嵌入式的工具条的Ҏ(gu)q不是本文的重点Q此处略去,有兴的朋友可以参考MSDNQ。我们知道,除了IUnknown接口外,Bands和BarsQ以下简UBand对象Q还需要实C个接口:(x)IObjectWithSiteQIPersistStream和IDeskBand。当用户选择工具条或面板Ӟ其容器(如IE的外xӞ׃(x)调用Band对象的IObjectWithSite::SetSiteҎ(gu)Q该Ҏ(gu)仅需要一个IUnknowncd的指针)Q将自己实现的IUnknown指针传递给Band对象。这是整个插g开始真正激zȝ入口Q也是我们的着手点?/font></p> <p style="margin: 0in; font-size: 10pt;"></p> <p style="margin: 0in; font-size: 10pt;">  MSDN<font face="Courier New">中说刎ͼ一般来_(d)Band对象对于SetSiteҎ(gu)的实现需要完成以下几件事Q?/font></p> <ol> <li><font face="Courier New"><font size="2">如果当前Band对象持有另外的Site指针Q则首先释放该指针?/font></font> </li> <li> <div><font face="Courier New"><font size="2">如果容器向SetSiteҎ(gu)传入的是一个空指针Q则表示要删除该Band对象Q此时SetSiteq回S_OK卛_?/font></font></div> </li> <li> <div><font face="Courier New"><font size="2">如果容器传入的不是空指针Q则需要设|新的SiteQ?</font></font></div> <ol style="margin-top: 0in; margin-bottom: 0in; margin-left: 0.5in; direction: ltr; unicode-bidi: embed;" type="1"> <li value="1" style="margin-top: 0px; font-size: 10pt; margin-bottom: 0px; vertical-align: middle; font-family: "Courier New";"><font face="Courier New">Ҏ(gu)IUnknown指针所指的新Site调用QueryInterface查询得到其IOleWindow接口?/font> </li> <li style="margin-top: 0px; font-size: 10pt; margin-bottom: 0px; vertical-align: middle; font-family: "courier new";" value="2"><font face="Courier New">调用得到的IOleWindow接口的GetWindowҎ(gu)获取父窗口的句柄Q此H口xBand对象的栖w之处)q保存下来。如果以后不?x)再用到IOleWindow接口的话对其调用Release?/font> </li> <li style="margin-top: 0px; font-size: 10pt; margin-bottom: 0px; vertical-align: middle; font-family: "courier new";" value="3"><font face="Courier New">现在可以创徏Band对象的窗口了Q当Ӟ要以W?步得到的H口为父H口来创建,q且该窗口目前只能以不可见状态存在?/font> </li> <li style="margin-top: 0px; font-size: 10pt; margin-bottom: 0px; vertical-align: middle; font-family: "courier new";" value="4"><font face="Courier New">如果Band对象实现了IInputObject接口Q即需要接攉盘输入,则还需要向容器传来的Site查询QQueryInterfaceQIInputObjectSite接口Q此接口指针也需要保存下来?/font> </li> <li style="margin-top: 0px; font-size: 10pt; margin-bottom: 0px; vertical-align: middle; font-family: "courier new";" value="5"><font face="Courier New">上述步骤完成后即可返回S_OKQ否则应q回OLE-defined的error code告知容器什么地方出了错?/font> </li> </ol> </li> </ol> <p style="margin: 0in; font-size: 10pt; font-family: "Courier New";"> </p> <p style="margin: 0in; font-size: 10pt;"><font face="Courier New">  昄Q就我们要讨论的问题而言Q只需换个角度Q编写IE外壳的的角度Q来考虑卛_。首先,我们需要一个IUnknown接口Q即Band对象所需的SiteQ,其次需要一个IInputObjectSite接口Q用以和Band对象的IInputObject接口交互Q处理输入焦点{Uȝ情况。接下来可以通过Band对象的IDeskBand接口来显C、隐藏Band对象了(注意IDeskBand接口z自IDockingWindow接口,后者又z自IOleWindow接口Q?/font></p> <p style="margin: 0in; font-size: 10pt; font-family: "Courier New";"> </p> <p style="margin: 0in; font-weight: bold; font-size: 10pt;">4<font face="Courier New">、实?/font></p> <p style="margin: 0in; font-size: 10pt;"><font face="Courier New">  实现分ؓ(f)两个部分Q其一是一个简单的c,用以模拟IE外壳Q我取名为CIESimulator。其二是一个管理IE扩展的类CIEBandPlugInManagerQ用以管理Band对象的方斚w面?/font></p> <p style="margin: 0in; font-size: 10pt; font-family: "Courier New";"> </p> <blockquote dir="ltr" style="margin-right: 0px;"> <p style="margin: 0in; font-size: 10pt; font-family: "Courier New";">class CIESimulator : public IInputObjectSite</p> <p style="margin: 0in; font-size: 10pt; font-family: "Courier New";">{</p> <p style="margin: 0in; font-size: 10pt; font-family: "Courier New";">private:</p> <p style="margin: 0in 0in 0in 0.5in; font-size: 10pt; font-family: "Courier New";">IWebBrowser2 *m_pwb; <font color="#ffffff"><font style="background-color: #999999;">//<font face="Courier New">保存WebBrowser Control的接口指?/font></font></font></p> <p style="margin: 0in; font-size: 10pt; font-family: "Courier New";">public:</p> <p style="margin: 0in 0in 0in 0.5in; font-size: 10pt; font-family: "Courier New";">CIESimulator(void){};</p> <p style="margin: 0in 0in 0in 0.5in; font-size: 10pt; font-family: "Courier New";">~CIESimulator(void){};</p> <p style="margin: 0in; font-size: 10pt; font-family: "Courier New";"> </p> <p style="margin: 0in 0in 0in 0.5in; font-size: 10pt; font-family: "Courier New";">void SetIWebBrowser2(IWebBrowser2* pwb);</p> <p style="margin: 0in; font-size: 10pt; font-family: "Courier New";"> </p> <p style="margin: 0in 0in 0in 0.5in; font-size: 10pt; font-family: "Courier New";"><font style="background-color: #999999;" color="#ffffff">//IUnknown methods</font></p> <p style="margin: 0in 0in 0in 0.5in; font-size: 10pt; font-family: "Courier New";">STDMETHODIMP QueryInterface(REFIID, void **);</p> <p style="margin: 0in 0in 0in 0.5in; font-size: 10pt; font-family: "Courier New";">STDMETHODIMP_(ULONG) AddRef(void);</p> <p style="margin: 0in 0in 0in 0.5in; font-size: 10pt; font-family: "Courier New";">STDMETHODIMP_(ULONG) Release(void);</p> <p style="margin: 0in; font-size: 10pt; font-family: "Courier New";"> </p> <p style="margin: 0in 0in 0in 0.5in; font-size: 10pt; font-family: "Courier New";"><font style="background-color: #999999;" color="#ffffff">//IInputObjectSite specific methods</font></p> <p style="margin: 0in 0in 0in 0.5in; font-size: 10pt; font-family: "Courier New";">STDMETHOD(OnFocusChangeIS)(THIS_ IUnknown* punkObj, BOOL fSetFocus);</p> <p style="margin: 0in; font-size: 10pt; font-family: "Courier New";">};</p> <p style="margin: 0in; font-size: 10pt; font-family: "Courier New";"> </p> <p style="margin: 0in; font-size: 10pt; font-family: "Courier New";">//IUnknown methods</p> <p style="margin: 0in; font-size: 10pt; font-family: "Courier New";">STDMETHODIMP CIESimulator::QueryInterface( REFIID riid, void **ppv )</p> <p style="margin: 0in; font-size: 10pt; font-family: "Courier New";">{</p> <p style="margin: 0in 0in 0in 0.5in; font-size: 10pt;">if ( riid == IID_IInputObjectSite )  <font style="background-color: #999999;" color="#ffffff">//</font><font style="background-color: #999999;" color="#ffffff" face="Courier New">q个接口需要自己处?/font></p> <p style="margin: 0in 0in 0in 0.5in; font-size: 10pt; font-family: "Courier New";">{</p> <p style="margin: 0in 0in 0in 1in; font-size: 10pt; font-family: "Courier New";">*ppv = static_cast<IInputObjectSite*>(this);</p> <p style="margin: 0in 0in 0in 0.5in; font-size: 10pt; font-family: "Courier New";">}</p> <p style="margin: 0in 0in 0in 0.5in; font-size: 10pt;">else if ( m_pwb )  <font style="background-color: #999999;" color="#ffffff">//</font><font color="#ffffff"><font style="background-color: #999999;"><font face="Courier New">其它的交lWebBrowser Controld?/font></font></font></p> <p style="margin: 0in 0in 0in 0.5in; font-size: 10pt; font-family: "Courier New";">{</p> <p style="margin: 0in 0in 0in 1in; font-size: 10pt; font-family: "Courier New";">m_pwb->QueryInterface( riid, ppv );</p> <p style="margin: 0in 0in 0in 0.5in; font-size: 10pt; font-family: "Courier New";">}</p> <p style="margin: 0in 0in 0in 0.5in; font-size: 10pt; font-family: "Courier New";">return S_OK;</p> <p style="margin: 0in; font-size: 10pt; font-family: "Courier New";">}</p> <p style="margin: 0in; font-size: 10pt; font-family: "Courier New";"> </p> <p style="margin: 0in; font-size: 10pt; font-family: "Courier New";">//IInputObjectSite specific methods</p> <p style="margin: 0in; font-size: 10pt; font-family: "Courier New";">STDMETHODIMP CIESimulator::OnFocusChangeIS(IUnknown* punkObj, BOOL fSetFocus)</p> <p style="margin: 0in; font-size: 10pt; font-family: "Courier New";">{</p> <p style="margin: 0in 0in 0in 0.5in; font-size: 10pt;">return S_OK;  <font style="background-color: #999999;" color="#ffffff">//</font><font style="background-color: #999999;" color="#ffffff" face="Courier New">此处我们单地q回</font></p> <p style="margin: 0in; font-size: 10pt; font-family: "Courier New";">}</p> <p style="margin: 0in; font-size: 10pt; font-family: "Courier New";"> </p> <p style="margin: 0in; font-size: 10pt; font-family: "Courier New";">void CIESimulator::SetIWebBrowser2(IWebBrowser2* pwb)</p> <p style="margin: 0in; font-size: 10pt; font-family: "Courier New";">{</p> <p style="margin: 0in 0in 0in 0.5in; font-size: 10pt; font-family: "Courier New";">m_pwb = pwb;</p> <p style="margin: 0in; font-size: 10pt; font-family: "Courier New";">}</p> </blockquote> <p style="margin: 0in; font-size: 10pt; font-family: "Courier New";"> </p> <p style="margin: 0in; font-size: 10pt;"><font face="Courier New">  注意q里我们q没有实现IOleWindow接口来向B(ti)and对象传递父H口对象Q窗口的宿主可以更改Q所以Band对象创徏的窗口的父窗口我们ƈ不关心,Band对象查询IOleWindow接口的动作实际上是向WebBrowser Control查询Q,而是在稍后的CIEBandPlugInManagercM通过调用IDeskBand的GetWindowҎ(gu)获得Band对象的窗口句柄,再手动将其嵌入我们指定的H口中?/font></p> <p style="margin: 0in; font-size: 10pt; font-family: "Courier New";"> </p> <p style="margin: 0in; font-size: 10pt;"><font face="Courier New">  首先我们定义一个结构用以保存Band的信息:(x)</font></p> <blockquote dir="ltr" style="margin-right: 0px;"> <p style="margin: 0in; font-size: 10pt; font-family: "Courier New";">enum eBANDTYPE</p> <p style="margin: 0in; font-size: 10pt; font-family: "Courier New";">{</p> <p style="margin: 0in 0in 0in 0.5in; font-size: 10pt; font-family: "Courier New";">btVertical = 0,</p> <p style="margin: 0in 0in 0in 0.5in; font-size: 10pt; font-family: "Courier New";">btHorizontal = 1</p> <p style="margin: 0in; font-size: 10pt; font-family: "Courier New";">};</p> <p style="margin: 0in; font-size: 10pt; font-family: "Courier New";"> </p> <p style="margin: 0in; font-size: 10pt; font-family: "Courier New";">enum eBANDSTATE</p> <p style="margin: 0in; font-size: 10pt; font-family: "Courier New";">{</p> <p style="margin: 0in 0in 0in 0.5in; font-size: 10pt; font-family: "Courier New";">bsUnInitialized = -1,</p> <p style="margin: 0in 0in 0in 0.5in; font-size: 10pt; font-family: "Courier New";">bsVisible = 0,</p> <p style="margin: 0in 0in 0in 0.5in; font-size: 10pt; font-family: "Courier New";">bsInVisible = 1,</p> <p style="margin: 0in 0in 0in 0.5in; font-size: 10pt; font-family: "Courier New";">bsUnLoaded = 2</p> <p style="margin: 0in; font-size: 10pt; font-family: "Courier New";">};</p> <p style="margin: 0in; font-size: 10pt; font-family: "Courier New";"> </p> <p style="margin: 0in; font-size: 10pt; font-family: "Courier New";">typedef struct tagIEBANDINFO</p> <p style="margin: 0in; font-size: 10pt; font-family: "Courier New";">{</p> <p style="margin: 0in 0in 0in 0.5in; font-size: 10pt; font-family: "Courier New";">char</p> <p style="margin: 0in 0in 0in 1in; font-size: 10pt; font-family: "Courier New";"> </p> <p style="margin: 0in 0in 0in 1.5in; font-size: 10pt; font-family: "Courier New";">szCLSID[39];</p> <p style="margin: 0in 0in 0in 0.5in; font-size: 10pt; font-family: "Courier New";">char</p> <p style="margin: 0in 0in 0in 1in; font-size: 10pt; font-family: "Courier New";"> </p> <p style="margin: 0in 0in 0in 1.5in; font-size: 10pt; font-family: "Courier New";">szName[MAX_PATH];</p> <p style="margin: 0in 0in 0in 0.5in; font-size: 10pt; font-family: "Courier New";">IUnknown</p> <p style="margin: 0in 0in 0in 1in; font-size: 10pt; font-family: "Courier New";">*puk;</p> <p style="margin: 0in 0in 0in 0.5in; font-size: 10pt; font-family: "Courier New";">HWND</p> <p style="margin: 0in 0in 0in 1in; font-size: 10pt; font-family: "Courier New";"> </p> <p style="margin: 0in 0in 0in 1.5in; font-size: 10pt; font-family: "Courier New";">hBand;</p> <p style="margin: 0in 0in 0in 0.5in; font-size: 10pt; font-family: "Courier New";">UINT</p> <p style="margin: 0in 0in 0in 1in; font-size: 10pt; font-family: "Courier New";"> </p> <p style="margin: 0in 0in 0in 1.5in; font-size: 10pt; font-family: "Courier New";">uMinHeight;</p> <p style="margin: 0in 0in 0in 0.5in; font-size: 10pt; font-family: "Courier New";">UINT</p> <p style="margin: 0in 0in 0in 1in; font-size: 10pt; font-family: "Courier New";"> </p> <p style="margin: 0in 0in 0in 1.5in; font-size: 10pt; font-family: "Courier New";">uBandID;</p> <p style="margin: 0in 0in 0in 0.5in; font-size: 10pt; font-family: "Courier New";">eBANDTYPE</p> <p style="margin: 0in 0in 0in 1in; font-size: 10pt; font-family: "Courier New";">eBandType;</p> <p style="margin: 0in 0in 0in 0.5in; font-size: 10pt; font-family: "Courier New";">eBANDSTATE</p> <p style="margin: 0in 0in 0in 1in; font-size: 10pt; font-family: "Courier New";">eBandState;</p> <p style="margin: 0in; font-size: 10pt; font-family: "Courier New";">} IEBANDINFO, *LPIEBANDINFO;</p> </blockquote> <p style="margin: 0in; font-size: 10pt; font-family: "Courier New";"> </p> <p style="margin: 0in; font-size: 10pt;"><font face="Courier New">  再用一个函数来获取所有Band的信息(以下代码为示例,具体实现是可从注册表把所有Band的信息一一dQ?/font></p> <blockquote dir="ltr" style="margin-right: 0px;"> <p style="margin: 0in; font-size: 10pt; font-family: "Courier New";">void CIEBandPlugInManager::GetAllBandCLSID(void)</p> <p style="margin: 0in; font-size: 10pt; font-family: "Courier New";">{</p> <p style="margin: 0in 0in 0in 0.5in; font-size: 10pt; font-family: "Courier New";">LPIEBANDINFO pIEBandInfo;</p> <p style="margin: 0in 0in 0in 0.5in; font-size: 10pt; font-family: "Courier New";"> </p> <p style="margin: 0in 0in 0in 0.5in; font-size: 10pt; font-family: "Courier New";">pIEBandInfo = new IEBANDINFO();</p> <p style="margin: 0in 0in 0in 0.5in; font-size: 10pt; font-family: "Courier New";">strcpy( pIEBandInfo->szCLSID, "{2318C2B1-4965-11d4-9B18-009027A5CD4F}\0");  <font style="background-color: #999999;" color="#ffffff">//Google Toolbar的CLSID</font></p> <p style="margin: 0in 0in 0in 0.5in; font-size: 10pt; font-family: "Courier New";">strcpy( pIEBandInfo->szName, GetDisplayName(pIEBandInfo->szCLSID) );</p> <p style="margin: 0in 0in 0in 0.5in; font-size: 10pt; font-family: "Courier New";">pIEBandInfo->uMinHeight = 22;</p> <p style="margin: 0in 0in 0in 0.5in; font-size: 10pt; font-family: "Courier New";">pIEBandInfo->uBandID = m_BandCtrlID++;</p> <p style="margin: 0in 0in 0in 0.5in; font-size: 10pt; font-family: "Courier New";">pIEBandInfo->eBandType = btHorizontal;</p> <p style="margin: 0in 0in 0in 0.5in; font-size: 10pt; font-family: "Courier New";">pIEBandInfo->eBandState = bsUnInitialized;</p> <p style="margin: 0in 0in 0in 0.5in; font-size: 10pt;">m_oaBand.Add( (CObject*)pIEBandInfo );<font color="#ffffff"><font style="background-color: #999999;">//m_oaBand<font face="Courier New">是一个CObArray</font></font></font></p> <p style="margin: 0in; font-size: 10pt; font-family: 宋体;"><font face="Courier New">?/font></p> <p style="margin: 0in; font-size: 10pt; font-family: "Courier New";"> </p> <p style="margin: 0in; font-size: 10pt;"><font color="#ffffff"><font style="background-color: #999999;">//Ҏ(gu)CLSID<font face="Courier New">从注册表获取Band的名U?/font></font></font></p> <p style="margin: 0in; font-size: 10pt; font-family: "Courier New";">CString CIEBandPlugInManager::GetDisplayName(CString strCLSID)</p> <p style="margin: 0in; font-size: 10pt; font-family: "Courier New";">{</p> <p style="margin: 0in 0in 0in 0.5in; font-size: 10pt; font-family: "Courier New";">TCHAR</p> <p style="margin: 0in 0in 0in 1in; font-size: 10pt; font-family: "Courier New";"> </p> <p style="margin: 0in 0in 0in 1.5in; font-size: 10pt; font-family: "Courier New";">sz[MAX_PATH];</p> <p style="margin: 0in 0in 0in 0.5in; font-size: 10pt; font-family: "Courier New";">HKEY</p> <p style="margin: 0in 0in 0in 1in; font-size: 10pt; font-family: "Courier New";"> </p> <p style="margin: 0in 0in 0in 1.5in; font-size: 10pt; font-family: "Courier New";">hKey;</p> <p style="margin: 0in 0in 0in 0.5in; font-size: 10pt; font-family: "Courier New";">DWORD</p> <p style="margin: 0in 0in 0in 1in; font-size: 10pt; font-family: "Courier New";"> </p> <p style="margin: 0in 0in 0in 1.5in; font-size: 10pt; font-family: "Courier New";">dwSize;</p> <p style="margin: 0in; font-size: 10pt; font-family: "Courier New";"> </p> <p style="margin: 0in 0in 0in 0.5in; font-size: 10pt; font-family: "Courier New";">strCLSID = "CLSID\\" + strCLSID;</p> <p style="margin: 0in 0in 0in 0.5in; font-size: 10pt; font-family: "Courier New";">if(RegOpenKey(HKEY_CLASSES_ROOT, strCLSID, &hKey) != ERROR_SUCCESS)</p> <p style="margin: 0in 0in 0in 0.5in; font-size: 10pt; font-family: "Courier New";">{</p> <p style="margin: 0in 0in 0in 1in; font-size: 10pt; font-family: "Courier New";">return _T("");</p> <p style="margin: 0in 0in 0in 0.5in; font-size: 10pt; font-family: "Courier New";">}</p> <p style="margin: 0in; font-size: 10pt; font-family: "Courier New";"> </p> <p style="margin: 0in 0in 0in 0.5in; font-size: 10pt; font-family: "Courier New";">RegQueryValueEx(hKey, NULL, NULL, NULL, (LPBYTE)sz, &dwSize);</p> <p style="margin: 0in 0in 0in 0.5in; font-size: 10pt; font-family: "Courier New";">RegCloseKey(hKey);</p> <p style="margin: 0in; font-size: 10pt; font-family: "Courier New";"> </p> <p style="margin: 0in 0in 0in 0.5in; font-size: 10pt; font-family: "Courier New";">return sz;</p> <p style="margin: 0in; font-size: 10pt; font-family: "Courier New";">}</p> <p style="margin: 0in; font-size: 10pt; font-family: "Courier New";"> </p> <p style="margin: 0in; font-size: 10pt;"><font color="#ffffff"><font style="background-color: #999999;">//<font face="Courier New">通过Band的CLSIDȀzBand</font></font></font></p> <p style="margin: 0in; font-size: 10pt; font-family: "Courier New";">bool CIEBandPlugInManager::ActivateBand( CString strCLSID )</p> <p style="margin: 0in; font-size: 10pt; font-family: "Courier New";">{</p> <p style="margin: 0in 0in 0in 0.5in; font-size: 10pt;">LPIEBANDINFO pIEBandInfo = GetBandInfo( strCLSID ); <font style="background-color: #999999;" color="#ffffff">//</font><font color="#ffffff"><font style="background-color: #999999;"><font face="Courier New">从m_oaBand中找到符合条件的Band的信?/font></font></font></p> <p style="margin: 0in 0in 0in 0.5in; font-size: 10pt; font-family: "Courier New";">if ( !pIEBandInfo )</p> <p style="margin: 0in 0in 0in 0.5in; font-size: 10pt; font-family: "Courier New";">{</p> <p style="margin: 0in 0in 0in 1in; font-size: 10pt; font-family: "Courier New";">return false;</p> <p style="margin: 0in 0in 0in 0.5in; font-size: 10pt; font-family: "Courier New";">}</p> <p style="margin: 0in; font-size: 10pt; font-family: "Courier New";"> </p> <p style="margin: 0in 0in 0in 0.5in; font-size: 10pt; font-family: "Courier New";">WCHAR wsz[MAX_PATH];  </p> <p style="margin: 0in 0in 0in 0.5in; font-size: 10pt; font-family: "Courier New";">::MultiByteToWideChar(CP_ACP, 0, strCLSID, -1, wsz, MAX_PATH);</p> <p style="margin: 0in; font-size: 10pt; font-family: "Courier New";"> </p> <p style="margin: 0in 0in 0in 0.5in; font-size: 10pt; font-family: "Courier New";">CLSID</p> <p style="margin: 0in 0in 0in 1in; font-size: 10pt; font-family: "Courier New";">clsid;</p> <p style="margin: 0in 0in 0in 0.5in; font-size: 10pt; font-family: "Courier New";">HRESULT hr2 = CLSIDFromString( wsz, &clsid);</p> <p style="margin: 0in 0in 0in 0.5in; font-size: 10pt; font-family: "Courier New";">if ( hr2 != NOERROR )</p> <p style="margin: 0in 0in 0in 1in; font-size: 10pt; font-family: "Courier New";">return false;</p> <p style="margin: 0in; font-size: 10pt; font-family: "Courier New";"> </p> <p style="margin: 0in 0in 0in 0.5in; font-size: 10pt; font-family: "Courier New";">HRESULT hr = ::CoCreateInstance(clsid, NULL, LSCTX_INPROC_SERVER, IID_IUnknown, (void**)&pIEBandInfo->puk); <font color="#ffffff"><font style="background-color: #999999;">//<font face="Courier New">创徏Band对象的实?/font></font></font></p> <p style="margin: 0in 0in 0in 0.5in; font-size: 10pt; font-family: "Courier New";">IUnknown* puk = pIEBandInfo->puk;</p> <p style="margin: 0in 0in 0in 0.5in; font-size: 10pt; font-family: "Courier New";">if (FAILED(hr))</p> <p style="margin: 0in 0in 0in 1in; font-size: 10pt; font-family: "Courier New";">return false;</p> <p style="margin: 0in; font-size: 10pt; font-family: "Courier New";"> </p> <p style="margin: 0in 0in 0in 0.5in; font-size: 10pt;">DoQueryBandInfo( pIEBandInfo );  <font style="background-color: #999999;" color="#ffffff">//</font><font color="#ffffff"><font style="background-color: #999999;"><font face="Courier New">查询Band对象实例的信?/font></font></font></p> <p style="margin: 0in; font-size: 10pt; font-family: "Courier New";"> </p> <p style="margin: 0in 0in 0in 0.5in; font-size: 10pt; font-family: "Courier New";">switch( pIEBandInfo->eBandType ) </p> <p style="margin: 0in 0in 0in 0.5in; font-size: 10pt; font-family: "Courier New";">{</p> <p style="margin: 0in 0in 0in 0.5in; font-size: 10pt; font-family: "Courier New";">case btVertical:</p> <p style="margin: 0in 0in 0in 1in; font-size: 10pt; font-family: "Courier New";">break;</p> <p style="margin: 0in 0in 0in 1.5in; font-size: 10pt;"><font color="#ffffff"><font style="background-color: #999999;">//我们<font face="Courier New">不处理Vertical的面?/font></font></font></p> <p style="margin: 0in 0in 0in 0.5in; font-size: 10pt; font-family: "Courier New";">case btHorizontal:</p> <p style="margin: 0in 0in 0in 0.5in; font-size: 10pt; font-family: "Courier New";">{</p> <p style="margin: 0in 0in 0in 1in; font-size: 10pt;">g_pMainFrame->m_wndReBar.AddBar2( pIEBandInfo->hBand, pIEBandInfo->uBandID, pIEBandInfo->uMinHeight, 0, 0); <font style="background-color: #999999;" color="#ffffff">//</font><font color="#ffffff"><font style="background-color: #999999;"><font face="Courier New">Band嵌入ȝ口的ReBar?/font></font></font></p> <p style="margin: 0in 0in 0in 1in; font-size: 10pt; font-family: "Courier New";"> </p> <p style="margin: 0in 0in 0in 1in; font-size: 10pt; font-family: "Courier New";">REBARBANDINFO rbbi;</p> <p style="margin: 0in 0in 0in 1in; font-size: 10pt; font-family: "Courier New";">rbbi.cbSize = sizeof(rbbi);</p> <p style="margin: 0in 0in 0in 1in; font-size: 10pt; font-family: "Courier New";">rbbi.fMask = RBBIM_CHILDSIZE | RBBIM_IDEALSIZE | RBBIM_SIZE;</p> <p style="margin: 0in 0in 0in 1in; font-size: 10pt; font-family: "Courier New";">rbbi.cxMinChild = 0;</p> <p style="margin: 0in 0in 0in 1in; font-size: 10pt; font-family: "Courier New";">rbbi.cyMinChild = pIEBandInfo->uMinHeight;</p> <p style="margin: 0in 0in 0in 1in; font-size: 10pt; font-family: "Courier New";">rbbi.cx = rbbi.cxIdeal = 250;</p> <p style="margin: 0in 0in 0in 1in; font-size: 10pt; font-family: "Courier New";">UINT nCount = g_pMainFrame->m_wndReBar.GetReBarCtrl().GetBandCount();</p> <p style="margin: 0in 0in 0in 1in; font-size: 10pt; font-family: "Courier New";">g_pMainFrame->m_wndReBar.GetReBarCtrl().SetBandInfo(nCount-1, &rbbi); </p> <p style="margin: 0in 0in 0in 1in; font-size: 10pt; font-family: "Courier New";">break;</p> <p style="margin: 0in 0in 0in 0.5in; font-size: 10pt; font-family: "Courier New";">}</p> <p style="margin: 0in 0in 0in 0.5in; font-size: 10pt; font-family: "Courier New";">default:</p> <p style="margin: 0in 0in 0in 1in; font-size: 10pt; font-family: "Courier New";">break;</p> <p style="margin: 0in 0in 0in 0.5in; font-size: 10pt; font-family: "Courier New";">} </p> <p style="margin: 0in 0in 0in 0.5in; font-size: 10pt; font-family: "Courier New";">pIEBandInfo->eBandState = bsVisible;</p> <p style="margin: 0in 0in 0in 0.5in; font-size: 10pt; font-family: "Courier New";">return true;</p> <p style="margin: 0in; font-size: 10pt; font-family: "Courier New";">}</p> <p style="margin: 0in; font-size: 10pt; font-family: "Courier New";"> </p> <p style="margin: 0in; font-size: 10pt;"><font color="#ffffff"><font style="background-color: #999999;">//<font face="Courier New">查询Band对象实例的信?/font></font></font></p> <p style="margin: 0in; font-size: 10pt; font-family: "Courier New";">void CIEBandPlugInManager::DoQueryBandInfo(LPIEBANDINFO pIEBandInfo)</p> <p style="margin: 0in; font-size: 10pt; font-family: "Courier New";">{</p> <p style="margin: 0in 0in 0in 0.5in; font-size: 10pt; font-family: "Courier New";">IObjectWithSite *pOWS;</p> <p style="margin: 0in 0in 0in 0.5in; font-size: 10pt;"><font color="#ffffff"><font style="background-color: #999999;">//<font face="Courier New">查询IObjectWithSite接口</font></font></font></p> <p style="margin: 0in 0in 0in 0.5in; font-size: 10pt; font-family: "Courier New";">HRESULT hr = pIEBandInfo->puk->QueryInterface(IID_IObjectWithSite, (void**)&pOWS);</p> <p style="margin: 0in 0in 0in 0.5in; font-size: 10pt; font-family: "Courier New";">if (SUCCEEDED(hr))</p> <p style="margin: 0in 0in 0in 0.5in; font-size: 10pt;">{     //<font face="Courier New">讄Site</font></p> <p style="margin: 0in 0in 0in 1in; font-size: 10pt;">pOWS->SetSite( (IUnknown *)&m_IESimulator ); <font style="background-color: #999999;" color="#ffffff">//</font><font color="#ffffff"><font style="background-color: #999999;">m_IESimulator<font face="Courier New">是CIESimulator的一个实例对象,对Band对象而言Q它?yu)像IE</font></font></font></p> <p style="margin: 0in 0in 0in 0.5in; font-size: 10pt; font-family: "Courier New";">}</p> <p style="margin: 0in; font-size: 10pt; font-family: "Courier New";"> </p> <p style="margin: 0in 0in 0in 0.5in; font-size: 10pt; font-family: "Courier New";">IDeskBand *pdb;</p> <p style="margin: 0in 0in 0in 0.5in; font-size: 10pt; font-family: "Courier New";">hr = pIEBandInfo->puk->QueryInterface(IID_IDeskBand, (void**)&pdb);</p> <p style="margin: 0in 0in 0in 0.5in; font-size: 10pt; font-family: "Courier New";">if (SUCCEEDED(hr))</p> <p style="margin: 0in 0in 0in 0.5in; font-size: 10pt;">{     <font style="background-color: #999999;" color="#ffffff">//</font><font color="#ffffff"><font style="background-color: #999999;"><font face="Courier New">查询得到Band对象H口的句柄,E候通过该句柄将Band对象的窗口嵌入我们指定的H口</font></font></font></p> <p style="margin: 0in 0in 0in 1in; font-size: 10pt; font-family: "Courier New";">pdb->GetWindow(&pIEBandInfo->hBand);</p> <p style="margin: 0in 0in 0in 0.5in; font-size: 10pt; font-family: "Courier New";">}</p> <p style="margin: 0in; font-size: 10pt; font-family: "Courier New";"> </p> <p style="margin: 0in 0in 0in 0.5in; font-size: 10pt;">ShowBand(pIEBandInfo, TRUE);<font color="#ffffff"><font style="background-color: #999999;">//<font face="Courier New">昄Band</font></font></font></p> <p style="margin: 0in; font-size: 10pt; font-family: "Courier New";">}</p> <p style="margin: 0in; font-size: 10pt; font-family: "Courier New";"> </p> <p style="margin: 0in; font-size: 10pt; font-family: "Courier New";">bool CIEBandPlugInManager::ShowBand(LPIEBANDINFO pIEBandInfo, bool bShow)</p> <p style="margin: 0in; font-size: 10pt; font-family: "Courier New";">{</p> <p style="margin: 0in 0in 0in 0.5in; font-size: 10pt; font-family: "Courier New";">IDockingWindow *pdw;</p> <p style="margin: 0in 0in 0in 0.5in; font-size: 10pt; font-family: "Courier New";">HRESULT hr = pIEBandInfo->puk->QueryInterface(IID_IDockingWindow, (void**)&pdw);</p> <p style="margin: 0in 0in 0in 0.5in; font-size: 10pt; font-family: "Courier New";">if (SUCCEEDED(hr))</p> <p style="margin: 0in 0in 0in 0.5in; font-size: 10pt; font-family: "Courier New";">{</p> <p style="margin: 0in 0in 0in 1in; font-size: 10pt; font-family: "Courier New";">pdw->ShowDW(bShow);</p> <p style="margin: 0in 0in 0in 0.5in; font-size: 10pt; font-family: "Courier New";">}</p> <p style="margin: 0in 0in 0in 0.5in; font-size: 10pt; font-family: "Courier New";">else</p> <p style="margin: 0in 0in 0in 0.5in; font-size: 10pt; font-family: "Courier New";">{</p> <p style="margin: 0in 0in 0in 1in; font-size: 10pt; font-family: "Courier New";">return false;</p> <p style="margin: 0in 0in 0in 0.5in; font-size: 10pt; font-family: "Courier New";">}</p> <p style="margin: 0in 0in 0in 0.5in; font-size: 10pt; font-family: "Courier New";">return true;</p> <p style="margin: 0in; font-size: 10pt; font-family: "Courier New";">}</p> </blockquote> <p style="margin: 0in; font-size: 10pt; font-family: "Courier New";"> </p> <p style="margin: 0in; font-size: 10pt;"><font face="Courier New">  下面是我试的一个截图,Google的搜索、广告窗口拦截均可正常工作?/font></p> <p style="margin: 0in;" align="center"><font face="Courier new" size="2"><img alt="嵌入Google toolbar演示" src="http://blog.csdn.net/images/blog_csdn_net/cathyeagle/32965/o_EmbedGoogleToolbarSnap.jpg"></font></p> <p style="margin: 0in; font-size: 10pt; font-family: "Courier New";"> </p> <p style="margin: 0in; font-weight: bold; font-size: 10pt;">5<font face="Courier New">、ȝ</font></p> <p style="margin: 0in; font-size: 10pt;"><font face="Courier New">  上述的原理看来很单,但具体实现的时候仍焉要作较多的测试和考虑QBand对象的管理和~存、接口的AddRef和Release{。时间有限,代码也很乱,不过只要原理交待清楚Q相信会(x)Ҏ(gu)兴趣的朋友有所帮助?/font></p> <p style="margin: 0in; font-size: 10pt; font-family: "Courier New";"> </p> <p style="margin: 0in; font-weight: bold; font-size: 10pt;">6<font face="Courier New">、参考资?/font></p> <p style="margin: 0in; font-size: 10pt;">MSDN:<font face="Courier New">?font face="Courier New">Creating Custom Explorer Bars, Tool Bands, and Desk Bands</font>?/font></p> <p style="margin: 0in; font-size: 10pt; font-family: "Courier New";"> </p> <p style="margin: 0in; font-size: 10pt; font-family: "Courier New";">引用地址Q?a >Internet Explorer~程qͼ?ji))在自q览器中嵌入Google工具?/a>?/p> <br><br> <p id="TBPingURL">Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=550698</p> <br><img src ="http://m.shnenglu.com/mydriverc/aggbug/28964.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://m.shnenglu.com/mydriverc/" target="_blank">旅?/a> 2007-07-29 15:25 <a href="http://m.shnenglu.com/mydriverc/articles/28964.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Internet Explorer ~程qͼ八)实现览历史菜单http://m.shnenglu.com/mydriverc/articles/28963.html旅?/dc:creator>旅?/author>Sun, 29 Jul 2007 07:22:00 GMThttp://m.shnenglu.com/mydriverc/articles/28963.htmlhttp://m.shnenglu.com/mydriverc/comments/28963.htmlhttp://m.shnenglu.com/mydriverc/articles/28963.html#Feedback0http://m.shnenglu.com/mydriverc/comments/commentRss/28963.htmlhttp://m.shnenglu.com/mydriverc/services/trackbacks/28963.html关键字:(x)ITravelLogStg, IEnumTravelLogEntry, ITravelLogEntry

 

1、概q?/p>

Internet Explorer的浏览历史菜单在4.0版本开始出玎ͼ但直?.5之前Q微软都未公布用于访问浏览历史的COM接口Q如今已是IE6.0大行光的年代,用于讉K览历史的接口也早已公布多时Q本文的目的则是试图抛砖引玉Q简单介l用于访问浏览历史的Travel Log接口Qƈ用一个小的cCIETravelLog来实现对Travel Log的封装?/p>

 

2、IOmHistory接口

在早些时候的MSDN中,我们能够查阅到关于浏览历史的接口仅有IOmHistoryQ而该接口实际上对应的是浏览器中可以通过脚本讉K?#8220;history”对象。对?#8220;history”对象QMSDN中是q样说的Q?/p>

 

For security reasons, the history object does not expose the actual URLs in the browser history. It does allow navigation through the browser history by exposing the back, forward, and go methods. A particular document in the browser history can be identified as an index relative to the current page. For example, specifying -1 as a parameter for the go method is the equivalent of clicking the Back button.

 

This object is available in script as of Microsoft Internet Explorer 3.0.

 

即ؓ(f)了安全的原因QIOmHistory接口仅提供了有限的几个方法来完成在浏览器中前q、后退{操作,q没有提供访问历史列表Url的能力。这也难怪,该接口在IE 3.0时代已经存在Q而当时IEq不成熟Q可~程能力也不甚强大。一直到IE 4.0通过与Windows 98捆绑销售一l天下之后,相关的文档才逐渐丰富Q多H口览器等ZInternet Explorer/WebBrowser Control的应用Y件也才铺天盖地开来。但在IE 5.5接口公布之前Q要完全模拟IE的Travel Log行ؓ(f)Qƈ不是一件容易的事。最Ҏ(gu)惛_的方法就是在BeforeNavigate、DocumentComplete{事件发生之时记?修改Urlq加以保存(我在早些时候也q样做过Q,但是效果不甚理想Q尤其是览包含Frame的网|Q处理更是麻烦。当Ӟ要完全模拟亦非难事,只不q开发h员都知道微Y公布接口是早晚的事,所以也没有大力气在模拟IE的Travel Log行ؓ(f)上?/p>

 

3、Travel Log?/p>

Internet Explorer 5.5推出以后QTravel Log接口也就开始出现在MSDN中,它是专门为OLE嵌入WebBrowser Control的应用程序设计的Q其目的?#8220;提高和加强用L(fng)讉K日志体验”Qimprove and enhance the user's travel log experienceQ。事实上Q稍后我?x)提刎ͼTravel Log接口正日益成为应用程序中的重要接口之一?/p>

微Y公布的Travel Log共包含三个接口:(x)ITravelLogStg, IEnumTravelLogEntry和ITravelLogEntry?/p>

 

  • ITravelLogStg——该接口提供了用于在Travel Log中添加、删除、枚举日志(览历史Q的Ҏ(gu)Q本文需要用到的几个Ҏ(gu)列D如下Q?

Ҏ(gu)?nbsp;    用?/p>

EnumEntries 问日志项创徏枚D器(IEnumTravelLogEntry接口指针Q?/p>

GetRelativeEntry q回一个日志项

TravelTo 讉K一个日志项

  • IEnumTravelLogEntry——该接口提供用于枚D日志Ҏ(gu)必需的方法,本文只用C个方法:(x)

Ҏ(gu)?nbsp;    用?/p>

Next   枚D下一个日志项Q返回ITravelLogEntry接口指针Q?/p>

  • ITravelLogEntry——该接口只有两个Ҏ(gu)Q分别用于返回日志项的Title和UrlQ?

Ҏ(gu)?nbsp;    用?/p>

GetTitle q回日志的Title

GetURL q回日志的Url

 

接口准备好了Q我们也很Ҏ(gu)得知它们之间的关p:(x)

  • 要得到相对于当前面的日志项列表Q首先应通过ITravelLogStg接口创徏一个枚丑֙QIEnumTravelLogEntry接口Q?
  • 通过IEnumTravelLogEntry枚D器的NextҎ(gu)枚DZ个个的日志项QITravelLogEntry接口Q?
  • 由ITravelLogEntry接口获取日志Ҏ(gu)代表的网늚Title和Urlq加以处理?
  • 讉K相对于当前页面的某个日志Ҏ(gu)Q首先由ITravelLogStg的GetRelativeEntryҎ(gu)Ҏ(gu)与当前页的距d到ITravelLogEntry接口Q再后者传入ITravelLogStg的TravelToҎ(gu)以达到访问日志项的目的(如前q和后退Q?

 

也许不是太恰当,我对UML也不熟?zhn)Q借用一个伪UML序列图表C其关系如下Q?/p>

 

 

 Travel log

 

4、封装Travel Log

接下来,我们q一个简单的cL完成对Travel Log的封装。如下所C,tlogstg.h包含了Travel Log的相x口声明,该头文g可以在Platform SDK中找到?/p>

 

#include "tlogstg.h"

 

class CIETravelLog

{

private:

ITravelLogStg *m_pTravelLogStg;

IEnumTravelLogEntry *m_pEnumLogEntry;

ITravelLogEntry *m_pTravalLogEntry;

IWebBrowser2* m_pWebBrowser;

public:

CIETravelLog(void);

~CIETravelLog(void);

void SetWebBrowser(IWebBrowser2* pWebBrowser);

void BuildHistoryMenu(CMenu * pMenu, unsigned char nCount, bool bForward);

void TravelTo(int nPosition);

};

 

CIETravelLog::CIETravelLog(void)

: m_pTravelLogStg(NULL), m_pEnumLogEntry(NULL), m_pTravalLogEntry(NULL), m_pWebBrowser(NULL)

{

}

 

CIETravelLog::~CIETravelLog(void)

{

if ( m_pTravelLogStg != NULL )

{

m_pTravelLogStg->Release();

}

if ( m_pEnumLogEntry != NULL )

{

m_pEnumLogEntry->Release();

}

if ( m_pTravalLogEntry != NULL )

{

m_pTravalLogEntry->Release();

}

if ( m_pWebBrowser != NULL )

{

m_pWebBrowser->Release();

}

}

 

//浏览器的IWebBrowser2接口指针赋予CIETravelLog的实?/font>

void CIETravelLog::SetWebBrowser(IWebBrowser2* pWebBrowser)

{

if ( (m_pWebBrowser == pWebBrowser) || (m_pWebBrowser == NULL) )

{

return;

}

if ( m_pWebBrowser != NULL )

{

m_pWebBrowser->Release();

}

m_pWebBrowser = pWebBrowser;

 

IServiceProvider *pSP;

HRESULT hr = m_pWebBrowser->QueryInterface(IID_IServiceProvider, (LPVOID*)&pSP);

m_pWebBrowser->Release();

if (SUCCEEDED(hr))

{

hr = pSP->QueryService(SID_STravelLogCursor, IID_ITravelLogStg, (LPVOID*)&m_pTravelLogStg);

pSP->Release();

}

}

 

//创徏览历史菜单QbForward指明是前q还是后退菜单

void CIETravelLog::BuildHistoryMenu(CMenu * pMenu, unsigned char nCount, bool bForward)

{

if ( m_pTravelLogStg == NULL )

{

return;

}

TLENUMF eFlag = bForward ? TLEF_RELATIVE_FORE : TLEF_RELATIVE_BACK;

if ( FAILED(m_pTravelLogStg->EnumEntries( eFlag, &m_pEnumLogEntry ) ) )

{

return;

}

 

ULONG uFetched;

int i=0;

if ( m_pEnumLogEntry !=NULL )

{

while ( SUCCEEDED( m_pEnumLogEntry->Next( 1, &m_pTravalLogEntry, &uFetched ) ) &&

m_pTravalLogEntry && i<10 )//我们最多只需?0条历史菜单,可根据实际情况修?/font>

{

LPOLESTR pszTitle;

m_pTravalLogEntry->GetTitle( &pszTitle );

CString strTitle = pszTitle;

if ( bForward )

{

//ID_IEHISTORY_MIDDLE是预定义的某个菜单项IDQ从该ID开始前后可以创?0个菜单项Q参见下一?/font>

pMenu->InsertMenu( 0, MF_STRING, ID_IEHISTORY_MIDDLE + ++i, strTitle );

}

else

{

pMenu->InsertMenu( 0, MF_STRING, ID_IEHISTORY_MIDDLE - ++i, strTitle );

}

CoTaskMemFree( pszTitle );

m_pTravalLogEntry->Release();

}

}

}

 

//Ҏ(gu)与当前页面的相对距离来访问历史网?/font>

void CIETravelLog::TravelTo(int nPosition)

{

if ( m_pTravelLogStg == NULL )

{

return;

}

if SUCCEEDED(m_pTravelLogStg->GetRelativeEntry( nPosition, &m_pTravalLogEntry ))

{

m_pTravelLogStg->TravelTo( m_pTravalLogEntry );

}

}

 

5、用CIETravelLog

假设是在我们自己~写的多H口览器中使用Travel Log。ؓ(f)单v见,我们声明一个CIETravelLog的全局对象g_IETravelLogQ以便在M地方调用。然后在适当的地方,如CMainFrame的TBN_DROPDOWN消息Q工h菜单下拉消息Q处理函数OnDropDown中,d下面的代码,用以创徏览历史菜单Q?/p>

//GetActiveWebBrowserPtrq回zd的浏览器IWebBrowser2接口指针

IETravelLog.SetWebBrowser( GetActiveWebBrowserPtr );

//bForward为true则创?#8220;前进”菜单Q否则创?#8220;后退”菜单

IETravelLog.BuildHistoryMenu( &Menu, 10, bForward);

 

以下定义单项ID的范_(d)前后共可以容U?0个菜单项Q可Ҏ(gu)实际情况修改?/p>

#define ID_IEHISTORY_FIRST  60200

#define ID_IEHISTORY_MIDDLE 60210

#define ID_IEHISTORY_LAST   60220

 

d命o(h)处理函数OnTravelHistoryUrl用以响应从ID_IEHISTORY_FIRST到ID_IEHISTORY_LAST的菜单命令?/p>

 

ON_COMMAND_RANGE(ID_IEHISTORY_FIRST, ID_IEHISTORY_LAST, OnTravelHistoryUrl)

 

void CMainFrame::OnTravelHistoryUrl(UINT nID /* Command ID */)

{

//nID - ID_IEHISTORY_MIDDLE即ؓ(f)要访问的览历史到当前页面的距离

g_IETravelLog.TravelTo( nID - ID_IEHISTORY_MIDDLE );

}

 

6、再谈Travel Log

前面我提?#8220;Travel Log接口正日益成为应用程序中的重要接口之一”Q此处加以说明。从微Yq_的开发模式及导向来看Q基于Internet Explorer/WebBrowser Control的应用势必会(x)成ؓ(f)L。在下一代的操作pȝLonghorn中,应用E序界面的描q将完全由XML的一个特化——XAML来完成,而XAML的解析将由浏览器完成。微软说未来应用E序的部|将?x)十分容易,本地应用和基于浏览器的应用之间的差异?x)被逐渐淡化Q而实现这一目标的一个重要表现就是,在将来的操作pȝq_上,应用E序实际上时刻都运行在Internet Explorer中,Internet Explorer在某U程度上来说变成了一个容器?/p>

于是Q扎根于Internet Explorer的Travel Log自然而然地就被整合到了我们的应用E序中。君不见Q我们每天在资源理器和览器上完成的工作,不就是在Travel Log中来来回回地跑吗Q如果所有的应用E序都嵌入到Internet Explorer中运行,那么我们在应用程序中所作的操作便自然得C记录Q?#8220;前进”?#8220;后退”也就很Easy了?/p>

很多软g都已l或多或地开始采用基于Internet Explorer的模式,如Microsoft Money、Microsoft Encarta、Visual Studio.net的安装程序等{,都是很好的范例。所以,q前来_(d)我们的应用E序按这U模式编写(可参考?a >利用览器实现程序界面与实现的分?/a>》)Q不是可以早一点获?#8220;讉K日志的体?#8221;吗?

何乐而不为?/p>

 

引用地址Q?a >Internet Explorer ~程qͼ八)实现览历史菜单?/font>

Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=308620




]]>
Internet Explorer~程q??http://m.shnenglu.com/mydriverc/articles/28962.html旅?/dc:creator>旅?/author>Sun, 29 Jul 2007 07:18:00 GMThttp://m.shnenglu.com/mydriverc/articles/28962.htmlhttp://m.shnenglu.com/mydriverc/comments/28962.htmlhttp://m.shnenglu.com/mydriverc/articles/28962.html#Feedback0http://m.shnenglu.com/mydriverc/comments/commentRss/28962.htmlhttp://m.shnenglu.com/mydriverc/services/trackbacks/28962.html 1、概q?/strong>

Internet Explorer有实在太多没有公布的东西。上一文章《Internet Explorer ~程qͼ六)自定义浏览器上下文菜单》提到的获取“~码”菜单的方法就是利用了览器的上层H口“Shell DocObject View”的未公布的命令ID。本文将要介l的是如何用q个ID?#8220;~码”菜单攑ֈ我们自己的菜单中来(如工h上的“~码”按钮的下拉菜单)?/p>

#define SHDVID_GETMIMECSETMENU 27
......
CComPtr spCT;

hr = pcmdTarget->QueryInterface(IID_IOleCommandTarget, (void**)&spCT);
......
// Get the language submenu
hr = spCT->Exec(&CGID_ShellDocView, SHDVID_GETMIMECSETMENU, 0, NULL, &var);

2、原?/strong>

上面指向IOleCommandTarget接口的智能指针spCT是从IDocHostUIHandler::ShowContextMenu的参数pcmdTarget得到的,它其实也可以从HTML文档接口得到Q这是实现的关键?/p>

3、实?/strong>

下面的代码演CZ如何?#8220;~码”菜单攄到我们自q~码菜单上去?/p>

void CMainFrame::OnDropDown( NMHDR* pNotifyStruct, LRESULT* pResult )

{

 const UINT CmdID_GetMimeSubMenu = 27;

 // Command ID for getting the Encoding submenu

 NMTOOLBAR* pNMToolBar = ( NMTOOLBAR* )pNotifyStruct;

 CMenu menu;

 CMenu* pPopup = 0;

 CMyHtmlView *pView = NULL;

 m_bIsEncodMenuPopup = false;//标志变量Q用以在WM_INITMENUPOPUP消息处理函数中检?#8220;~码”菜单

 switch ( pNMToolBar->iItem )

 {

 ......
 case ID_VIEW_ENCODE://按下“~码”按钮

 {

  m_bIsEncodMenuPopup = true;

  VERIFY( menu.LoadMenu( IDR_ENCODE ) );//IDR_ENCODE是预|的“~码”菜单资源Q内含Q意一占位用的菜?/font>

  CMyHtmlView = GetActiveMyHtmlView();//查当前是否存在活动的览器视囄?/font>

  if ( pView != NULL )

  {

   LPDISPATCH lpDispatch =pView->GetHtmlDocument();//获得文档指针

   if ( lpDispatch != NULL )

   {

    // Get an IDispatch pointer for the IOleCommandTarget interface.

    IOleCommandTarget * pCmdTarget = NULL;

    HRESULT hr = lpDispatch->QueryInterface(IID_IOleCommandTarget, (void**)&pCmdTarget);

    if ( SUCCEEDED( hr ) )

    {

     VARIANT varEncSubMenu;

     ::VariantInit( &varEncSubMenu );

     hr = pCmdTarget->Exec( &::CGID_ShellDocView, CmdID_GetMimeSubMenu, OLECMDEXECOPT_DODEFAULT, NULL, &varEncSubMenu );

     if ( SUCCEEDED( hr ) )

     {

      // d“~码”菜单

      MENUITEMINFO miiEncoding;

      ::memset( &miiEncoding, 0, sizeof(MENUITEMINFO) );

      miiEncoding.cbSize = sizeof(MENUITEMINFO);

      miiEncoding.fMask = MIIM_SUBMENU;

      miiEncoding.hSubMenu = reinterpret_cast< HMENU > (varEncSubMenu.byref);

      menu.SetMenuItemInfo(0, &miiEncoding, TRUE);//丢掉设计时占位用的菜单,替换?#8220;~码”菜单

      }

    }

   }

  }

  pPopup = menu.GetSubMenu( 0 );

  break;

 }

 ......

 }

 

 if ( pPopup != 0 )

 {

  CRect rc;

  ::SendMessage( pNMToolBar->hdr.hwndFrom, TB_GETRECT, pNMToolBar->iItem, ( LPARAM )&rc );

  rc.top = rc.bottom;

  ::ClientToScreen( pNMToolBar->hdr.hwndFrom, &rc.TopLeft() );

  long lResult = pPopup->TrackPopupMenu( TPM_LEFTALIGN | TPM_LEFTBUTTON | TPM_RETURNCMD, rc.left, rc.top, this );

  m_bIsEncodMenuPopup = false;

  if ( pNMToolBar->iItem == ID_VIEW_ENCODE )

  {

   //其余的事教给览器去做,参考?a id="CategoryEntryList.ascx_EntryStoryList_Entries__ctl1_TitleUrl" >Internet Explorer ~程qͼ五)调用IE隐藏的命令(中文版)?/font>

    CFindIEWnd FindIEWnd( pView->m_wndBrowser.m_hWnd, "Internet Explorer_Server");

   ::SendMessage( FindIEWnd.m_hWnd, WM_COMMAND, MAKEWPARAM(LOWORD(lResult), 0x0), 0 );

  }

  else

  {

   SendMessage( WM_COMMAND, MAKEWPARAM(LOWORD(lResult), 0x0), 0 );

  }

 }

 *pResult = TBDDRET_DEFAULT;

}


void CMainFrame::OnInitMenuPopup(CMenu* pPopupMenu, UINT nIndex, BOOL bSysMenu)

{

 CMDIFrameWndEx::OnInitMenuPopup(pPopupMenu, nIndex, bSysMenu);

 if ( m_bIsEncodMenuPopup )

 {

  //默认情况?#8220;~码”的所有菜单项都是Disabled的,在此修改其状态ؓ(f)Enabled

  for ( UINT i=0; i GetMenuItemCount(); i++ )

  {

   pPopupMenu->EnableMenuItem( pPopupMenu->GetMenuItemID( i ), MF_ENABLED | MF_BYCOMMAND );

  }

 }

}

q样一来,原本只在览器上下文菜单中出现的“~码”菜单出现在了我们自q工具条按钮下拉菜单上Q无需更多的处理,菜单状态的改变Q编码的讄{,一切都教给览器自己去完成了?/p>


]]>
Internet Explorer~程q??http://m.shnenglu.com/mydriverc/articles/28961.html旅?/dc:creator>旅?/author>Sun, 29 Jul 2007 07:17:00 GMThttp://m.shnenglu.com/mydriverc/articles/28961.htmlhttp://m.shnenglu.com/mydriverc/comments/28961.htmlhttp://m.shnenglu.com/mydriverc/articles/28961.html#Feedback0http://m.shnenglu.com/mydriverc/comments/commentRss/28961.htmlhttp://m.shnenglu.com/mydriverc/services/trackbacks/28961.html

1、概q?br> Internet Explorer提供了非常开发的接口Q开发h员不仅可以把其浏览器核心嵌入应用E序Q还可以通过各种接口以实现更深层的控制。本文就介l对览器进行高U控制的话题之一——自定义上下文菜单?/p>

2、最单的情况
自定义的IE及WebBrowser的上下文菜单Q最单的方式是在注册表的HKEY_CURRENT_USER\Software\Microsoft\Internet Explorer\MenuExt下添加自定义的键|步骤如下Q?br> 1) d一个新的键Q其名称即ؓ(f)来昄在上下文菜单中的菜单名Uͼ如:(x)
 HKEY_CURRENT_USER\Software\Microsoft\Internet Explorer\MenuExt\&Google Search
2) 新增的键的默认D|ؓ(f)一个包含脚本的|页的URLQ或文g路径全名Q,该网中的脚本将在用L(fng)M下文菜单中的“Google Search”后被览器执行?/p>

3)在新增的键下q可以新Z个二q制值ContextsQ用以指定我们新增的菜单w对特定的|页对象是否出现Q其取值可以是如下值的l合Q逻辑或)

Context     Value
Default     0x1
Images     0x2
Controls    0x4
Tables     0x8
Text selection 0x10
Anchor     0x20

4) q可以徏立一个DWORDcd的Flagsƈ其D|ؓ(f)0x01Q这得前q脚本在一个模态窗口中执行Q就好像是通过window.showModalDialog调用的,但不同的是在脚本中仍然可以访问window对象?br> 5) 实例脚本如下Q?/p>

通过修改注册表自定义菜单的方法适用于Internet Explorer和W(xu)ebBrowserQ也h良好的扩展性。但我们如果希望执行的是不仅仅是脚本Q二是自qE序中代码,q种Ҏ(gu)׃适用了?/p>

3、用完全自定义的菜?br>1) IDocHostUIhandler接口提供了一个ShowContextMenuҎ(gu)Q在需要显CZ下文菜单之前QMSHTML引擎׃(x)调用实现了IDocHostUIHandler接口?br>宿主E序的ShowContextMenuҎ(gu)?/p>

HRESULTIDocHostUIHandler::ShowContextMenu(
  DWORD dwID,
  POINT *ppt,
  IUnknown *pcmdtReserved,
  IDispatch *pdispReserved
);

dwID参数的意义与Contexts的组合类|ppt单的弹出点屏q坐标;pcmdtReserved接口指向 IOleCommandTarget接口Q可用于网对象的状态和执行命o(h){操作。pdispReserved在IE5以上版本中指向的是网对象的 IDispatch接口Q用以区分不同对象,比如我们可以q样来获得网对象的指针Q?/p>

IHTMLElement *pElem;
HRESULT hr;
hr = pdispReserved->QueryInterface(IID_IHTMLElement, (void**)pElem);
if(SUCCEEDED (hr)) {
  BSTR bstr;
  pElem->get_tagName(bstr);
  USES_CONVERSION;
  ATLTRACE("TagName:%s\n", OLE2T(bstr));
  SysFreeString(bstr);
  pElem->Release();
}

如果我们在该Ҏ(gu)中返回S_OKQ则告诉MSHTML我们用自q菜单Q界面)Q如果是S_FALSEQ则弹出默认的菜单?/p>

2) 实现
原理清楚之后Q实现v来非常简单,和弹Z般的菜单没什么两P举例如下Q显CZ框架?#8220;文g菜单”Q?/p>

HRESULT CMyHtmlView::OnShowContextMenu(DWORD dwID, LPPOINT ppt, IUnknown * pcmdtReserved, IDispatch *)
{
 // 载入主菜?br> HMENU hMenuParent = ::LoadMenu( ::AfxGetInstanceHandle(), MAKEINTRESOURCE(IDR_MAINFRAME) );
 if (hMenuParent)
 {
  HMENU hMenu = ::GetSubMenu( hMenuParent, 0 ); // 取得“文g”子菜?br>  if (hMenu)
  {
   // 昄菜单
   TrackPopupMenuEx( hMenu,
    TPM_LEFTALIGN | TPM_TOPALIGN,
    ppt->x,
    ppt->y,
    ::AfxGetMainWnd()->m_hWnd,
    NULL );
  }
  ::DestroyMenu( hMenuParent );
 }
 return S_OK;
}

4、自定义标准上下文菜?br>1) 原理
更多的时候我们希望能在浏览器原来菜单的基上作一些修改,如删?#8220;查看源文?#8221;Q添加自q菜单,{等Q而不是完全不要原始的菜单Q怎么办呢Q借助MSDN提供的例子,我们来看看:(x)

HRESULT CBrowserHost::ShowContextMenu(DWORD dwID, POINT *ppt,IUnknown *pcmdTarget,IDispatch *pdispObject)
{
 #define IDR_BROWSE_CONTEXT_MENU 24641
 #define IDR_FORM_CONTEXT_MENU 24640
 #define SHDVID_GETMIMECSETMENU 27
 #define SHDVID_ADDMENUEXTENSIONS 53

 HRESULT hr;
 HINSTANCE hinstSHDOCLC;
 HWND hwnd;
 HMENU hMenu;

 CComPtr spCT;
 CComPtr spWnd;

 MENUITEMINFO mii = {0};
 CComVariant var, var1, var2;
 hr = pcmdTarget->QueryInterface(IID_IOleCommandTarget, (void**)&spCT);
 hr = pcmdTarget->QueryInterface(IID_IOleWindow, (void**)&spWnd);
 hr = spWnd->GetWindow(&hwnd);//取得览器窗口句?br> hinstSHDOCLC = LoadLibrary(TEXT("SHDOCLC.DLL"));
 if (hinstSHDOCLC == NULL)
 {
  // Error loading module -- fail as securely as possible
  return;
 }
 hMenu = LoadMenu(hinstSHDOCLC, MAKEINTRESOURCE(IDR_BROWSE_CONTEXT_MENU));
 hMenu = GetSubMenu(hMenu, dwID);
 // Get the language submenu
 hr = spCT->Exec(&CGID_ShellDocView, SHDVID_GETMIMECSETMENU, 0, NULL, &var);
 mii.cbSize = sizeof(mii);
 mii.fMask = MIIM_SUBMENU;
 mii.hSubMenu = (HMENU) var.byref;
 // Add language submenu to Encoding context item
 SetMenuItemInfo(hMenu, IDM_LANGUAGE, FALSE, &mii);
 // Insert Shortcut Menu Extensions from registry
 V_VT(&var1) = VT_INT_PTR;
 V_BYREF(&var1) = hMenu;
 V_VT(&var2) = VT_I4;
 V_I4(&var2) = dwID;
 hr = spCT->Exec(&CGID_ShellDocView, SHDVID_ADDMENUEXTENSIONS, 0, &var1, &var2);
 // Remove View Source
 DeleteMenu(hMenu, IDM_VIEWSOURCE, MF_BYCOMMAND);//删除“查看源文?#8221;菜单?br> // Show shortcut menu
 int iSelection = ::TrackPopupMenu(hMenu,
  TPM_LEFTALIGN | TPM_RIGHTBUTTON | TPM_RETURNCMD ,//q回用户选择的菜单命令ID
  ppt->x,
  ppt->y,
  0,
  hwnd,
  (RECT*)NULL);
 // Send selected shortcut menu item command to shell
 LRESULT lr = ::SendMessage(hwnd, WM_COMMAND, iSelection, NULL);//发送到Internet Explorer_Serverq行内部处理?br> FreeLibrary(hinstSHDOCLC);
 return S_OK;
}

? 上面的例子我们看出,基本的方法就是根?#8220;shdoclc.dll”文g中的菜单资源建立菜单Q再通过来自pcmdTarget? IOlcCommandTarget接口获得“~码”菜单以及HKEY_CURRENT_USER\Software\Microsoft\ Internet Explorer\MenuExt下的定义扩展菜单Q然后以TPM_RETURNCMD标志调用TrackPopupMenu? TrackPopupMenuEx弹出菜单Qƈ返回的菜单命o(h)ID教给览器窗口进行处理。这U方法可以调用许多通过览器无法直接调用的命o(h)和对话框 Q参阅:(x)?a >Internet Explorer ~程qͼ五)调用IE隐藏的命?/font>》)?/font>

所以,我们只需要在弹出菜单之前做一些自定义操作卛_辑ֈ修改默认菜单的目的,如上面代码中q删除?#8220;查看源文?#8221;菜单V?/font>

2) 问题
如果我们不仅仅是删除默认的菜单项或是修改了默认的菜单,q添加了自己的菜单项Q会(x)出现什么情况呢Q由于用了cM于MFC中UpdateUI的机Ӟ遇到不认识的CommandIDQ浏览器׃(x)其状态设|ؓ(f)DisabledQ所以我们自己添加的菜单是无法被选择的?br>? 以想刎ͼ如果把菜单状态设|ؓ(f)EnabledQƈ通过TPM_RETURNCMD标志调用TrackPopupMenu? TrackPopupMenuExQ再把返回的命o(h)ID教给合适的H口Q如L架窗口)d理不p了。关键点在于如何把菜单状态设|ؓ(f) Enabled?/font>

3) 实现
解决的办法是截获 WM_INITMENUPOPUP 消息Q在菜单创徏以后Q尚未显CZ前修改菜单项状态,那浏览器没有办法了。截获WM_INITMENUPOPUP消息则可使用子类化(subclassQ的技术,前面通过IOleWindow接口我们得到了浏览器H口的句柄hwndQ则可以q样做:(x)

HMENU g_hPubMenu = NULL;
WNDPROC g_lpPrevWndProc = NULL;

LRESULT CALLBACK CustomMenuWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
 if (uMsg == WM_INITMENUPOPUP)
 {
  if (wParam == (WPARAM) g_hPubMenu)
  {
   ::EnableMenuItem( 自定义的菜单命o(h)ID, MF_ENABLED | MF_BYCOMMAND );
   ::CheckMenuItem( 自定义的菜单命o(h)ID, MF_BYCOMMAND);
   return 0;
  }
 }
 return CallWindowProc(g_lpPrevWndProc, hwnd, uMsg, wParam, lParam);
}

HRESULT CMyHtmlView::OnShowContextMenu(DWORD dwID, LPPOINT ppt,
LPUNKNOWN pcmdtReserved, LPDISPATCH pdispReserved)
{
//览器菜单句柄保存在g_hPubMenu?br>......
// subclass览器窗?br>g_lpPrevWndProc = (WNDPROC)::SetWindowLong(hwnd, GWL_WNDPROC, (LONG)CustomMenuWndProc);
//m_SubclassWnd.SubclassWindow( hwnd );//MFC中用此方法更?/font>

// Show shortcut menu
int iSelection = ::TrackPopupMenu(hSubMenu,
 TPM_LEFTALIGN | TPM_RIGHTBUTTON | TPM_RETURNCMD,
 ppt->x,
 ppt->y,
 0,
 hwnd,
 (RECT*)NULL);
// Unsubclass览器窗?br>::SetWindowLong(hwnd, GWL_WNDPROC, (LONG)g_lpPrevWndProc);
g_lpPrevWndProc = NULL;
//m_SubclassWnd.UnsubclassWindow();

if (iSelection == 自定义的菜单命o(h)ID )
{
 ::SendMessage( ::AfxGetMainWnd()->m_hWnd, WM_COMMAND, MAKEWPARAM(LOWORD(lResult), 0x0), 0 );
}
else
{
 LRESULT lr = ::SendMessage(hwnd, WM_COMMAND, iSelection, NULL);
}
......
}

在MFC 中则更ؓ(f)方便Q从CWndl承一个窗口类Q假设ؓ(f)CWebBrowserSubclassWndQؓ(f)CMyHtmlViewd一? CWebBrowserSubclassWndcd的成员变量m_SubclassWndQ在子类化和去除子类化时调用 m_SubclassWnd.SubclassWindow( hwnd )和m_SubclassWnd.UnsubclassWindow()卛_。相应的WM_INITMENUPOPUP消息处理函数如下所C:(x)

void CWebBrowserSubclassWnd::OnInitMenuPopup(CMenu* pPopupMenu, UINT nIndex, BOOL bSysMenu)
{
 CWnd::OnInitMenuPopup(pPopupMenu, nIndex, bSysMenu);

 pPopupMenu->EnableMenuItem( 自定义的菜单命o(h)ID, MF_ENABLED | MF_BYCOMMAND );
 pPopupMenu->CheckMenuItem( 自定义的菜单命o(h)ID, MF_BYCOMMAND);
}

下面的图片显CZ?#8220;文字大小”菜单Ҏ(gu)加到“~码”菜单的下面的效果?/font>

5、新的问?br> 看完上面的代码,我们又自然地惛_览器编E中的另一个问题,那就?#8220;~码”菜单。我们指定,手动建立一?#8220;~码”菜单是比较麻烦的事,而且很难做到与浏览器上下文菜单上?#8220;~码”菜单一L(fng)效果。何不用上q的Ҏ(gu)让浏览器自己建立“~码”菜单和处理相应的命o(h)呢?

具体实现L(fng)下一文章《Internet Explorer ~程qͼ七)完美?#8220;~码”菜单?/font>


参考资?/strong> Q?br>MSDN:Adding Entries to the Standard Context Menu
MSDN:How To Adding to the Standard Context Menus of the WebBrowser Control
MSDN:IDocHostUIHandler::ShowContextMenu Method
BeginThread.com:Custom WebBrowser Context Menus




]]>
Internet Explorer~程q??http://m.shnenglu.com/mydriverc/articles/28959.html旅?/dc:creator>旅?/author>Sun, 29 Jul 2007 07:14:00 GMThttp://m.shnenglu.com/mydriverc/articles/28959.htmlhttp://m.shnenglu.com/mydriverc/comments/28959.htmlhttp://m.shnenglu.com/mydriverc/articles/28959.html#Feedback0http://m.shnenglu.com/mydriverc/comments/commentRss/28959.htmlhttp://m.shnenglu.com/mydriverc/services/trackbacks/28959.html
  除了“整理收藏?#8221;?#8220;d到收藏夹”对话框外Q还有其它一些对话框是我们希望直接通过WebBrowser调用的, 比如“导入/导出”对话框,用一般的Ҏ(gu)很难调用。IShellUIHelper管提供了ImportExportFavoritesҎ(gu)Q但l果只是 昄一个选择文g的对话框Q且只能导入/导出收藏夹而不能对Cookies操作?br>

  2、契?br>
  MSDN中有一叫“WebBrowser Customization”的文章,其中介绍了通过IDocHostUIHandler.ShowContextMenuҎ(gu)自定义WebBrowser上下文菜单的Ҏ(gu)?br>
? 原理是从“shdoclc.dll”的资源中创徏菜单Q作一些修改之后用TrackPopupMenu函数Q注意在标志中包? TPM_RETURNCMDQ将菜单弹出Q然后把q回的Command ID发送给“Internet Explorer_Server”H口q行处理?/p>


  ......
  // 昄菜单
  int iSelection = ::TrackPopupMenu(hMenu,
  TPM_LEFTALIGN | TPM_RIGHTBUTTON | TPM_RETURNCMD,
  ppt->x,
  ppt->y,
  0,
  hwnd,
  (RECT*)NULL);
  // 发送Command ID到外壳窗?br>  LRESULT lr = ::SendMessage(hwnd, WM_COMMAND, iSelection, NULL);
  ......

  好,如果扑ֈ所有上下文菜单的Command IDQ不可以随时调用了Q确实是q样的?br>
  3、实?br>  用eXeScope之类应用E序资源探烦器打开“shdoclc.dll”便可以在菜单资源下找C下文菜单的设计,如下图:(x)

  我们要做的,是这些ID发送到“Internet Explorer_Server”H口q行处理。问题是WebBrowser其实是一个OLE容器Q我们用的CHtmlView又是更外层的装Q他? 的m_hWnd成员变量q不是IEH口的句柄,如何扑ֈ我们需要的句柄呢?L(fng)下面的图Q?/p>


  Ҏ(gu)图中昄的从属关p,摸瓜Q最内层的窗?#8220;Internet Explorer_Server”的句柄就是我们需要的东西。ؓ(f)了简化问题,我这里用了来自MSDN Magazine资深专栏撰稿人Paul Dilascia的CFindWndc,非常好用?/p>


  ////////////////////////////////////////////////////////////////
  // MSDN Magazine -- August 2003
  // If this code works, it was written by Paul DiLascia.
  // If not, I don't know who wrote it.
  // Compiles with Visual Studio .NET on Windows XP. Tab size=3.
  //
  // ---
  // This class encapsulates the process of finding a window with a given class name
  // as a descendant of a given window. To use it, instantiate like so:
  //
  // CFindWnd fw(hwndParent,classname);
  //
  // fw.m_hWnd will be the HWND of the desired window, if found.
  //
  class CFindWnd {
  private:
  //////////////////
  // This private function is used with EnumChildWindows to find the child
  // with a given class name. Returns FALSE if found (to stop enumerating).
  //
  static BOOL CALLBACK FindChildClassHwnd(HWND hwndParent, LPARAM lParam) {
  CFindWnd *pfw = (CFindWnd*)lParam;
  HWND hwnd = FindWindowEx(hwndParent, NULL, pfw->m_classname, NULL);
  if (hwnd) {
  pfw->m_hWnd = hwnd; // found: save it
  return FALSE; // stop enumerating
  }
  EnumChildWindows(hwndParent, FindChildClassHwnd, lParam); // recurse
  return TRUE; // keep looking
  }
  public:
  LPCSTR m_classname; // class name to look for
  HWND m_hWnd; // HWND if found
  // ctor does the work--just instantiate and go
  CFindWnd(HWND hwndParent, LPCSTR classname)
  : m_hWnd(NULL), m_classname(classname)
  {
  FindChildClassHwnd(hwndParent, (LPARAM)this);
  }
  };

 

  再写一个函数InvokeIEServerCommandQ调用就很方便了Q《Internet Explorer ~程qͼ四)“d到收藏夹”对话框》中最后给出的Ҏ(gu)是从这里来的?/p>


  void CMyHtmlView::InvokeIEServerCommand(int nID)
  {
  CFindWnd FindIEWnd( m_wndBrowser.m_hWnd, "Internet Explorer_Server");
  ::SendMessage( FindIEWnd.m_hWnd, WM_COMMAND, MAKEWPARAM(LOWORD(nID), 0x0), 0 );
  }
void CMyHtmlView::OnFavAddtofav()
  {
  InvokeIEServerCommand(ID_IE_CONTEXTMENU_ADDFAV);//调用“d到收藏夹”对话?br>  }



  4、Command IDs
  Ҏ(gu)有的Command ID逐一试后我们发玎ͼ(x)
  1)不是所有的Command ID都可以用上面的方法调用;
  2)不是所有的Command ID都是?#8220;Internet Explorer_Server”H口处理Q?br>  3)有一些Command ID是由上一U窗?#8220;Shell DocObject View”处理?br>  所以我们还需要写一个函数?/p>


  void CMyHtmlView::InvokeShellDocObjCommand(int nID)
  {
  CFindWnd FindIEWnd( m_wndBrowser.m_hWnd, "Shell DocObject View");
  ::SendMessage( FindIEWnd.m_hWnd, WM_COMMAND, MAKEWPARAM(LOWORD(nID), 0x0), 0 );
  }

 

  调用文章开头提到的“导入/导出”对话框可以这h做:(x)


  void CDemoView::OnImportExport()
  {
  InvokeShellDocObjCommand(ID_IE_FILE_IMPORTEXPORT);//调用“导入/导出”对话?br>  }

  ?Internet Explorer_Server"H口处理的Command ID:
  #define ID_IE_CONTEXTMENU_ADDFAV 2261
  #define ID_IE_CONTEXTMENU_VIEWSOURCE 2139
  #define ID_IE_CONTEXTMENU_REFRESH 6042

  ?Shell DocObject View"H口处理的Command ID:
  #define ID_IE_FILE_SAVEAS 258
  #define ID_IE_FILE_PAGESETUP 259
  #define ID_IE_FILE_PRINT 260
  #define ID_IE_FILE_NEWWINDOW 275
  #define ID_IE_FILE_PRINTPREVIEW 277
  #define ID_IE_FILE_NEWMAIL 279
  #define ID_IE_FILE_SENDDESKTOPSHORTCUT 284
  #define ID_IE_HELP_ABOUTIE 336
  #define ID_IE_HELP_HELPINDEX 337
  #define ID_IE_HELP_WEBTUTORIAL 338
  #define ID_IE_HELP_FREESTUFF 341
  #define ID_IE_HELP_PRODUCTUPDATE 342
  #define ID_IE_HELP_FAQ 343
  #define ID_IE_HELP_ONLINESUPPORT 344
  #define ID_IE_HELP_FEEDBACK 345
  #define ID_IE_HELP_BESTPAGE 346
  #define ID_IE_HELP_SEARCHWEB 347
  #define ID_IE_HELP_MSHOME 348
  #define ID_IE_HELP_VISITINTERNET 349
  #define ID_IE_HELP_STARTPAGE 350
  #define ID_IE_FILE_IMPORTEXPORT 374
  #define ID_IE_FILE_ADDTRUST 376
  #define ID_IE_FILE_ADDLOCAL 377
  #define ID_IE_FILE_NEWPUBLISHINFO 387
  #define ID_IE_FILE_NEWCORRESPONDENT 390
  #define ID_IE_FILE_NEWCALL 395
  #define ID_IE_HELP_NETSCAPEUSER 351
  #define ID_IE_HELP_ENHANCEDSECURITY 375

  5、Refresh

  熟?zhn)TEmbeddedWB的读者可能注意到了ID_IE_CONTEXTMENU_REFRESH(6042)q个IDQ在TEmbeddedWB中给Z一个当|页h时触发的OnRefresh事gQ其中的关键代码如下Q?/p>


  ......
  if Assigned(FOnRefresh) and ((nCmdID = 6041 { F5}) or (nCmdID = 6042 { ContextMenu}) or (nCmdID = 2300)) then
  begin
  FCancel := False;
  FOnRefresh(self, nCmdID, FCancel);
  if FCancel then Result := S_OK;
  end;
  ......


其中?402是我们q里的ID_IE_CONTEXTMENU_REFRESHQ?300是内|的h命o(h)Q那6041呢。见下图Q还? “shdoclc.dll”Q?041原来是IE“查看”菜单?#8220;h”菜单的命令ID。实际开发中我们发现直接调用WebBrowser? Refresh命o(h)有时候会(x)D一些错误,可以用这里的Ҏ(gu)替换一下?br>



  6、需要注意的问题

  1)用InvokeIEServerCommand (ID_IE_CONTEXTMENU_ADDFAV)调用“d到收藏夹”对话框时需要注意的是,IE接收? ID_IE_CONTEXTMENU_ADDFAV命o(h)时是对网中当前被选中的链接来执行“d到收藏夹”操作的,如果没有选中的链接,才是当前网? d到收藏夹?br>
  2)新徏IEH口。这是浏览器~程中的N之一Q即从当前窗口新Z个Internet ExplorerH口Q完全复制当前页的内容(包括“前进”?#8220;后退”的状态)Q这可以通过InvokeShellDocObjCommand (ID_IE_FILE_NEWWINDOW)来实现?br>
  3)昄IE的版本信息。调用InvokeShellDocObjCommand(ID_IE_HELP_ABOUTIE)Q如下:(x)

  4)InvokeShellDocObjCommand(ID_IE_FILE_PRINT)调出?#8220;打印”对话框是非模态的Q我们不太清? Microsoft的设计意图,我认?#8220;打印”对话框应该是模态的Q,昄模态窗口的Ҏ(gu)请参考我的另一文章《利用WH_CBT Hook非模态对话框昄为模态对话框?/p>


]]>
Internet Explorer~程q??http://m.shnenglu.com/mydriverc/articles/28958.html旅?/dc:creator>旅?/author>Sun, 29 Jul 2007 07:12:00 GMThttp://m.shnenglu.com/mydriverc/articles/28958.htmlhttp://m.shnenglu.com/mydriverc/comments/28958.htmlhttp://m.shnenglu.com/mydriverc/articles/28958.html#Feedback0http://m.shnenglu.com/mydriverc/comments/commentRss/28958.htmlhttp://m.shnenglu.com/mydriverc/services/trackbacks/28958.html  调用“d到收藏夹”对话框(如下Q与调用“整理收藏?#8221;对话框有不同之处Q前者所做的工作比后者要来得复杂。将链接d到收藏夹除了链接保存之外,q可能会(x)有脱问的讄Q从IE 4.0到IE 5.0Q处理的方式也发生了一些变化?br>




  2、IShellUIHelper接口

  微Y专门提供了一个接口IShellUIHelper来实现对Windows Shell API一些功能的讉KQ将链接d到收藏夹也是其中之一Q就是下面的AddFavorite函数?/p>


  HRESULT IShellUIHelper::AddFavorite(BSTR URL, VARIANT *Title);

  实例代码如下Q?/p>


  void CMyHtmlView::OnAddToFavorites()
  {
  IShellUIHelper* pShellUIHelper;
  HRESULT hr = CoCreateInstance(CLSID_ShellUIHelper, NULL,
  CLSCTX_INPROC_SERVER, IID_IShellUIHelper,(LPVOID*)&pShellUIHelper);

  if (SUCCEEDED(hr))
  {
  _variant_t vtTitle(GetTitle().AllocSysString());
  CString strURL = m_webBrowser.GetLocationURL();

  pShellUIHelper->AddFavorite(strURL.AllocSysString(), &vtTitle);
  pShellUIHelper->Release();
  }
  }

  我们注意到这里的“AddFavorite”函数q没有像“DoOrganizeFavDlg”那样需要一个父H口句柄。这也导致与在IE中打 开不同Q通过IShellUIHelper接口昄出来?#8220;d到收藏夹”对话框是“非模?#8221;的,有一个独立于我们应用E序的Q务栏按钮Q这使我们的览 器显得非怸专业Q我是个q求完美的hQ这也是我的览器迟q不能发布的原因之一Q?br>
  于是我们很自然地惛_“shdocvw.dll”中除?#8220;DoOrganizeFavDlg”外,应该q有一个类似的函数Q可以传入一个父H口句柄用以昄模态窗口,也许像q样Q?/p>


  typedef UINT (CALLBACK* LPFNADDFAV)(HWND, LPTSTR, LPTSTR);

  事实上,q样的函数确实存在于“shdocvw.dll”中,那就?#8220;DoAddToFavDlg”?/p>


  3、DoAddToFavDlg函数

  “DoAddToFavDlg”函数也是“shdocvw.dll”暴露出来的函C一Q其原型如下Q?/p>


  typedef BOOL (CALLBACK* LPFNADDFAV)(HWND, TCHAR*, UINT, TCHAR*, UINT,LPITEMIDLIST);

  W一个参数正是我们想要的父窗口句柄,W二和第四个参数分别是初始目录(一般来说就是收藏夹目录Q和要添加的链接的名字(比如|页? TitleQ,W三和第五个参数分别是第二和W四两个~冲区的长度Q而最后一个参数则是指向与W二个参数目录相关的item identifier list的指?PIDL)。但最奇怪的是这里ƈ没有?#8220;AddFavorite”函数一L(fng)链接URLQ那链接是怎样d的呢Q答案是“手动创徏”?br>
W二个参数在函数调用q回后会(x)包含用户?#8220;d到收藏夹”对话框中选择或创建的完整链接路径名(?#8220;X:\XXX\mylink.url”Q,我们根 据这个\径和|页的URL来创建链接,代码如下Qؓ(f)化,此处省去?shdocvw.dll"是否已在内存中的代码Q参见《Internet Explorer ~程qͼ三)“整理收藏?#8221;对话框》)Q?/p>


  void CMyHtmlView::OnFavAddtofav()
  {
  typedef BOOL (CALLBACK* LPFNADDFAV)(HWND, TCHAR*, UINT, TCHAR*, UINT,LPITEMIDLIST);

  HMODULE hMod = (HMODULE)LoadLibrary("shdocvw.dll");
  if (hMod)
  {
  LPFNADDFAV lpfnDoAddToFavDlg = (LPFNADDFAV)GetProcAddress( hMod, "DoAddToFavDlg");
  if (lpfnDoAddToFavDlg)
  {
  TCHAR szPath[MAX_PATH];
  LPITEMIDLIST pidlFavorites;

  if (SHGetSpecialFolderPath(NULL, szPath, CSIDL_FAVORITES, TRUE) &&
  (SUCCEEDED(SHGetSpecialFolderLocation(NULL, CSIDL_FAVORITES, &pidlFavorites))))
  {
  TCHAR szTitle[MAX_PATH];
  strcpy(szTitle, GetLocationName());

  TCHAR szURL[MAX_PATH];
  strcpy(szURL, GetLocationURL());

  BOOL bOK = lpfnDoAddToFavDlg(m_hWnd, szPath,
  sizeof(szPath)/sizeof(szPath[0]), szTitle,
  sizeof(szTitle)/sizeof(szTitle[0]), pidlFavorites);
  CoTaskMemFree(pidlFavorites);

  if (bOK)
  CreateInternetShortcut( szURL, szPath, "");  //创徏Internet快捷方式
  }
  }
  FreeLibrary(hMod);
  }
  return;
  }

  实现CreateInternetShortcut函数创徏Internet快捷方式Q可以用dINI文g的方法,但更好的则是利用IUniformResourceLocator接口?/p>


  HRESULT CMyHtmlView::CreateInternetShortcut(LPCSTR pszURL, LPCSTR pszURLfilename,
  LPCSTR szDescription,LPCTSTR szIconFile,int nIndex)
  {
  HRESULT hres;

  CoInitialize(NULL);

  IUniformResourceLocator *pHook;

  hres = CoCreateInstance (CLSID_InternetShortcut, NULL, CLSCTX_INPROC_SERVER,
  IID_IUniformResourceLocator, (void **)&pHook);

  if (SUCCEEDED (hres))
  {
  IPersistFile *ppf;
  IShellLink *psl;

  // Query IShellLink for the IPersistFile interface for
  hres = pHook->QueryInterface (IID_IPersistFile, (void **)&ppf);
  hres = pHook->QueryInterface (IID_IShellLink, (void **)&psl);

  if (SUCCEEDED (hres))
  {
  WORD wsz [MAX_PATH]; // buffer for Unicode string

  // Set the path to the shortcut target.
  pHook->SetURL(pszURL,0);

  hres = psl->SetIconLocation(szIconFile,nIndex);

  if (SUCCEEDED (hres))
  {
  // Set the description of the shortcut.
  hres = psl->SetDescription (szDescription);

  if (SUCCEEDED (hres))
  {
  // Ensure that the string consists of ANSI characters.
  MultiByteToWideChar (CP_ACP, 0, pszURLfilename, -1, wsz, MAX_PATH);

  // Save the shortcut via the IPersistFile::Save member function.
  hres = ppf->Save (wsz, TRUE);
  }
  }

  // Release the pointer to IPersistFile.
  ppf->Release ();
  psl->Release ();
  }

  // Release the pointer to IShellLink.
  pHook->Release ();

  }
  return hres;
  }

  好,上面的方法虽焉烦一点,但ȝ解决?#8220;模态窗?#8221;的问题,使得我们的程序不至于让用户鄙视。但是问题又来了Q我们发?#8220;允许脱机使用”是Disabled的,?#8220;自定?#8221;也就无从谈v了,管90%的h都没有用过IE提供的脱机浏览?br>

  N我们的希望要破灭吗?我们一斚w惛_调用“AddFavorite”函数一L(fng)不必手动创徏链接Q一斚w又要模态显C窗口,像IE那样Q还能自定义脱机览?/p>

  3、脚本方?/p>

  许多|页上都?x)有一个按钮或链接“d本页到收藏夹”Q实际上通过下面的脚本显C模态的“d到收藏夹”对话框将|页加入到收藏夹?/p>


  window.external.AddFavorite(location.href, document.title);

  q里的external对象是WebBrowser内置的COM自动化对象,以实现对文档对象模型QDOMQ的扩展Q我们也可以通过 IDocHostUIHandler实现自己的扩展).查阅MSDN可以得知external对象的的Ҏ(gu)与IShellUIHelper接口提供的方? 是一L(fng)。我们有理由怿QIShellUIHelper提供了对WebBrowser内置的external对象的访问,如果在适当的地方创? IShellUIHelper接口的实例,也许调用“AddFavorite”函数昄出来的就是模态对话框了。问题是我们q没有找到这L(fng)地方?/p>

  从上面的脚本Q我们很自然地又惛_另一个方法。如果能够让|页来执行上面的脚本Q岂不是问题p决了Q说做就做,如下Q?/p>


  void CMyHtmlView::OnFavAddtofav()
  {
  CString strUrl = GetLocationURL();
  CString strTitle = GetLocationName();
  CString strjs = "javascript:window.external.AddFavorite('" + strUrl + "'," + "'" + strTitle + "');";
  ExecScript(strjs);
  }

  void CMIEView::ExecScript(CString strjs)
  {
  CComQIPtr<IHTMLDocument2>   pHTMLDoc = (IHTMLDocument2*)GetHtmlDocument();
  if ( pHTMLDoc != NULL  )
  {
  CComQIPtr<IHTMLWindow2>   pHTMLWnd;
  pHTMLDoc->get_parentWindow( &pHTMLWnd );

  if ( pHTMLWnd != NULL  )
  {
  CComBSTR bstrjs = strjs.AllocSysString();
  CComBSTR bstrlan = SysAllocString(L"javascript");
  VARIANT varRet;
  pHTMLWnd->execScript(bstrjs, bstrlan, &varRet);
  }
  }
  }

  先从CHtmlView获得文档的父H口window对象的指针,再调用其Ҏ(gu)execScript来执行脚本(事实上可以执行Q意的脚本Q? 试验发现Q这个方法非常有效,不仅H口是模态的Q而且不需要手动创建链接,更重要的?#8220;允许脱机使用”?#8220;自定?#8221;按钮也可以用了?/p>

  4、问题仍旧没有解?/p>

  执行脚本的方式看h有效Q可一旦我们的E序实现了IDocHostUIHandler接口对WebBrowserq行高控制Q就?x)发C? 执行的脚本包含有?#8220;external”对象的调用,׃(x)出现“找不到对?#8221;的脚本错误。原因是当MSHTML解析引擎Qƈ非WebBrowserQ检? 到宿dCIDocHostUIHandler接口Q就?x)调用其GetExternalҎ(gu)以获得一个用以扩展DOM的自动化接口的引用?/p>


  HRESULT IDocHostUIHandler::GetExternal(IDispatch **ppDispatchQ?/p>

  但有时候我们ƈ没有惌扩展DOMQ同时我们还希望WebBrowser使用它自qDOM扩展。糟p的是GetExternalҎ(gu)的文档中 说这U情况下必须把ppDispatch讄为NULLQ换句话_(d)W(xu)ebBrowserq它内置的external对象也不用了Q那我们? window.external.AddFavorite变得无处ؓ(f)家了?/p>

  我曾多方试WebBrowser内置的external对象扑և来,虽然都没有成功,但是解决问题的方法却被我扑ֈ了?/p>

  5、完的Ҏ(gu)

  WebBrowser内置的external对象我们虽然找不刎ͼ但它肯定存在Q我们只要想办法让WebBrowser自己完成对其调用卛_? 实现非常单,扑ֈWebBrowser中包含的“Internet Explorer_Server”H口的句柄,发一个消息就完成了。下面的代码中假设m_hWndIE是“Internet Explorer_Server”H口的句柄?/p>


  #define ID_IE_ID_ADDFAV 2261
  ::SendMessage( m_hWndIE, WM_COMMAND, MAKEWPARAM(LOWORD(ID_IE_ID_ADDFAV), 0x0), 0 );

  试一试成果,是不是和在Internet Explorer中选择“d到收藏夹”的效果一模一栗?/p>

  至于Z么这样做Q后l文章再说?/p>


]]>
Internet Explorer~程q??http://m.shnenglu.com/mydriverc/articles/28956.html旅?/dc:creator>旅?/author>Sun, 29 Jul 2007 07:10:00 GMThttp://m.shnenglu.com/mydriverc/articles/28956.htmlhttp://m.shnenglu.com/mydriverc/comments/28956.htmlhttp://m.shnenglu.com/mydriverc/articles/28956.html#Feedback0http://m.shnenglu.com/mydriverc/comments/commentRss/28956.htmlhttp://m.shnenglu.com/mydriverc/services/trackbacks/28956.html  关键字:(x)d到收藏夹Q整理收藏夹QDoAddToFavDlgQ?DoOrganizeFavDlg

   1、整理收藏夹

  调用“整理收藏?#8221;对话框(如下Q,基本上来说都用的是同一个方法,卌?#8220;shdocvw.dll”中的“DoOrganizeFavDlg”函数Q把父窗口句柄和收藏夹\径作为参C入即可?/p>


 

   2、代?/strong>

  代码实例如下所C,值得注意的是?#8220;shdocvw.dll”的处理,为避免重复调用,应该先检查其是否已经在内存中?/p>


  void CMyHtmlView::OnFavOrganizefav()
  {
  typedef UINT (CALLBACK* LPFNORGFAV)(HWND, LPTSTR);

  bool bResult = false;

  HMODULE hMod = ::GetModuleHandle( _T("shdocvw.dll") );

  if (hMod == NULL)//如果"shdocvw.dll"未载入则蝲入之
  {
  hMod = ::LoadLibrary( _T("shdocvw.dll") );

  if (hMod == NULL)
  {



  MessageBox( _T("The dynamic link library ShDocVw.DLL cannot be found."),
  _T("Error"), MB_OK | MB_ICONSTOP );
  return;
  }
  LPFNORGFAV lpfnDoOrganizeFavDlg = (LPFNORGFAV)
  ::GetProcAddress( hMod, "DoOrganizeFavDlg" );

  if (lpfnDoOrganizeFavDlg == NULL)
  {
  MessageBox( _T("The entry point DoOrganizeFavDlg cannot be found\n")
  _T("in the dynamic link library ShDocVw.DLL."),
  _T("Error"), MB_OK | MB_ICONSTOP );
  return;
  }

  TCHAR szPath [ MAX_PATH ];
  HRESULT hr;

  hr = ::SHGetSpecialFolderPath( m_hWnd, szPath, CSIDL_FAVORITES, TRUE );
  if (FAILED(hr))
  {
  MessageBox( _T("The path of the Favorites folder cannot be found."),
  _T("Error"), MB_OK | MB_ICONSTOP );
  return;
  }

  bResult = (*lpfnDoOrganizeFavDlg) ( m_hWnd, szPath ) ? true : false;

  ::FreeLibrary( hMod );
  }
  else//如果"shdocvw.dll"已经在调用者进E的地址I间中则直接使用?br>  {
  LPFNORGFAV lpfnDoOrganizeFavDlg = (LPFNORGFAV)
  ::GetProcAddress( hMod, "DoOrganizeFavDlg" );

  if (lpfnDoOrganizeFavDlg == NULL)
  {
  MessageBox( _T("The entry point DoOrganizeFavDlg cannot be found\n")
  _T("in the dynamic link library ShDocVw.DLL."),
  _T("Error"), MB_OK | MB_ICONSTOP );
  return;
  }

  TCHAR szPath [ MAX_PATH ];
  HRESULT hr;

  hr = ::SHGetSpecialFolderPath( m_hWnd, szPath, CSIDL_FAVORITES, TRUE );
  if (FAILED(hr))
  {
  MessageBox( _T("The path of the Favorites folder cannot be found."),
  _T("Error"), MB_OK | MB_ICONSTOP );
  return;
  }


  bResult = (*lpfnDoOrganizeFavDlg) ( m_hWnd, szPath ) ? true : false;
  }

  return;


  }

   3、讨?/strong>

  实际上,?#8220;DoOrganizeFavDlg”函数的原型声明我们可以看刎ͼ׃需要一个\径,所?#8220;整理收藏?#8221;对话框其实不仅可以用来整 理收藏夹Q还可以整理盘上的目录。而且所谓的整理也不q是提供了一个对话框使用L(fng)h比较方便而已Q和直接在资源管理器中整理没有实质性的差别。因? 调用“整理收藏?#8221;对话框的Ҏ(gu)从IE4.0开始就没有变过Q除了对话框的布局有所改变?/p>


  typedef UINT (CALLBACK* LPFNORGFAV)(HWND, LPTSTR);

  IE 4.0?#8220;整理收藏?#8221;对话?br>

  IE 4.0?#8220;整理收藏?#8221;对话框(原本的设计)

  “d到收藏夹”׃同了Q?#8220;DoAddToFavDlg”函数不再?#8220;DoOrganizeFavDlg”函数一样对所有IE的版本都适用?/p>

   参考资料:(x)

  MSDN: Adding Internet Explorer Favorites to Your Application




]]>
Internet Explorer~程q??http://m.shnenglu.com/mydriverc/articles/28955.html旅?/dc:creator>旅?/author>Sun, 29 Jul 2007 07:09:00 GMThttp://m.shnenglu.com/mydriverc/articles/28955.htmlhttp://m.shnenglu.com/mydriverc/comments/28955.htmlhttp://m.shnenglu.com/mydriverc/articles/28955.html#Feedback0http://m.shnenglu.com/mydriverc/comments/commentRss/28955.htmlhttp://m.shnenglu.com/mydriverc/services/trackbacks/28955.html  除了打开Internet上的|页QInternet Explorerq能够浏览本地文件夹及文件。如果浏览的是PDF文档或Office文档Q有时候你?x)发现当调用Navigate("xxx.doc") 的时候,Adobe Reader/Acrobat或Office{Document Servers?x)在IE中嵌入自q一个实例以打开相应的文Ӟ当然有时候也?x)在独立的Acrobat或OfficeH口中打开文g?

  在Adobe Reader/Acrobat的属性设|窗口中Q我们可以找?#8220;Display PDF in browser”的选项Q如果勾上,则Navigate("xxx.pdf")会(x)以嵌入的方式在IE中浏览PDF文gQ否则在独立的Adobe Reader/AcrobatH口中浏览。但在Office?#8220;选项”对话框中我们找不到这L(fng)讄?/p>

  问题Q如何在自己的浏览器中控制Officeq类Ole Servers的打开方式Q?br>
  {案Q修Ҏ(gu)件夹选项Q或修改注册表?br>
  Ҏ(gu)1、如下所C,从控刉板中打开“文g?#8221;选项Q在“文gcd”属性页上找到相应的文g后缀名,?#8220;DOC”Q点?#8220;高”按钮Q在弹出?#8220;~辑文gcd”对话框中?#8220;在同一H口中浏?#8221;的选项Q如果勾上,则以嵌入IE的方式打开文档Q否则在独立H口中打开?br>



  Ҏ(gu)2、直接修Ҏ(gu)册表?br>
  ?#8220;HKEY_LOCAL_MACHINE\SOFTWARE\Classes”键gQ保存了各种文gcd的注册信息,以Office文档ZQ与文档相关键值如下?br>
  文档cd 键?br>
  Microsoft Excel 7.0 worksheet Excel.Sheet.5

  Microsoft Excel 97 worksheet Excel.Sheet.8

  Microsoft Excel 2000 worksheet Excel.Sheet.8

  Microsoft Word 7.0 document Word.Document.6

  Microsoft Word 97 document Word.Document.8

  Microsoft Word 2000 document Word.Document.8

  Microsoft Project 98 project MSProject.Project.8

  Microsoft PowerPoint 2000 document PowerPoint.Show.8

如果我们要修改Word文档的打开方式Q,则在“HKEY_LOCAL_MACHINE\SOFTWARE\Classes\ Word.Document.8”下新Z个名?#8220;BrowserFlags”Q类型ؓ(f)“REG_DWORD”的子键|如果讄其gؓ(f)“8”Q则在独? 的窗口中打开Word文档Q否则在嵌入IE的WordH口中打开文档?br>
  注:(x)Microsoft Excel 7.0 worksheetE有不同Q应讄BrowserFlags的gؓ(f)“9”方可在独立的H口中打开文档?br>

参考资料:(x)

  MSDNQ?59970QIn-Place Activating Document Servers in Internet Explorer

MSDNQ?62059QHow to configure Internet Explorer to open Office documents in the appropriate Office program instead of in Internet Explorer


]]>
Internet Explorer~程q?一)http://m.shnenglu.com/mydriverc/articles/28954.html旅?/dc:creator>旅?/author>Sun, 29 Jul 2007 07:08:00 GMThttp://m.shnenglu.com/mydriverc/articles/28954.htmlhttp://m.shnenglu.com/mydriverc/comments/28954.htmlhttp://m.shnenglu.com/mydriverc/articles/28954.html#Feedback0http://m.shnenglu.com/mydriverc/comments/commentRss/28954.htmlhttp://m.shnenglu.com/mydriverc/services/trackbacks/28954.htmlTWebBrowser~程q?/font>》,发表在自q个h主页“阿甘的家”上,得到了不网友的回应Q也被许多网站{载。此后相当长的时间内不断回答|友的提问,收获良多?

  光正是多窗口浏览器全面开q日子Q无奈手头事情太多,我的作品Multiple iExplorer也一直未能问世,至今遗憾。后来常与GoSurf的作者交学?fn),替他解决了不问题,也从他那里学到许多。如今GoSurf有了比较 固定的用L(fng)Q有我一份功劻I是一U安慰吧Q他也一度在GoSurf官方主页上将我列为核心技术支持,但我后来因ؓ(f)工作和学?fn)的关系很少再和他联p,? 在惭愧?/p>

  回头再看当时的文章,错误实在不少Q认识也比较薄Q有些问题更是一直没有得到解冻I所以我觉得有必要在前文的基上,q旉我U篏的关于Internet Explorer~程的问题比较完整地写出来,希望对自己有个交代,对大家有一些帮助?/p>

  是ؓ(f)序?/p>

   Internet Explorer~程qͼ一QWebBrowserq是WebBrowser_V1

  你的机器上L存在着“?#8221;个WebBrowserQ一个叫WebBrowserQ另一个叫WebBrowser_V1Q其CLASSID如下Q?/p>


  CLASS_WebBrowser: TGUID = '{8856F961-340A-11D0-A96B-00C04FD705A2}';
  CLASS_WebBrowser_V1: TGUID = '{EAB22AC3-30C1-11CF-A7EB-0000C05BAE0B}';

  它们分别对应的接口是IWebBrowser2和IWebBrowser。问题是我们该用哪一个呢Q?br>  按照微Y的推荐,应该量使用 前者,因ؓ(f)后者是为兼容Internet Explorer 3.x而保留的Q尽它能够响应来自Internet Explorer 3.x?.x?.x?.x的事ӞQ相应的IWebBrowser和IWebBrowserApp接口也应抛弃?/p>

  ׃Internet Explorer 3.xq代久远Q导致WebBrowser_V1提供的事件少得可怜,但值得一提的是它提供的两个事件OnNewWindow? OnFrameBeforeNavigate有着与OnBeforeNavigate几乎相同的参敎ͼ(x)


  OnBeforeNavigate(
  BSTR URL,
  long Flags,
  BSTR TargetFrameName,
  VARIANT* PostData,
  BSTR Headers,
  BOOL FAR* Cancel)


  OnNewWindow(
  BSTR URL,
  long Flags,
  BSTR TargetFrameName,
  VARIANT* PostData,
  BSTR Headers,
  BOOL FAR* Processed)

  OnFrameBeforeNavigate(
  BSTR URL,
  long Flags,
  BSTR TargetFrameName,
  VARIANT* PostData,
  BSTR Headers,
  BOOL FAR* Cancel)

  所以用WebBrowser_V1使得我们的浏览器在有新窗口打开时能够轻易捕捉到其URL及相关的数据Q如果将Processed讄为TRUEQ则可取消新H口的弹出。同P处理Frame也比在WebBrowser中来得容易?/p>

  但WebBrowser_V1的致命弱Ҏ(gu)它不支持高接口Q如IDocHostUIHandlerQ即便我们实C IDocHostUIHandler接口Q也不会(x)被WebBrowser_V1调用。所以希望在自己的浏览器中实现XP的界面主题、扩展IE的DOM QDocument Object ModelQ等高控制的话Q就肯定不能选择WebBrowser_V1了?/p>

  处理新窗口实在是很麻烦的一件事Q不知道微YZ么在新版本的OnNewWindow2事g中去掉了URLq样的参敎ͼ而且OnNewWindow2事g不能完全捕捉到所有的新窗口打开。但如果安装了Windows XP SP2的话Q好处又回来了?/p>

  Windows XP SP2对Internet Explorer 6作了升Qƈ且提供了一个新的事件OnNewWindow3Q它在OnNewWindow2事g之前发生Q也包含了让我们能够加以qo(h)处理的新H口? URL{参敎ͼ再加上INewWindowManager接口Q就是实现Windows XP SP2中过滤广告窗口功能的基础?/p>


]]>
BHO开发基http://m.shnenglu.com/mydriverc/articles/28951.html旅?/dc:creator>旅?/author>Sun, 29 Jul 2007 06:59:00 GMThttp://m.shnenglu.com/mydriverc/articles/28951.htmlhttp://m.shnenglu.com/mydriverc/comments/28951.htmlhttp://m.shnenglu.com/mydriverc/articles/28951.html#Feedback0http://m.shnenglu.com/mydriverc/comments/commentRss/28951.htmlhttp://m.shnenglu.com/mydriverc/services/trackbacks/28951.html文g览器(exploer.exeQ应用于文gpȝQ和Internet览? Qiexplore.exeQ应用于互联|资源)?/span>׃q两个浏览器功能强大Q而且又与Windows操作pȝ捆绑销售,最l也成Z览器的标准。但 有时候,Zl浏览器加入一些新的特性,我们往往?x)重新设计一个自q览器。新的浏览器模仿标准览器的大部分功能,同时加入新特性。这U做法最直观Q? 但实际上也是相对于微软的重复力_Q且工作量比较大。其实,使用BHO插gQ一切都变得很简单?br>
BHOQBrowser Help ObjectsQ,是实C特定接口的COMlg。开发好的BHO插g在注册表特定的位|注册好后,每当微Y的浏览器启动QBHO实例׃(x)被创建。在览 器工作的工程中,BHO?x)接收到很多事gQ比如浏览器览新的地址、前q或后退、生成新的窗口、浏览器退出等{;BHO可以在这些事件的响应中实C览 器的交互?br>
下面Q我们首先来介绍一下BHO的工作原理。上面我们已l提刎ͼBHO是COMlgQ而且一定实CIObjectWithSite接口。这些组仉了在 注册表中注册为COM Server外,q必d它们的CLSID在HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindows CurrentVersionExplorerBrowser Helper Objects下注册ؓ(f)子键。微软在设计览器的时候,已经l这些组仉留了I间。每当浏览器启动Ӟ览器会(x)首先在上q注册表位置查看是否有注册的 BHO CLSIDQ如果有则分别创Z个实例,q对BHO实例q行初始化,建立交互q接。(注:(x)BHO实例只有在创建它的浏览器H口销毁时才被释放。)下图演示 了BHO的创E:(x)
说明 createbho.jpg

成功创徏的BHOQ不仅可以得到各U标准的览器操作事Ӟq做出响应;q可以定制浏览器的菜单、工h{界面元素;更或者可以安装钩子函敎ͼ监视览? 的一举一动。值得注意的是Q用BHO插gQInternet览器要求在4.0以上版本Q如果是文g览器,操作pȝ要求是Windows 95/98/2000或Window NT 4.0以上版本Qƈ且Shell的版本在4.71以上。下面是支持BHOҎ(gu)的pȝ一览表Q?br>
Shell版本 操作pȝ版本 支持BHO
4.00 Windows 95 and Windows NT 4.0QIE版本?4.0Q?仅IE4.0
4.71 Windows 95 and Windows NT 4.0QIE版本?4.0Q?IE和文件浏览器
4.72 Windows 98 IE和文件浏览器
5.00   Windows 2000 IE和文件浏览器

接下去,W者就来介l一下如何开发B(ti)HO插gQ开发环境ؓ(f)VC6.0Q用ATLQ,安装Platform SDK中的Internet Development SDK。首先,启动VC的ATL COM AppWizardQ生成一个项目名为BhoPluginQ其余均采用默认讄。接着Q我们就来分步详l阐q?br> W一步,增加一个ATL Object到该目中。VC菜单Insert->New ATL Object…Q在弹出的对话框中选择“Internet Explorer Object”Q输入COMcdQ在Short Name后输入EyeOnIEQ其它各会(x)自动生成Q。完成后Q我们可以看到CEyeOnIEcL一个基cIObjectWithSiteImplQ这? 是实现IObjectWithSite接口的模版类?br> W二步,实现IObjectWithSite的接口方法。在q之前,我们要先定义几个成员变量QCComQIPtr<IWebBrowser2, &IID_IWebBrowser2> mWebBrowser2Q(需要加?include "ExDisp.h"Q,用以保存?gu)览器组件的指针QDWORD mCookieQ用以保存与览器的q接ID。IObjectWithSite有两个接口方法:(x)SetSite和GetSite。我们只需重蝲 SetSitep了。在EyeOnIE.h中增加函数声明STDMETHOD(SetSite)(IUnknown *pUnkSite)Q在EyeOnIE.cpp实现如下Q?br> STDMETHODIMP CEyeOnIE::SetSite(IUnknown *pUnkSite)
{
USES_CONVERSION;

if (pUnkSite)
{
mWebBrowser2 = pUnkSite;
if (mWebBrowser2)
{
return RegisterEventHandler(TRUE);
}
}
return E_FAIL;
}

HRESULT CEyeOnIE::RegisterEventHandler(BOOL inAdvise)
{
CComPtr<IConnectionPoint> spCP;
// Receives the connection point for WebBrowser events
CComQIPtr<IConnectionPointContainer, &IID_IConnectionPointContainer> spCPC(mWebBrowser2);
HRESULT hr = spCPC->FindConnectionPoint(DIID_DWebBrowserEvents2, &spCP);
if (FAILED(hr))
return hr;

if (inAdvise)
{
// Pass the event handlers to the container
hr = spCP->Advise(reinterpret_cast<IDispatch*>(this), &mCookie);
}
else
{
spCP->Unadvise(mCookie);
}
return hr;
}
我们可以看到QSetSite的参数实际上指向的是览器组件。在SetSite实现中,我们首先保存?gu)览器组件指针,然后该BHO向浏览器注册Z件处理器?br> W三步,实现IDispatch接口Ҏ(gu)。事件处理也在IDispatch::Invoke中实玎ͼ各个事g的ID在ExDispID.h中定义)? BHO可能?x)接收到很多事gQ但我们只需要响应我们感兴趣的那一部分。首先在EyeOnIE.h中增加该函数的声明,在EyeOnIE.cpp的实CQ? W者试着响应览器浏览一个地址之前发出的事?a name="baidusnap1"> STDMETHODIMP CEyeOnIE::Invoke(DISPID dispidMember,REFIID riid, LCID lcid,
WORD wFlags, DISPPARAMS * pDispParams,
VARIANT * pvarResult,EXCEPINFO * pexcepinfo,
UINT * puArgErr)
{
USES_CONVERSION;

if (!pDispParams)
return E_INVALIDARG;

switch (dispidMember)
{
//
// The parameters for this DISPID are as follows:
// [0]: Cancel flag - VT_BYREF|VT_BOOL
// [1]: HTTP headers - VT_BYREF|VT_VARIANT
// [2]: Address of HTTP POST data - VT_BYREF|VT_VARIANT
// [3]: Target frame name - VT_BYREF|VT_VARIANT
// [4]: Option flags - VT_BYREF|VT_VARIANT
// [5]: URL to navigate to - VT_BYREF|VT_VARIANT
// [6]: An object that evaluates to the top-level or frame
// WebBrowser object corresponding to the event.
//
case DISPID_BEFORENAVIGATE2 :
{
LPOLESTR lpURL = NULL;
mWebBrowser2->get_LocationURL(&lpURL);
char * strurl;
if (pDispParams->cArgs >= 5 && pDispParams->rgvarg[5].vt == (VT_BYREF|VT_VARIANT))
{
CComVariant varURL(*pDispParams->rgvarg[5].pvarVal);
varURL.ChangeType(VT_BSTR);
strurl = OLE2A(varURL.bstrVal);
}
if (strstr(strurl, "girl.com"))
{
*pDispParams->rgvarg[0].pboolVal = TRUE;
::MessageBox(NULL, _T("该网已被禁?"),_T("Warning"),MB_ICONSTOP);
return S_OK;
}
break;
}

case DISPID_NAVIGATECOMPLETE2:
break;
case DISPID_DOCUMENTCOMPLETE:
break;
case DISPID_DOWNLOADBEGIN:
break;
case DISPID_DOWNLOADCOMPLETE:
break;
case DISPID_NEWWINDOW2:
break;
case DISPID_QUIT:
RegisterEventHandler(FALSE);
break;
default:
break;
}

return S_OK;
}
我们看到Q当用户览的新地址包含"girl.com"字符的时候,览器就?x)弹Z个警告对话框Qƈ且停止进一步的动作。另外值得注意的是Q在DISPID_QUIT事gQ浏览器要退出)的响应中Q我们将BHO事g处理器进行了注销?br> W四步,因ؓ(f)BHO可能?x)被文g览器加载。如果我们不惌P我们p在DllMain中对加蝲者进行判断,参考如下:(x)
extern "C"
BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID /*lpReserved*/)
{
if (dwReason == DLL_PROCESS_ATTACH)
{
// Check who's loading us.
// If it's Explorer then "no thanks" and exit...
TCHAR pszLoader[MAX_PATH];
GetModuleFileName(NULL, pszLoader, MAX_PATH);
_tcslwr(pszLoader);
if (_tcsstr(pszLoader, _T("explorer.exe")))
return FALSE;

_Module.Init(ObjectMap, hInstance, &LIBID_BHOPLUGINLib);
DisableThreadLibraryCalls(hInstance);
}
else if (dwReason == DLL_PROCESS_DETACH)
_Module.Term();
return TRUE; // ok
}
最后,别忘了修Ҏ(gu)册表文gQ追加BHO的注册信息。在EyeOnIE.rgs文g的下面增加如下代码:(x)
HKLM
{
SOFTWARE
{
Microsoft
{
Windows
{
CurrentVersion
{
Explorer
{
'Browser Helper Objects'
{
{6E28339B-7A2A-47B6-AEB2-46BA53782379}
}
}
}
}
}
}
}
注意Q{6E28339B-7A2A-47B6-AEB2-46BA53782379}是笔者这个BHO的CLSIDQ如果你自己开发B(ti)HOQ这里应该正填写你的CLSID?br>
BHO插g可以实现的功能还有很多,比如|页内容分析、IE界面定制{等。作为ȝQ笔者还要提醒读者一点的是,如果不想让BHO起作用了Q可以注销该插 Ӟ如下格式Qregsvr32 /u yourpathyourbho.dllQ或者直接在注册表中?#8220;Browser Helper Objects”目录下注册的CLSID删掉?



]]>
þþþƷһ| þþƷɧ| þԾƷ| ޹㽶þþþþ| պݺݾþ͵͵ɫۺ96| þþоƷ| ۺϾþĻӰ | ھƷþþþþ99 | þùƷ| ŷAŷaþ| Ʒѿþþ| ˾þ777777| պʮ˽һþ| ɫۺϾþþþۺһ| 69Ʒþþþ777| þ91ᆱƷ2020| ŷ޹Ʒþþþ| þˬˬƬAV| 99þùۺϾƷˮ| պ޹ۺϾþþ| þþþһvr| 91Ʒ91þþþþ | ˾þþþƷ| ɫúݺݾþۺ| AVҰ¾þ| þ99Ʒþþþþò| þþþþþƷþþþ| þŮˬŮˬ| þ˾Ʒһ| Ʒþþþþۺձ| ˾þۺӰԺ| ݺݾþ| ݺݾƷþþĻ | ݺݺɫۺϾþ| þۺ77777鶹| 97ȾþƵƷ99| ҹƷþþþó| ĻѾþ| ƷþþþþĻ| պþþþƷӰԺҳ| ɫ͵͵þһ|