Windows 2000 UI 新特点之二
增强的文件夹特性:自定义文件夹栏目
原文参见:MSDN Magazine March 2000
编译/赵湘宁
第一部分 Windows 2000 UI 新特点之一:信息条提示(Infotip)
本文源代码
本文假设您熟悉windows的外壳编程及ATL。
摘要:
本文是关于Windows 2000 UI 新特点系列文章的第二篇,本文将创建一个定制的栏目管理器扩展(column handler extension),它使我们能通过Windows的资源管理器在“查看”菜单的“详细资料”栏的视图中看到新创建的文件属性栏目。 在Windows 2000中,有五种可能的方式来浏览一个文件夹的内容。(虚拟文件夹和名字空间扩展除外)。传统的方式有四种:大图标、小图标、列表和详细资料。第五种方式为:缩略图方式(thumbnail mode)。缩略图方式使用正方形的象素区显示常规的文件对象图标。这种视图模式对于图像文件夹和包含可预览文档的文件夹最有用,如:元文件、图形文件和预览开关打开的MS Office文档。
在所有的浏览方式中,详细资料模式是提供信息最丰富的一种方式。这种方式是通过栏目来组织实现的。在Windows 2000 以前,典型的栏目是:名字、大小、类型和修改日期,可不可以为文件再添加更多的栏目呢?象隐藏、只读或版本号等。答案是肯定的。Windows 2000不但引入了许多可以预定义的栏目,甚至还可以定制和创建自己的栏目。如果您在任何栏目的说明上单击右键,会弹出上下文菜单,包含的菜单项是所有可获得的栏目的一个子集。然后您可以打开和关闭任何栏目,但名字栏除外。(参见图五)

图五 详细资料视图中的栏目
通过选择“更多选项(More)”,还可以显示出整个栏目列表。有 、三个栏目是让人耳目一新的:即创建日期、作者和模块版本。创建日期显示的是文件或文件夹最初创建的日期。作者栏则显示的是按照复合文件的摘要信息(SummaryInformation)头内容指定的文档签名者的名字。尤其是在一个全是Office文档的文件夹中,一眼就能区分出某人写的文档。而且,一旦显示了一个新的栏目,同时也能按这个栏目来对文件排序。注意作者信息只在文档被存为嵌入了摘要信息头的复合文档时才能获得。除了微软的Office文档格式以外(Word、Execel 或PowerPoint),输出摘要信息块的文档类型不多,除了Office文档以外,还有FlashPix图像文件也输出摘要信息块。
在栏目中包含可执行文件版本号“Module Version” (模块版本栏目)是人们期待已久的事情了。图六中显示的就是一个在system32文件夹中使能的模块版本栏目。

图六 Module Version 栏目
通过栏目选择对话框,您可以设置一个缺省的栏目宽度并选择它显示的位置。栏目重新排序使每个文件夹的基本特性,在某个文件夹上通过对属性的调整,总是能使所有文件夹的有相同的外观,方法是在文件夹选项对话框的“视图(View)”标签中按“与当前文件夹一样(Like Current Folder)”按钮。还有一个关于文件夹的设置是“记忆每个文件夹的设置(Remember each folder’s setting)”,这个特性允许您控制是否将全程文件夹选项应用到每一个单个的文件夹。
上面所讲的文件夹是针对相应的文件系统目录而言的。其他类型的文件夹,如名字空间扩展(namespace extensions),由其自己定义非栏目视图。但也有例外,那就是“我的文档”和“Favorites”。它们是名字空间扩展,但它们的内容映象到常规文件夹目录,提供标准的表格式视图并对应到选中的当前文件夹设置。
想要编写基于栏目的名字空间扩展应用,应该提供一种允许从说明栏上单击右键弹出的上下文菜里定制栏目。
如何定义定制栏目
Windows 2000 允许您定制栏目并将它加到列表中(见图五)。为了定义一个新栏目,必须要编写并注册一个新的外壳类型:栏目处理器(Column Hander)。大多数情况下,一个栏目为一个文件类提供特殊信息----例如,BMP文件的尺寸和调色板大小。然而栏目处理器并不绑定到文件类,而是文件夹对象的一个特性。换句话说,您不用在位图文件类子树中注册一个栏目处理器,而要在文件夹子树下注册。用扩展的代码来区分文件,它知道如何有针对性地处理和返回文件的信息。
一个栏目处理器扩展需要实现单接口:IColumnProvider。这样就使得在初始化时与其它需要IPersistFile 或 IShellExtInit 接口的扩展有些轻微的差别(这是因为实际上栏目处理器不适用于文件类)。
建立BMP文件的尺寸栏目
先创建一个新的ATL工程并插入一个对象,将其progID指定为BmpCol.BmpColInfo 。下面是这个扩展的实现源代码:
栏目扩展实现代码// IColumnProviderImpl.h#include <AtlCom.h>#include <ShlObj.h>class ATL_NO_VTABLE IColumnProviderImpl : public IColumnProvider {protected: TCHAR m_szFolder[MAX_PATH];public: // IUnknown STDMETHOD(QueryInterface)(REFIID riid, void** ppvObject) = 0; _ATL_DEBUG_ADDREF_RELEASE_IMPL(IColumnProviderImpl) // IColumnProvider // IColumnProvider::Initialize STDMETHOD(Initialize)(LPCSHCOLUMNINIT psci){ USES_CONVERSION; _tcscpy(m_szFolder, OLE2T((WCHAR*)psci->wszFolder)); return S_OK; } // IColumnProvider::GetColumnInfo STDMETHOD(GetColumnInfo)(DWORD dwIndex, SHCOLUMNINFO *psci){ return S_FALSE; } // IColumnProvider::GetItemData STDMETHOD(GetItemData)(LPCSHCOLUMNID pscid, LPCSHCOLUMNDATA pscd, VARIANT *pvarData){ return S_FALSE; }};// BmpColInfo.h : Declaration of the CBmpColInfo#ifndef __BMPCOLINFO_H_#define __BMPCOLINFO_H_#include "resource.h" // main symbols#include <shlguid.h> // GUID of IColumnProvider#include "IColumnProviderImpl.h" // IColumnProvider base implconst UINT BMPCH_DEFWIDTH = 16;// column default width in chars const UINT BMPCH_MAXSIZE = 80; // max text size const DWORD BMP