王朝网络
分享
 
 
 

Windows 2000 UI 新特点之一:信息条提示(Infotip)

王朝vc·作者佚名  2006-01-17
宽屏版  字体: |||超大  

Windows 2000 UI 新特点之一:信息条提示(Infotip)

原文参见:MSDN Magazine March 2000

编译/赵湘宁

本文源代码

本文假设您熟悉windows的外壳编程及ATL。

摘要:

Windows 2000引入了许多很有用的用户界面新特点,我们能在自己的应用程序中定制和实现这些用户界面。本文是由一系列文章组成,将探讨包括信息提示(Infotip)、增强文件夹特性、搜索管理、图标覆盖和快速启动工具条在内的几个新的UI编程,使用它们来丰富系统外壳的功能。

阅读本篇系列文章之后,您将学会Windows 2000用户界面编程的几个新特点:

如何为文件提供“infotips”(信息条提示)特性;

如何创建一个定制的栏目管理器扩展(column handler extension),它使我们能通过Windows的资源管理器在“查看”菜单的“详细资料”栏的视图中看到新创建的文件属性栏目。

为了进一步扩展外壳,我们还将另外实现几个界面特点:搜索管理、清除管理、使用属性页的文件夹定制、图标覆盖、以及上下文菜单外壳扩展。

随着 Windows 操作系统的不断更新,其用户界面也在随之推陈出新,甚至有一些人已经在抱怨微软公司花太多的精力来开发用户界面,而在操作系统的其它功能上创新不够。这个说法是否正确,有待广大Windows用户来评判。

探究 Windows 2000 的几个UI新特点。可以发现Windows用户界面的几个发展趋势:首先是脚本,尤其是WSH将取代命令行;其次是新的用户界面为将来定制自己的应用程序提供了更好的(基于COM的)图形用户界面接口;第三是应用程序将与系统外壳(SHELL)结合得更紧密。

对系统外壳的简单回顾

外壳扩展是一个COM进程内服务器,它由资源管理器 (Explorer) 来调用以响应系统外壳内发生的事件。只有少数几个任务是靠资源管理器与用户定义的应用来协作完成。在开始这些任务之前,资源管理器查找这些注册的模块并加载它们。从概念上讲,这些模块相当于回调函数。而回调函数是由Windows3.1引入并影响了整整一代程序员的著名编程特点。

外壳扩展需要实现一对COM接口:一个提供特定行为,另一个用于初始化目的。另外,外壳扩展必须要有精确的注册方案,它们必须在适当的地方创建正确的注册入口以便资源管理器在需要时能找到并加载它们。

下表列出了目前可获得的所有外壳扩展类型,需要的最小版本号,有关的接口和简单描述:

(表一)

类型

类型说明

适用于

版本

有关的接口

描述

Context Menu

上下文菜单

文件类和外壳对象

Windows 9x

IContextMenu、IContextMenu2、IContextMenu3

允许在外壳对象的上下文菜单中增加新的才单项

Right drag and drop

右拖拽

文件类和外壳对象

Windows 9x

IContextMenu、IContextMenu2、IContextMenu3

允许在右拖拽后出现的上下文菜单中增加新的才单项

Drawing shell Icons

绘制外壳图标

文件类和外壳对象

Windows 9x

IExtractIcon

对于一个文件类来说,可以选择文件在运行时应该显示那个图标

Property Sheet

属性页

文件类和外壳对象

Windows 9x

IShellPropSheetExt

向文件类属性对话框中加入另外的属性表页。也适用于控制面板应用

Left drag and drop

左拖拽

文件类和外壳对象

Windows 9x

IDropTarget

决定在外壳内用鼠标左键拖拽一个对象到另一个对象上时做什么

Clipboard

剪贴板

文件类和外壳对象

Windows 9x

IDataObject

定义如何将对象拷贝到剪贴板以及如何从剪贴板吸取对象

File Hook

文件钩

Windows 9x

ICopyHook

控制整个外壳内的任何文件操作。您可以允许或拒绝这些对文件的操作,但不会通知您成功或失败

Program Execution

外壳执行程序

资源管理器

桌面更新

IShellExecuteHook

拦截(钩)外壳内任何程序的执行

Infotip

信息条提示

文件类和外壳对象

桌面更新

IQueryInfo

当鼠标移到某个文件类型文档上时显示简短文本信息

Column

栏目

文件夹

Windows 2000

IColumnProvider

在资源管理器“查看”菜单的“详细资料”视图中增加新的栏目

Icon Overlay

图标覆盖

资源管理器

Windows 2000

IShellIconOverlay

用定制的图像覆盖图标

Search

搜索

资源管理器

Windows 2000

IContextMenu

在“开始”菜单的“搜索”菜单项中增加新的搜索入口

Cleanup

清除

清除管理器

Windows 2000

IEmptyVolumeCache2

向清除管理器中增加新的入口来恢复磁盘空间

例如,给定某一类文件,外壳扩展允许您添加新的项目到上下文菜单或插入一个附加的属性页到标准属性对话框。虽然可以用任何支持COM组件的工具编写外壳扩展代码,但大多数外壳扩展都是在ATL框架中用C++编写的。

如果您使用VB来做同样的事情会有一些困难,因为您找不到专门的向导或者可以直接使用的设计器来帮助您编写支持特定COM接口的组件。您不得不写一个类型库来描述接口,然后在工程中引用这个类型库并使用实现关键字来声明只对此接口的支持。在VB6.0的光盘中可以找到一个用VB编写的外壳扩展例子。

外壳扩展常常与文档类有关,也就是说外壳扩展的功能只适用于具有某些扩展名的文件。更详细的信息可以参考MSDN库和有关Windows外壳编程的书籍。

有许多用户界面特点已在桌面更新(Desktop Update)中引入----Windows 9x和Windows

NT4.0中有各自的外壳扩展。桌面更新是随IE4.0和Windows 98 一同而来。但应注意桌面更新不是IE5.0的一部分。所以如果您想在NT4.0上安装,需要先安装IE4.0,必须选中桌面更新选项,IE5.0将更新NT4.0和Windows

95现存的设置,否则将不会安装桌面更新。

编写信息条提示(Infotip)外壳扩展

一个典型的外壳扩展应用是帮助用户对文档进行分类。以BMP文件为例,当从文件列表中选中BMP文件时,桌面更新(外壳版本4.72+)会以小图方式提供这个BMP文件的预览,但是它不提供BMP文件的大小及颜色信息。如果您对系统外壳稍加扩展就可以使您的应用程序对BMP文件作更细致的处理,这将大大方便用户的使用。

第一个想到的方案便是为BMP文件添加新的属性页。实际上,这不是最好的方法,因为用户要单击右键,选中“属性”菜单项,再选择正确的标签读取信息。为了达到同样的目的,最佳方法是使用新的信息条提示(Infotips)特性。

信息提示的作用是当鼠标移到某种类型的文件上时,让工具提示(tooltip)控件显示一个简短的文本,这个文本片段提供了关于特定文件的属性细节信息。对于Excel和Word文档,信息提示特性是自动使能的。它显示文档的标题、作者和主题。信息条提示特性是针对特殊类型文件的外壳扩展,其注册方案也很独特。信息条提示扩展接收对当前选中文件的引用,然后作处理以便抽取需要的信息。

图二 BMP文件的 Infotip

图二显示了一个BMP文件的信息提示扩展,为了建立这个扩展,您需要创建一个进程内的服务器,实现IQueryInfo和IPersistFile接口。IQueryInfo用来给外壳提供运行时的

文本。IPersistFile由资源管理器使用,让扩展知道当前鼠标指针指向的文件。本文的例子代码定义了一对从上述两个接口派生的最小限度的ATL基类(IQueryInfoImpl.h

和IPersistFileImpl.h),可以使用它们来建立更专业的类。在源代码中您还能看到嵌入到这个外壳的其它相关类的声明。下面是ATL基类定义:

实现对位图文件的信息提示条(BMP Infotip)

// IPersistFileImpl.h

#include class ATL_NO_VTABLE IPersistFileImpl : public IPersistFile{public: TCHAR m_szFile[MAX_PATH]; // IUnknown STDMETHOD(QueryInterface)(REFIID riid, void** ppvObject) = 0; _ATL_DEBUG_ADDREF_RELEASE_IMPL(IPersistFileImpl) // IPersistFile STDMETHOD(Load)(LPCOLESTR wszFile, DWORD dwMode){ USES_CONVERSION; _tcscpy(m_szFile, OLE2T((WCHAR*)wszFile)); return S_OK; }; STDMETHOD(GetClassID)(LPCLSID){ return E_NOTIMPL; } STDMETHOD(IsDirty)(VOID){ return E_NOTIMPL; } STDMETHOD(Save)(LPCOLESTR, BOOL){ return E_NOTIMPL; } STDMETHOD(SaveCompleted)(LPCOLESTR){ return E_NOTIMPL; } STDMETHOD(GetCurFile)(LPOLESTR FAR*){ return E_NOTIMPL; }};// IQueryInfoImpl.h#include #include class ATL_NO_VTABLE IQueryInfoImpl : public IQueryInfo{public: // IUnknown STDMETHOD(QueryInterface)(REFIID riid, void** ppvObject) = 0; _ATL_DEBUG_ADDREF_RELEASE_IMPL(IQueryInfoImpl) // IQueryInfo::GetInfoTip STDMETHOD(GetInfoTip)(DWORD dwFlags, LPWSTR *ppwszTip){ wcscpy(*ppwszTip, L"InfoTip"); return S_OK; } // IQueryInfo::GetInfoFlags STDMETHOD(GetInfoFlags)(LPDWORD pdwFlags){ *pdwFlags = 0; return E_NOTIMPL; }};// BmpTip.h : Declaration of the CBmpTip coclass#ifndef __BMPTIP_H_#define __BMPTIP_H_#include "resource.h" // main symbols#include "comdef.h" // GUIDs #include "IPersistFileImpl.h" // IPersistFile#include "IQueryInfoImpl.h" // IQueryInfo// CBmpTipclass ATL_NO_VTABLE CBmpTip : public CComObjectRootEx, public CComCoClass, public IQueryInfoImpl, public IPersistFileImpl, public IDispatchImpl{public: CBmpTip(){ HRESULT hr; hr = SHGetMalloc(&m_pAlloc); if (FAILED(hr)) m_pAlloc = NULL; } ~CBmpTip(){ m_pAlloc-Release(); }DECLARE_REGISTRY_RESOURCEID(IDR_BMPTIP)DECLARE_PROTECT_FINAL_CONSTRUCT()BEGIN_COM_MAP(CBmpTip) COM_INTERFACE_ENTRY(IBmpTip) COM_INTERFACE_ENTRY(IQueryInfo) COM_INTERFACE_ENTRY(IPersistFile) COM_INTERFACE_ENTRY(IDispatch)END_COM_MAP()// IQueryInfopublic: STDMETHOD(GetInfoTip)(DWORD, LPWSTR*);private: STDMETHOD(GetBitmapInfo)(CComBSTR*); LPMALLOC m_pAlloc;};#endif //__BMPTIP_H_ PersistFile的Load方法将文件名存储在m_szFile成员变量中,这个方法在初始化过程期间被资源管理器隐含调用。IqueryInfo只包含两个函数,其中GetInfoFlags目前还不被支持并且必须返回E_NOTIMPL。实际上,一旦您实现了IQueryInfoImpl.h 和IPersistFileImpl.h提供的最小限度的派生类,写一个信息条提示扩展是很容易的,先建立一个新的ATL进程内对象并实现IQueryInfo::GetInfoTip方法: HRESULT CBmpTip::GetInfoTip(DWORD dwFlags, LPWSTR* ppwszTip) 参数dwFlags目前不使用,ppwszTip是一个指向Unicode串缓冲的指针,用来返回运行时关于文件的文本。要注意ppwszTip缓冲必须使用标准的外壳内存分配器起来为它分配内存。这个缓冲由应用程序负责分配内存,由外壳来释放分配的内存。为了保证所发生的一切都是线程安全的,请使用SHGetMalloc来获得外壳内存分配器(一个IMalloc对象)的指针。然后,使用IMalloc的Alloc方法分配需要的内存并以Unicode方式存储信息条提示文本。 下面的代码段说明了外壳扩展如何获取和返回文本: CComBSTR bstrInfo;GetBitmapInfo((CComBSTR *)&bstrInfo);*ppwszTip = (WCHAR*) m_pAlloc-Alloc( (bstrInfo.Length() +1) * sizeof(WCHAR) );if (*ppwszTip) wcscpy(*ppwszTip, (WCHAR*)(BSTR)bstrInfo); GetBitmapInfo是一个内部成员,它只是准备一个串来存放图像的大小和颜色。为了得到这个信息,这个函数打开BMP文件并读取bitmap文件的头。

注册信息条提示扩展 信息提示扩展以非标准方式进行注册。通常基于文件的扩展在标识这个文件的注册键下创建它们自己的子树。例如:.ext文件的类名是在HKEY_CLASSES_ROOT下.ext注册键的缺省值。但是,BMP文件的信息提示必须创建下列入口: HKCR \.bmp \shellex \{00021500-0000-0000-C000-000000000046} 这个键的缺省值必须是实现COM对象的CLISID。这个地方的CLSID是IqueryInfo接口的IID,而不是BMP文件的文件类。这就是为什么信息条提示扩展以非标准方式进行注册的原因。另一方面,这个注册方案适用于任何一个处理BMP文件的注册应用程序。实际上,处理某个文件类的应用将自身注册为缺省处理程序的话,它也能改变类名,也能使所有的注册扩展无效。如果MS Paint是缺省处理程序的话,用于BMP文件的类名就是PaintPicture。如果使用另一个程序编辑浏览bitmaps,用于BMP文件的类名可能就不是PaintPicture。 为了能在NT和Windows 2000中正常工作,外壳扩展必须被注册并且要得到系统管理员的批准。许多开发人员都低估了这一点,因为他们多数以管理员的身份登陆到NT系统。在这种情况下可以忽略系统管理员的审批。以下是负责扩展审批的注册入口: HKLM \SOFTWARE \Microsoft \Windows \CurrentVersion \Shell Extensions \Approved 在这个键下,用外壳扩展的CLSID名字创建一个新串值并给出一个描述文本。
如何存储信息条提示设置 在很多情形下都可以应用信息条提示外壳扩展,包括定制的文档和象DLL及EXE这样的本地文件类。图四显示了一个信息条提示应用的例子。它列出了静态链接到给定的EXE或DLL模块的动态链接库的列表。注意在Windows资源管理器的状态条也显示了相同的内容。
图四 DLL 和 EXE 文件的 Infotip Visual Studio 6.0 中有一个很好的工具: Dependency Walker,这个工具也有与信息条提示一样的功能。不同是这个工具是一个独立的可执行程序,你必须得从上下文菜单来运行。 如果您只想知道某个可执行文件依赖的主动态链接库列表,使用本文的外壳扩展就足够了。为了获得静态链接库的列表,本文的代码中使用了ImageHLP API,关于这个API,我将在另文中说明。此外,代码还使用了BindImageEx来请求每个输入函数的有效地址。为此,BindImageEx邦定可执行文件图像并为每一个输入库和函数调用回调函数。您要做的全部工作是写一个回调函数将模块名简单地连结为一个串。 从属列表很有用,但它显示的可能不是每次当您的鼠标移到某个DLL或EXE文件上时您想要的信息。如果能用一个逻辑变量来控制信息条提示特性的使能和取消那不是更好吗?为了实现这个功能,既可以利用注册表,也可以用INI文件来存储这个控制变量的值,但有一个问题是:如何改变存储在注册表或INI文件中的这个值?使用注册表编辑器或者写字板当然可以,但那未免土了点。如果外壳扩展是应用的一部分,那么为应用程序做一个参数选项对话框应该是最好的解决办法。

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
>>返回首页<<
推荐阅读
 
 
频道精选
静静地坐在废墟上,四周的荒凉一望无际,忽然觉得,凄凉也很美
© 2005- 王朝网络 版权所有