新的 Windows 7 任务栏代表了 Windows 启动界面多年演化的顶峰。新的任务栏简化了许多最终用户应用场景,包括:
• 启动应用程序
• 在正在运行的应用程序之间和一个应用程序的多个窗口之间切换
• 管理最近/常用的用户目标目录
• 访问常用的应用程序任务
• 通过任务栏按钮报告进度和状态通知
• 无需离开任务栏缩略图就可以控制应用程序
图 1
新的 Windows 7 任务栏和开始菜单
新的任务栏是与众不同,它让应用程序闪耀在 Windows 7 平台上。它是最终用户发起和管理活动的主要接触点。因此,将新的任务栏功能集成到现代 Windows 应用程序中是一个极为重要的目标。
新的任务栏用户界面的特征在设计时整合了多项功能,旨在提供更为简洁的 Windows 外观,减少用户必须学习才能与系统交互的概念,简化了主要功能、任务和目标的发现,使常用的最终用户应用场景更容易访问。
目标
在此动手实验中,您将了解如何将 MFC 应用程序与 Windows 7 任务栏集成,包括如何:
• 使用任务栏进度栏和覆盖图标提供可视化的进度和状态指标
• 使用任务栏上的跳转列表、系统类别和自定义类别快速访问一般任务和常用目标
• 使用 MDI 视图的实时预览自定义任务栏缩略图
系统要求
您必须拥有以下内容才能完成本实验:
• Microsoft Visual Studio 2010 Beta 2(或更高版本)
• Windows 7
• Windows 7 SDK
练习 1:试验新的 Windows 7 任务栏功能
在本练习中,我们将尝试新的 Windows 7 任务栏功能。扩展一个展示应用程序,演示使用新的任务栏功能提供任务栏覆盖图标、进度栏、跳转列表和缩略图预览。应用程序的大部分用户界面已经实现,只需要填写缺少的部分,即使用 Visual C++ MFC( Microsoft 基础类库)与 Windows 7 任务栏交互。
要开始本练习,使用 Visual Studio 2010 打开 TaskbarDemo_Starter/TaskbarDemo.sln 解决方案(在 Source 文件夹中)。
图 2
Visual Studio 2010 中 Taskbar Concepts 解决方案的结构
花一两分钟浏览头文件、源文件和资源文件。看一看各个对话框和主要表单。再花几分钟时间生成并运行应用程序。
任务 1 - 使用任务栏覆盖图标
在这项任务中,当用户单击一个图标的按钮时,将切换应用程序任务栏按钮上的覆盖图标。
请注意,在 MFC 中,可以使用 CFrameWnd::SetTaskbarOverlayIcon() 设置覆盖图标。要清除任务栏覆盖图标,将 NULL (0) 传递给 SetTaskbarOverlayIcon()。 .
1. 在 TaskbarDemo/SourceFiles 子树中,打开 OverlayIconTab.cpp 并寻找 Info 覆盖图标的消息处理程序 COverlayIconTab::OnOverlayIconInfo()。
我们将使用此消息处理程序添加必要的代码,在按钮上将相同的图标设置为任务栏覆盖图标。
2. 将以下代码添加到 COverlayIconTab::OnOverlayIconInfo() 中:
C++
CMainFrame* mainFrm = dynamic_cast<CMainFrame*>(AfxGetApp()->GetMainWnd());
if (mainFrm)
mainFrm->SetTaskbarOverlayIcon(IDI_ICON_INFO,L"Info");
3. 编译并运行应用程序。
4. 单击信息按钮。
5. 请注意,任务栏上的显示已经从原来的 更改为现在叠加在它上面的信息按钮 (参见下面的图 3)。
图 3
显示的任务栏覆盖图标
6. 继续其余为覆盖图标消息处理程序添加必要的代码:
C++
void COverlayIconTab::OnOverlayIconQuestion()
{
// TODO:Add code to set question overlay icon
CMainFrame* mainFrm = dynamic_cast<CMainFrame*>(AfxGetApp()->GetMainWnd());
if (mainFrm)
mainFrm->SetTaskbarOverlayIcon(IDI_ICON_QUESTION, L"Question");
}
void COverlayIconTab::OnOverlayIconNoVolume()
{
// TODO:Add code to set no-volume overlay icon
CMainFrame* mainFrm = dynamic_cast<CMainFrame*>(AfxGetApp()->GetMainWnd());
if (mainFrm)
mainFrm->SetTaskbarOverlayIcon(IDI_ICON_NO_VOLUME,L"No Volume");
}
void COverlayIconTab::OnOverlayIconNone()
{
// TODO:Add code to clear overlay icon
CMainFrame* mainFrm = dynamic_cast<CMainFrame*>(AfxGetApp()->GetMainWnd());
if (mainFrm)
mainFrm->SetTaskbarOverlayIcon((HICON)0, L"");
}
7. 生成并运行示例,测试其他的覆盖图标。
任务 2 - 使用任务栏进度栏
在这项任务中,当用户从一个组合框选择进度状态或使用滑块更改值时,设置应用程序任务栏的进度栏状态和值。 MFC 提供了许多方法来更新任务栏进度栏的值和状态:
• CFrameWnd::SetProgressBarRange()
• CFrameWnd::SetProgressBarPosition()
• CFrameWnd::SetProgressBarState()
1. 在 TaskbarDemo/SourceFiles 子树中:
a. 打开 ProgressBarTab.cpp 文件
b. 寻找滑块控件的消息处理程序 CProgressBarTab::OnHScroll()
c. 在注释后面添加以下代码来更新任务栏的进度栏,以处理滑块的变化:
C++
UpdateData();
CMainFrame* mainFrm = dynamic_cast<CMainFrame*>(AfxGetApp()->GetMainWnd());
mainFrm->SetProgressBarPosition(m_ProgressSliderValue);
2. 编译并运行应用程序,然后:
a. 转到 Progress Bar 选项卡。
b. 移动滑块,并注意滑块在应用程序任务栏按钮上的运动。
应该看到类似图 4 的输出:
图 4
滚动条和任务栏按钮进度指示器
3. 现在,我们要在相关组合框选项更新时更新进度栏的状态,因此向 CProgressBarTab::OnCbnSelchangeProgressStatusCombo() 事件处理程序添加必要的代码:
C++
CMainFrame* mainFrm = dynamic_cast<CMainFrame*>(AfxGetApp()->GetMainWnd());
switch (m_ProgrssStatusCombo.GetCurSel())
{
case 0 :
mainFrm->SetProgressBarState(TBPF_NORMAL);
break;
case 1 :
mainFrm->SetProgressBarState(TBPF_ERROR);
break;
case 2 :
mainFrm->SetProgressBarState(TBPF_PAUSED);
break;
case 3 :
mainFrm->SetProgressBarState(TBPF_INDETERMINATE);
break;
case 4 :
mainFrm->SetProgressBarState(TBPF_NOPROGRESS);
break;
default:
mainFrm->SetProgressBarState(TBPF_NORMAL);
}
4. 编译并运行应用程序,然后:
a. 导航到 Progress Bar 选项卡
b. 从 Progress Status 组合框选择不同的样式,然后
c. 移动进度滑块。
进度栏状态将更改为适当的样式,即 Progress Status 设置为 Error 时,任务栏的进度栏为红色,Progress Status 设置为 Normal 时,任务栏的进度栏为绿色,(您也可以查看其他样式):
图 5
红色进度栏显示存在错误
5. 最后一步是可选的,但是,当进度从 No Progress 或 Intermediate 更新时,您可能需要将状态组合框重置为‘Normal’。
要解决此问题,请在 CProgressBarTab::OnHScroll() 中添加以下代码:
C++
if (m_ProgressSliderValue > 0 && m_ProgrssStatusCombo.GetCurSel() >= 3) // No progress or intermediate
{
// Set to something else other than no progress
m_ProgrssStatusCombo.SetCurSel(0); // Normal
}
任务 3 - 使用任务栏跳转列表
在这项任务中,我们将添加功能来支持向应用程序跳转列表添加已知类别、自定义类别、目标和任务。为了支持这项功能,MFC 提供了一个新类 CJumpList,它允许在任务栏应用程序的 JumpList 上操作类别和条目。
1. 在 TaskbarDemo/SourceFiles 子树中,打开 JumpListTab.cpp 文件并寻找 CJumpListTab::UpdateRegistration() 的实现。
此方法执行另一个进程以注册所需的文件关联。然而,文件关联注册并不需要在另一个进程中进行,放在另一个进程中是为了保持本教程的应用程序简单和重点突出。
注意:我们需要注册文件关联,因为对于将出现在跳转列表中的类型的项目,应用程序必须是该文件类型的已注册处理程序。但是,它不必是该文件类型的默认处理程序。
2. 添加必要的代码来在相应消息处理程序中更新注册表和注销 jpg 文件关联:
C++
void CJumpListTab::OnRegisterFileType()
{
// TODO:Register file associations
UpdateRegistration(TRUE);
}
void CJumpListTab::OnUnregisterFileType()
{
// TODO:Unregister file associations
UpdateRegistration(FALSE);
}
3. 接下来的步骤用于添加必要的代码,从而添加各种跳转列表项。下面是对每项的描述:
图 6
跳转列表项描述
4. 要向跳转列表追加已知类别,将此代码添加到 CJumpListTab::OnAddKnownCategory() 事件处理程序中:
C++
int curSel = m_knownCategoryCombo.GetCurSel();
if (curSel < 0)
{
AfxMessageBox(L"Must select a known category above");
return;
}
if (curSel == 0)
{
if (m_jumpList.AddKnownCategory(KDC_FREQUENT))
m_JumpList_Display_Items.AddString(L"Known Category:Frequent");
else
AfxMessageBox(L"Failed to add Frequent Known Category");
}
else if (curSel == 1)
{
if (m_jumpList.AddKnownCategory(KDC_RECENT))
m_JumpList_Display_Items.AddString(L"Known Category:Recent");
else
AfxMessageBox(L"Failed to add Recent Known Category");
}
5. 要在跳转列表中添加目标,将此代码添加到 CJumpListTab::OnAddDestination() 事件处理程序中:
C++
UpdateData(); // Sync variables to UI controls
if (m_destinationPath.IsEmpty() || m_destinationCategory.IsEmpty())
{
AfxMessageBox(L"Both Destination categeory and path must be added.");
return;
}
if (!m_jumpList.AddDestination(m_destinationCategory, m_destinationPath))
{
AfxMessageBox(L"Failed to add destination.");
}
else
{
CString text = L"Destination:" + m_destinationPath;
m_JumpList_Display_Items.AddString(text);
}
6. 要向跳转列表添加新任务,将此代码添加到 CJumpListTab::OnAddTask() 事件处理程序中:
C++
UpdateData(); // Sync variables to UI controls
if (m_taskPath.IsEmpty() || m_taskTitle.IsEmpty())
{
AfxMessageBox(L"Both Task Path and Title must be added.");
return;
}
if (!m_jumpList.AddTask(m_taskPath, m_taskArgs, m_taskTitle, m_taskIconPath, m_taskIconIndex))
{
AfxMessageBox(L"Failed to add Task.");
}
else
{
CString text = L"Task:" + m_taskTitle ;
m_JumpList_Display_Items.AddString(text);
}
7. 要允许从跳转列表删除所有条目,将下面的代码添加到 CJumpListTab::OnClearAll() 事件处理程序中:
C++
m_jumpList.ClearAll();
m_JumpList_Display_Items.ResetContent();
8. 要提交所作的跳转列表更改,将下面的代码添加到 CJumpListTab::OnCommit() 事件处理程序中:
C++
if (m_jumpList.CommitList())
{
m_JumpList_Display_Items.ResetContent();
// Start another list
m_jumpList.InitializeList();
}
else
{
AfxMessageBox(L"Failed to commit jump list.");
}
注意:所有对 JumpList 的更新必须发生在调用 CJumpList::InitializeList() 和 CJumpList::CommitList() 之间,否则,添加将会失败。
9. 编译并运行应用程序。
10. 在 Jump List 选项卡中,单击 Register .jpg file association 按钮注册 JPEG 文件关联。
注意:此注册过程需要特权才能进行,所以 UAC 会提示提升权限。
11. 在 Jump List 选项卡中,开始向跳转列表添加项目,并确保在最后单击了“Commit”按钮,以便添加的项目可以出现在跳转列表中。要添加的项目示例:
a. 添加 Recent 和 Frequent Known Categories(从 Known Category 下拉列表选择 Frequent,然后单击 Add Known Category ==>)
b. 填充 Category = “Custom Category”(不含引号)和 Path = C:/Users/Public/Pictures/Sample Pictures/Desert.jpg,然后单击 Add Destination ==>,添加一个目标。
c. 填充 Title=”Bing”(不含引号)和 Path/Url=http://www.bing.com(图标是可选的),然后单击 Add task ==>,添加一个任务。
d. 单击 Commit。
e. 右键单击应用程序的任务栏按钮,将看到类似于以下内容的输出:
图 7
跳转列表示例
练习 2:支持任务栏缩略图
MFC 在 Visual Studio 2010 中添加了对任务栏缩略图的支持。内置于 MFC 应用程序中的这种支持基于选项卡式的多文档界面(MDI)。
注意:
在 MFC 中,对任务栏缩略图预览的支持是内置的,所以任务栏缩略图会显示任何呈现的内容。因此,除了实现自己的视图绘制,您不必提供任何明确的代码来更新这些缩略图。
任务 1 - 支持任务栏缩略图
在使用 MFC Application Wizard 时,为了在 MFC 应用程序中启用任务栏缩略图,用户需要做的就是选择“Multiple documents”应用程序类型并启用“Tabbed documents”选项(见图 8)。当应用程序运行时,MFC 将采集每个视图的快照并将其发送到任务栏 API 以显示为缩略图。
图 8
MFC Application Wizard - Application Type
1. 在 Visual Studio 2010 中,打开 TaskbarThumbnails_Solution/TaskbarthumbnailsDemo.sln 解决方案(在 Source 文件夹中)。
2. 编译并运行应用程序。
3. 使用应用程序打开一些 .jpeg 图像文件。
4. 将鼠标悬停在任务栏中该应用程序的 Demo 按钮上。应该看到类似图 9 的输出:
图 9
MDI 应用程序的任务栏缩略图
总结
在本实验中,通过在一个简单的 MFC 应用程序中使用针对 Windows 7 任务栏的新 MFC 支持,我们体验了 Windows 7 任务栏功能。您已经看到使用进度栏和覆盖图标从任务栏按钮提供相关的进度和状态信息非常简单,看到了如何使用跳转列表快速获取一般任务和目标,以及如何利用 MFC 对缩略图预览的内置支持。
将具有生产级质量的应用程序与 Windows 7 任务栏集成需要完成的工作可能比在这个实验中完成的工作稍微多一些,但现在您足以开始自己的练习了。