ImageVerifierCode 换一换
格式:DOCX , 页数:19 ,大小:136.67KB ,
资源ID:9451342      下载积分:3 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bdocx.com/down/9451342.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(ATL 实现定制的 IE 浏览器栏工具栏和桌面工具栏.docx)为本站会员(b****7)主动上传,冰豆网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰豆网(发送邮件至service@bdocx.com或直接QQ联系客服),我们立即给予删除!

ATL 实现定制的 IE 浏览器栏工具栏和桌面工具栏.docx

1、ATL 实现定制的 IE 浏览器栏工具栏和桌面工具栏ATL 实现定制的 IE 浏览器栏、工具栏和桌面工具栏作者:杨老师下载源代码关键字:Band,Desk Band,Explorer Band,Tool Band,浏览器栏,工具栏,桌面工具栏一、引言最近,由于工作的要求,我需要在 IE 上做一些开发工作。于是在 MSDN 上翻阅了一些资料,根据 MSDN 上的说明我用 ATL 胜利完成了“资本家老板”分配的任务。(并且在白天睡觉的过程中梦到了老板给我加工资啦.)现在,我把 MSDN 上的原文资料,经过翻译整理并把一个 ATL 的实现奉贤给 VCKBASE 上的朋友们。 概念 原理基本band

2、对象必须实现的 COM 接口 IPersistStream IObjectWithSite IDeskBand、IDockingWindow、IOleWindow选择实现的 COM 接口Band 对象注册 ATL 实现 二、概念在翻译的过程中,有两个词汇非常不好理解。第一个词是 Band 对象,词典中翻译为“镶边、裙子边、带子、乐队.”我的英文水平有限,实在不知道应该翻译为什么词汇更合适。于是我毅然决然地决定:在如下的论述中,依然使用 band 这个词!(什么?没听明白?我的意思就是说,我不翻译这个词了)但到底 Band 对象应该如何理解那?请看图一:图一图一中画红圈的地方,分别称作“垂直的浏

3、览器栏”、“水平的浏览器栏”、“工具栏”和“桌面工具栏”。这些“栏”,都可以在 IE 的“查看”菜单中或鼠标右键的上下文快捷方式菜单中显示或隐藏起来。这些界面窗口的实现,其实就是实现一种 COM 接口对象,而这个对象叫 band。这个概念实在是只能意会而无法言传的,我总不能在文章中把它翻译为“总是靠在 IE 主窗口边上的对象”吧?_另外,还有一个词叫 site。这个很好翻译,叫“站点”!。呵呵,我敢打包票,如果你要能理解这个翻译在计算机类文章中的含义,那就只能恭喜你了,你的智慧太高了。(都是学计算机软件的人,做人的差距咋就这么大呢?)在本篇文章中,site 可以这样理解:IE 的主框架四周,就

4、好比是“汽车站”,那些 band 对象,就好比是“汽车”。band 汽车总是可以停靠在“汽车站”上。所以,site 就是“站点”,它也是 COM 接口的对象(IObjectWithSite、IInputObjectSite)。三、原理3.1基本 band 对象Band 对象,从 Shell 4.71(IE 5.0) 开始提供支持。Band 是一个 COM 对象,必须放在一个容器中去使用,当然使用它们就好象使用普通窗口是一样的。IE 就是一个容器,桌面 Shell 也是一个容器,它们提供不同的函数功能,但基本的实现是相似的。Band 对象分三种类型,浏览器栏 band(Explorer band

5、s)、工具栏 band(Tool Bands)和桌面工具栏(Desk bands),而浏览器栏 band 又有两种表现形式:垂直和水平的。那么 IE 和 Shell 如何区分并加载这些 bands 对象呢?方法是:你要对不同的 band 对象,在注册表中注册不同的组件类型(CATID)。Band 样式组件类型CATID垂直的浏览器栏CATID_InfoBand00021493-0000-0000-C000-000000000046水平的浏览器栏CATID_CommBand00021494-0000-0000-C000-000000000046桌面的工具栏CATID_DeskBand000214

6、92-0000-0000-C000-000000000046IE 工具栏不使用组件类型注册,而是使用在注册进行 CLSID 的登记方式。详细情况见 3.3。在例子程序中,实现了全部四个类型的 band 对象,垂直浏览器栏(CVerticalBar)显示了一个 HTML 文件,并且实现了对 IE 主窗口浏览网页的导航等功能;水平的浏览器栏(CHorizontalBar)是一个编辑窗,它同步显示当前网页的 BODY 源文件内容;IE 工具栏(CToolBar)最简单,只是添加了一个空的工具栏;桌面工具栏(CDeskBar)实现了一个单行编辑窗口,你可以在上面输入命令行或文件名称,回车后它会执行 S

7、hell 的打开动作。3.2必须实现的 COM 接口Band 对象是 IE 或 Shell 的进程内服务器,所以它被包装在 DLL 中。而作为 COM 对象,它必须要实现 IUnknown 和 IClassFactory 接口。(大家可以不同操心,因为我们用 ATL 写程序,这两个接口是不用我们自己写代码的。)另外,Band 对象还必须实现 IDeskBand、IObjectWithSite 和 IPersistStream 三个接口:IPersistStream 是持续性接口的一种。当 IE 加载 band 对象的时候,它通过这个接口的 Load 方法传递属性值给对象,让其进行初始化;而当卸

8、载前,IE 则调用这个接口的 Save 方法保存对象的属性。用 ATL 实现这个接口很简单: class ATL_NO_VTABLE Cxxx : . public IPersistStreamInitImpl, / 添加继承 .public: BOOL m_bRequiresSave; / IPersistStreamInitImpl 所必须的变量.BEGIN_COM_MAP(CVerticalBar) . COM_INTERFACE_ENTRY2(IPersist, IPersistStreamInit) COM_INTERFACE_ENTRY2(IPersistStream, IPers

9、istStreamInit) COM_INTERFACE_ENTRY(IPersistStreamInit) .END_COM_MAP()BEGIN_PROP_MAP(Cxxx). / 添加需要持续性的属性END_PROP_MAP() 上面的代码,其实实现的是 IPersistStreamInit 接口,不过没有关系,因为 IPersistStreamInit 派生自 IPersistStream,实例化了派生类,自然就实例化了基类。在例子程序中,我只在桌面工具栏对象中添加了持续性属性,用来保存和初始化“命令行”。另外 COM_INTERFACE_ENTRY2(A,B)表示的含义是:如果想查询

10、A接口的指针,则提供B接口指针来代替。为什么可以这样那?因为B接口派生自A接口,那么B接口的前几个函数必然就是A接口的函数了,自然B接口的地址其实和A接口的地址是一样的了。IObjectWithSite 是 IE 用来对插件进行管理和通讯用的一个接口。必须要实现这个接口的2个函数:SetSite() 和 GetSite()。当 IE 加载 band 对象和释放 band 对象的时候,都要调用 SetSite()函数,那么在这个函数里正好是写初始化和释放操作代码的地方: STDMETHODIMP Cxxx:SetSite(IUnknown *pUnkSite) if( NULL = pUnkSi

11、te ) / 释放 band 的时候 / 如果加载的时候,保存了一些接口 / 那么现在:释放它 else / 加载 band 的时候 m_hwndParent = NULL; / 装载 band 的父窗口(就是带有标题的那个框架窗口) / 这个窗口的句柄,是调用 IUnknown:QueryInterface() 得到 IOleWindow / 然后调用 IOleWindow:GetWindow() 而获得的。 CComQIPtr spOleWindow(pUnkSite); if( spOleWindow ) spOleWindow-GetWindow(&m_hwndParent); if(

12、 !m_hwndParent ) return E_FAIL; / 现在,正好是建立子窗口的时机。 / 注意,子窗口建立的时候,不要使用 WS_VISIBLE 属性 . . / 在例子程序中,用 CAxWindow 实现了一个能包容ActiveX的容器窗口(垂直浏览器栏) / 在例子程序中,用 WIN API 函数 CreateWindow 实现了标准窗口(水平浏览器栏、工具栏) / 在例子程序中,用 CWindowImpl 实现了一个包容窗口(桌面工具栏) /*/ 以下部分,根据 band 对象特有的功能,是可以选择实现的 */ / 如果子窗口实现了用户输入,那么必须实现 IInputObj

13、ect 接口, / 而该接口是被 IE 的 IInputObjectSite 调用的,因此在你的对象 / 中,应该保存 IInputObjectSite 的接口指针。 / 在类的头文件中,定义: / CComQIPtr m_spSite; m_spSite = pUnkSite; / 保存 IInputObjectSite 指针 if( !m_spSite ) return E_FAIL; / 你需要控制 IE 的主框架吗? / 那么在类的头文件中,定义: / CComQIPtr m_spFrameWB; / 然后,先取得 IServiceProvider,再取得 IWebBrowser2 C

14、ComQIPtr spSP(pUnkSite); if( !spSP ) return E_FAIL; spSP-QueryService( SID_SWebBrowserApp, &m_spFrameWB ); if( !m_spFrameWB) return E_FAIL; / 如果你取得了 IE 主框架的 IWebBrowser2 指针 / 那么,当它发生了什么事情,你难道不想知道吗? / 定义:CComPtr m_spCP; CComQIPtr spCPC( m_spFrameWB ); if( spCPC ) spCPC-FindConnectionPoint( DIID_DWebB

15、rowserEvents2, &m_spCP ); if( m_spCP ) m_spCP-Advise( reinterpret_cast( this ), &m_dwCookie ); / 咳 不说了,看源码去吧。这里能干的事情太多了. . return S_OK; IDeskBand 是一个特殊的 band 对象接口,有一个方法函数:GetBarInfo();IDockingWindow 是 IDeskBank 的基类,有3个方法函数:ShowDW()、CloseDW()、ResizeBorderDW();IOleWindow 又是 IDockingWindow 的基类,有2个方法函数:

16、GetWindow()、ContextSensitiveHelp(); 首先声明 IDeskBand ,然后要实现 IDeskBand 接口的共6个函数,这些函数比较简单,不同类型的 band 对象,其实现方法也都基本一致: 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)

17、 / 取得 band 对象的窗口句柄 / m_hWnd 是建立窗口时候保存的 *phwnd = m_hWnd; return S_OK;STDMETHODIMP Cxxx:ContextSensitiveHelp(BOOL fEnterMode) / 上下文帮助,参考 IContextMenu 接口 return E_NOTIMPL;/ IDockingWindowSTDMETHODIMP CVerticalBar:ShowDW(BOOL bShow) / 显示或隐藏 band 窗口 if( m_hWnd ) :ShowWindow( m_hWnd, bShow ? SW_SHOW : SW_

18、HIDE); return S_OK;STDMETHODIMP CVerticalBar:CloseDW(DWORD dwReserved) / 销毁 band 窗口 if( :IsWindow( m_hWnd ) ) :DestroyWindow( m_hWnd ); m_hWnd = NULL; return S_OK;STDMETHODIMP CVerticalBar:ResizeBorderDW(LPCRECT prcBorder, IUnknown* punkToolbarSite, BOOL fReserved) / 当框架窗口的边框大小改变时 return E_NOTIMPL;/

19、 IDeskBandSTDMETHODIMP CVerticalBar:GetBandInfo(DWORD dwBandID, DWORD dwViewMode, DESKBANDINFO* pdbi) / 取得 band 的基本信息,你需要填写 pdbi 参数作为返回 if( NULL = pdbi ) return E_INVALIDARG; / 如果将来需要调用 IOleCommandTarget:Exec() 则需要保存这2个参数 m_dwBandID = dwBandID; m_dwViewMode = dwViewMode; if(pdbi-dwMask & DBIM_MINSIZ

20、E) / 最小尺寸 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;

21、 if(pdbi-dwMask & DBIM_TITLE) / 窗口标题 wcscpy(pdbi-wszTitle,L窗口标题); if(pdbi-dwMask & DBIM_MODEFLAGS) pdbi-dwModeFlags = DBIMF_VARIABLEHEIGHT; if(pdbi-dwMask & DBIM_BKCOLOR) / 如果使用默认的背景色,则移除该标志 pdbi-dwMask &= DBIM_BKCOLOR; return S_OK; 3.3选择实现的 COM 接口有两个接口不是必须实现的,但也许很有用:IInputObject 和 IContextMenu。如果 b

22、and 对象需要接收用户的输入,那么必须实现 IInputObject 接口。IE 实现了 IInputObjectSite 接口,当容器中有多个输入窗口时,它调用 IInputObject 接口方法去负责管理用户的输入焦点。在浏览器栏中需要实现3个函数:UIActivateIO()、HasFocusIO()、TranslateAcceleratorIO()。当浏览器栏激活或失去活性的时候,IE 调用 UIActivateIO 函数,当激活的时候,浏览器栏一般调用 SetFocus 去设置它自己窗口的焦点。当 IE 需要判断哪个窗口有焦点的时候,它调用 HasFocusIO 。当浏览器栏的窗口

23、或其子窗口有输入焦点时,则应返回 S_OK,否则返回 S_FALSE。TranslateAcceleratorIO 允许对象处理加速键,例子程序中没有实现,所以直接返回 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;STDMETHODIM

24、P CExplorerBar:TranslateAcceleratorIO(LPMSG pMsg) return S_FALSE; Band 对象能够通过包容器的 IOleCommandTarget:Exec() 调用执行命令。而 IOleCommandTarget 接口指针,则可以通过调用包容器的 IInputOjbectSite:QueryInterface(IID_IOleCommandTarget,.) 函数得到。CGID_DeskBand 是命令组,当一个 band 对象的 GetBandInfo 被调用的时候,包容器通过 dwBandID 参数指定一个 ID 给 band 对象,对

25、象要保存住这个ID,以便调用 IOleCommandTarget:Exec()的时候使用。ID 的命令有: DBID_BANDINFOCHANGEDBand 的信息变化。设置参数 pvaIn 为 band ID, 该 ID 就是最近一次调用 GetBandInfo 所得到的值,容器会调用 band 对象的 GetBandInfo 函数来更新请求信息。 DBID_MAXIMIZEBAND 最大化 band。设置参数 pvaIn 为 band ID,该 ID 就是最近一次调用 ?GetBandInfo ?所得到的值。 DBID_SHOWONLY 打开或关闭容器中其它的 bands。 设置参数 pv

26、aIn 为VT_UNKNOWN 类型,它可以是如下的值: 值描述pUnkband 对象的 IUnknown 指针,其它的桌面 bands 将被隐藏0隐藏所有的桌面 bands1显示所有的桌面 bands DBID_PUSHCHEVRON在菜单项左边显示“v”的选择标志。容器发送一个 RB_PUSHCHEVRON 消息,当 band 对象接收到通知消息 RBN_CHEVRONPUSHED 提示它显示一个v的标志。设置 IOleCommandTarget:Exec 函数中 nCmdExecOpt 参数为 band ID,该 ID 是最近一次调用 GetBandInfo ?所得到的值,设置 IOle

27、CommandTarget:Exec 函数中 pvaIn 参数为 VT_I4 类型,这是应用程序定义的一个值,它通过通知消息 RBN_CHEVRONPUSHED 中lAppValue 回传给 band 对象。 3.4Band 对象注册Band 对象必须注册为一个 OLE 进程内的服务器,并且支持 apartment 线程公寓。注册表中默认键的值是表示菜单的文字。对于浏览器栏,它加到 IE 菜单的“查看浏览器栏”中;对于工具栏 band ,它加到 IE 菜单的“查看工具栏”中;对于桌面 band, 它加到系统任务栏的快捷菜单中。在菜单资源中,可以使用“&”指明加速键。通常,一个基本的 band

28、对象的注册表项目是:HKEY_CLASSES_ROOT CLSID 你的 band 对象的 CLSID (Default) = 菜单的文字 InProcServer32 (Default) = DLL 的全路径文件名 ThreadingModel= Apartment工具栏 bands 还必须把它们的 CLSID 注册到 IE 的注册表中。在 HKEY_LOCAL_MACHINESoftwareMicrosoftInternet ExplorerToolbar 下给出 CLSID 作为键名,而其键值是被忽略的。HKEY_LOCAL_MACHINE Software Microsoft Internet Explorer Toolbar 你的 band 对象的 CLSID还有几个可选的注册表项目(例子程序并不是这样实现的)。比如,你想让浏览器栏显示 HTML 的话,必须要如下设置注册表: HKEY_CLASSES_ROOT CLSID 你的 Band 对象的 CLSID Instance CLSID (Default) = 4D5C8C2A-D075-11D0-B416-00C04FB90376同时,如果要指定一个本地的 HTML 文件,那么要如下设置: HKEY_CLASSES_R

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1