C++ 中的 Windows 7 实用程序:为 Jump Lists 添加自定义任务





5.00/5 (15投票s)
在 Windows 7 的应用程序 Jump List 中创建自定义任务。
目录
引言
正如我在 上一篇关于 Jump Lists 的文章 中所见,Windows 7 允许应用程序使用 IApplicationDestinations
和 ICustomDestinationList
接口来自定义其 Jump List。在本文中,我们将超越内置类别,看看如何通过添加自定义任务来自定义 Jump List,以及如何在程序中处理这些任务。
与本系列的其他文章一样,示例代码是使用 Visual Studio 2008、WTL 8.0 和 beta 版 Windows 7 SDK 构建的。
Jump Lists 中的任务
在上一篇文章中,我们看到 Jump Lists 可以有两种类型的条目:目标和任务。本文将介绍任务,它们是应用程序可以执行的命令,例如“创建新文档”。任务在内部表示为 IShellLink
,因此任务应该是可以通过命令行传递给应用程序的命令。
请记住,用户可以将应用程序固定到任务栏,然后从固定快捷方式中调出 Jump List。这意味着在用户调用任务之前,您的应用程序不必正在运行。因此,任务必须是随时可以执行的操作。例如,IE8 有一个打开新 InPrivate 浏览器窗口的任务,无论 IE 是否已运行,都可以执行此操作。Microsoft 建议任务列表应该是静态的,并且不根据应用程序的当前状态而更改。
任务显示在它们自己的类别中,类似于我们上次看到的“最近”和“常用”类别。“任务”类别始终是列表中最后一个类别(最靠近底部),但只要列表中有空间,其项目就会一直显示。这可能会为其他类别留出更少的空间,因此在决定将哪些任务放入列表时,请考虑拥有大量任务会为最近使用或经常使用的文件留出更少的空间(如果您在 Jump List 中包含这些类别)。
没有记录的任务数量上限,但上限受屏幕空间和可用性问题的限制。Windows 7 的 beta 版本似乎没有强制执行上限(我能够创建一个 Jump List,其内容超出了我 1920x1200 屏幕的边缘),而 RC 版本最多有 16 个。您不应依赖此数字保持不变,因为 Microsoft 可能会出于设计或可用性决策而更改 Jump Lists 的内部工作方式。如果您添加的任务过多,Jump List 将显示它能显示的任务数量,其余的将不可见。
本文的示例项目是一个简单的时钟,其 Jump List 包含用于运行具有各种颜色方案的应用程序的任务。
该应用程序还为每个任务关联了一个命令行开关。
/r
:红色文本/y
:黄色文本/g
:绿色文本/z
:随机颜色
如果应用程序在没有开关的情况下运行,它将使用您对窗口颜色和文本颜色的偏好设置。
但是,使用四个开关之一运行它将使用不同的颜色方案。
设置 Jump List
使用任务需要创建自定义 Jump List,因此程序是:
- 创建一个
DestinationList
COM 对象并获取ICustomDestinationList
接口。 - 调用
SetAppID()
来告知 Jump List 您应用程序的 AppID。 - 调用
BeginList()
来创建一个新的、空的 Jump List。 - 创建一个
EnumerableObjectCollection
对象。 - 创建您的任务并将它们添加到对象集合中。
- 调用
AddUserTasks()
将任务添加到 Jump List。 - 调用
CommitList()
保存 Jump List。
演示应用程序在 WinMain()
中设置其 Jump List,因此每次程序运行时都会完成这项工作。(这意味着自定义的 Jump List 在您运行程序一次后才会出现。)创建 Jump List 不是一项耗时的操作,因此不会对启动时间产生明显影响。
创建新的 Jump List
在示例项目中,所有与 Jump List 相关的代码都在 SetUpJumpList()
中。我们首先创建一个新的 Jump List。
// NOTE: Error-handling omitted bool SetUpJumpList() { CComPtr<ICustomDestinationList> pDestList; // Create a jump list COM object. pDestList.CoCreateInstance ( CLSID_DestinationList ); // Tell the jump list our AppID. pDestList->SetAppID ( g_wszAppID ); // Create a new, empty jump list. We aren't adding custom destinations, // so cMaxSlots and pRemovedItems aren't used. UINT cMaxSlots; CComPtr<IObjectArray> pRemovedItems; pDestList->BeginList ( &cMaxSlots, IID_PPV_ARGS(&pRemovedItems) );
接下来,我们创建一个对象集合来保存我们的任务。我们通过创建具有 CLSID CLSID_EnumerableObjectCollection
的 COM 对象并请求 IObjectCollection
接口来执行此操作。
// Create an object collection to hold the custom tasks. CComPtr<IObjectCollection> pObjColl; pObjColl.CoCreateInstance ( CLSID_EnumerableObjectCollection );
然后,我们调用另一个函数 AddJumpListTasks()
来填充集合。我们稍后将看到 AddJumpListTasks()
的代码。
// Add our custom tasks to the collection. AddJumpListTasks ( pObjColl );
现在任务已放入集合中,我们查询集合以获取 IObjectArray
接口,将该接口传递给 AddUserTasks()
,然后保存 Jump List。
// Get an IObjectArray interface for AddUserTasks. CComQIPtr<IObjectArray> pTasksArray = pObjColl; // Add the tasks to the jump list. pDestList->AddUserTasks ( pTasksArray ); // Save the jump list. pDestList->CommitList(); }
创建任务
示例项目中的 AddJumpListTasks()
函数创建了四个任务,如文章开头屏幕截图所示。每个任务的创建方式都相同,即创建一个 ShellLink
对象并查询 IShellLink
接口,然后调用相应的 IShellLink
方法。每个任务都有五个属性,其中四个通过 IShellLink
方法设置:
SetPath()
:可执行文件的完整路径(必需)。SetArguments()
:要传递给可执行文件的命令行参数(可选,但通常会设置参数)。SetIconLocation()
:显示在任务旁边的图标(可选)。SetDescription()
:任务的描述,显示为工具提示(可选)。
最后一个属性,即显示在 Jump List 项中的文本,是通过查询 ShellLink
对象以获取 IPropertyStore
接口并设置 PKEY_Title
属性来设置的。
让我们看一个如何创建任务的示例。如果您曾经处理过快捷方式(它们也使用 IShellLink
),这对您来说应该很熟悉。为简单起见,此代码片段中的所有值都是硬编码的,但示例项目中的 AddJumpListTasks()
会查询一些通用数据(如可执行文件路径),并为每个任务调用一次 AddJumpListTask()
。
// NOTE: Error-handling omitted bool AddJumpListTask ( IObjectCollection* pObjColl ) { // Create a shell link COM object. CComPtr<IShellLink> pLink; pLink.CoCreateInstance ( CLSID_ShellLink ); // Set the executable path TCHAR szExePath[MAX_PATH]; GetModuleFileName ( NULL, szExePath, _countof(szExePath) ); pLink->SetPath ( szExePath ); // Set the arguments pLink->SetArguments ( _T("/r") ); // Set the icon location. IDI_RED is the resource ID of the icon pLink->SetIconLocation ( szExePath, -IDI_RED ); // Set the link description (tooltip on the jump list item) pLink->SetDescription ( _T("Run the clock with red text") );
接下来,我们获取 IPropertyStore
接口并设置 PKEY_Title
属性。
// Set the link title (the text of the jump list item). // This is kept in the object's property store, so QI for that interface. CComQIPtr<IPropertyStore> pPropStore = pLink; PROPVARIANT pv; InitPropVariantFromString ( L"Red Text", &pv ); // Set the title property. pPropStore->SetValue ( PKEY_Title, pv ); PropVariantClear ( &pv ); // Save the changes we made to the property store pPropStore->Commit();
现在我们已经设置好了链接,我们将其添加到 SetUpJumpList()
中创建并传递给此函数的对象集合中。
// Add this shell link to the object collection. pObjColl->AddObject ( pLink ); }
这是仅包含红色文本任务的 Jump List 的样子。
创建分隔符
您可以在任务列表中添加的另一项是分隔符。您可以在绿色文本和随机颜色项之间看到一个分隔符。
在 Windows 7 的 beta 版本中,分隔符非常小,不会占用 Jump List 中的完整高度。但在 RC 版本中,线条更宽,分隔符周围有更多的垂直空间。
分隔符基本上是一个任务,其 ShellLink
具有将其标记为分隔符的属性。所有其他方面与普通任务相同,您创建一个 ShellLink
对象并将其添加到对象集合中。要创建分隔符,您只需执行一件事:将 ShellLink 的 PKEY_AppUserModel_IsDestListSeparator
属性设置为 TRUE
。
// NOTE: Error-handling omitted bool AddJumpListSeparator ( IObjectCollection* pObjColl ) { // Create a shell link COM object. CComPtr<IShellLink> pLink; pLink.CoCreateInstance ( CLSID_ShellLink ); // Get an IPropertyStore interface. CComQIPtr<IPropertyStore> pPropStore = pLink; InitPropVariantFromBoolean ( TRUE, &pv ); // Set the property that makes the task a separator. pPropStore->SetValue ( PKEY_AppUserModel_IsDestListSeparator, pv ); PropVariantClear ( &pv ); // Save the property changes. pPropStore->Commit(); // Add this shell link to the object collection. pObjColl->AddObject ( pLink ); }
就是这样!请注意,Windows 会在任务列表的开头和结尾检查分隔符并将其删除。它还会将多个连续的分隔符合并为一个。
您还可以对 Jump Lists 做另一件事:创建一个自定义类别来显示您定义的目标。我们将在下次介绍如何做到这一点。
修订历史
2009 年 6 月 28 日:文章首次发布