第四项:应用MFC扩展增强软件功能
除了Ribbon界面之外,Visual C++ 2010对MFC的扩展还有很多内容,例如新的工具栏控件,任务对话框(CTaskDialog)以及重启管理器(restart manager)等等,充分利用这些MFC扩展,可以很好地增强软件的功能。
任务对话框是为了提高软件的用户体验而提出的,跟原来呆板的提示信息用的MessageBox不同的是,任务对话框可以提供更加丰富的信息,方便用户作出决定。例如它可以显示命令链接(command link),按钮,图标,以及多种形式的提示信息等等。它的目的,就是为了替换原来的MessageBox,以方便用户更好的与应用程序进行交互。
要在我们的软件中使用任务对话框,我们首先需要引入
CString strMessage("你是否访问过imcc.blogbus.com?");
CString strDialogTitle("访问调查");
CString strMainInstruction("访问调查");
CString expandedLabel("隐藏提示信息");
CString collapsedLabel("显示提示信息");
CString expansionInfo("imcc.blogbus.com是一个关于Visual Studio及C++的原创技术网站,文章新鲜热辣有趣,你访问过吗?");
// 判断系统是否支持任务对话框
if (CTaskDialog::IsSupported())
{
// 构建任务对话框
CTaskDialog taskDialog(strMessage, strMainInstruction, strDialogTitle, TDCBF_OK_BUTTON);
// 设置任务对话框的一些属性
taskDialog.SetMainIcon(TD_INFORMATION_ICON);
taskDialog.SetCommonButtons(TDCBF_NO_BUTTON | TDCBF_CANCEL_BUTTON);
// 设置两个命令控件,IDS_STRING102和IDS_STRING103是控件的字符串资源
taskDialog.LoadCommandControls(IDS_STRING102, IDS_STRING103);
taskDialog.SetExpansionArea(expansionInfo, collapsedLabel, expandedLabel);
taskDialog.SetFooterText(L"现在就去imcc.blogbus.com瞧瞧");
// 显示对话框
INT_PTR result = taskDialog.DoModal();
// 根据用户选择作出反应
switch (result)
{
case IDS_STRING102:
//…
break;
//…
}
}
除了使用CTaskDialog的DoModal()函数显示对话框之外,我们还可以使用CTaskDialog的ShowDialog()函数,它提供了丰富的参数让我们可以设置任务对话框的各个属性,让任务对话框的创建和显示更加简单。
更多信息的任务对话框
任务对话框的使用,可以提高软件的用户体验,而重启管理器则可以增强软件的健壮性。重启管理器是 Windows Vista 中引入的一项有用的保护用户劳动成果的功能,可以使应用程序在遇到异常意外中止运行的时候执行保存的操作,然后重新启动的时候恢复其原来的状态,从而不至于使得用户的辛苦付之流水。
要向一个从Visual C++ 2010升级而来的项目添加重启管理器,我们可以按照下面的步骤进行:
• 修改应用程序类的基类为CWinAppEx
跟Ribbon界面相似,微软对MFC的应用程序类CWinApp进行了扩展来支持重启管理器,所以为了支持重启管理器,我们的应用程序类需要从新的经过扩展后的CWinAppEx派生。
• 指定重启管理器的风格
重启管理器可以支持多种风格,例如,有的风格(AFX_RESTART_MANAGER_SUPPORT_RESTART)只是将崩溃的应用程序重新启动,而有的风格(AFX_RESTART_MANAGER_SUPPORT_ALL_ASPECTS)不仅将应用程序重新启动,还可以打开原来自动保存的文档,恢复应用程序到崩溃前的状态。我们可以在应用程序类的构造函数中,通过指定CWinAppEx的dwRestartManagerSupportFlags成员变量来指定重启管理器的风格:
m_dwRestartManagerSupportFlags =
AFX_RESTART_MANAGER_SUPPORT_ALL_ASPECTS;
当我们需要重启管理器在重新启动应用程序后,自动恢复原来的文档时,重启管理器器会根据应用程序自动保存的文档进行恢复。默认情况下,应用程序每5分钟自动保存一次文档,当然,我们也可以在应用程序的InitInstance()函数中修改这个自动保存的时间间隔,以满足我们的实际需要:
CDataRecoveryHandler* autohandler = AfxGetApp()->GetDataRecoveryHandler();
autohandler->SetAutosaveInterval(60000);
如果我们需要对文档的自动保存和自动加载进行自定义操作,我们还可以通过重载应用程序类CWinAppEx的下列虚函数来完成:
virtual void LoadCustomState() {} // 在文档加载之后被调用
virtual void PreSaveState() {} // 在文档保存之前被调用
virtual void SaveCustomState() {} // 在文档保存之后被调用
通过这些强大的MFC扩展,可以有效地增强我们软件的功能,达到让我们的应用程序脱胎换骨的效果。
第五项:应用C++0x新特性改善代码
我们的升级工作,当然不仅仅是让原来的代码可以在新的平台下编译通过,或者是给软件换一个华丽的界面,改头换面就万事大吉了。我们的升级,更多的是为了利用新平台给我们的各种新特性来改善我们的软件,达到脱胎换骨的目的。Visual C++ 2010支持最新的C++标准C++0x,我们当然不能错过利用C++0x所带来的各种新特性,从根本上来改善我们的代码,提高软件质量。C++0x给我们带来了很多新特性,例如,Lambda表达式,auto关键字,类型推定等等,可以让我们的代码更加简洁;而右值引用,STL库的改写,更是可以大大提高C++代码的性能。
要在我们迁移完成后的代码中应用新的C++0x特性来改善代码也非常简单,只需要使用C++0x的新特性改写相应的代码,利用Visual C++ 2010支持C++0x的编译器,我们就可以直接获得C++0x所给我们带来的优势。比如,我们可以使用Lambda表达式对一些代码进行改写,使得代码更加简洁高效:
在Visual C++ 6.0中,为了统计一个vector容器中大于某个数值的元素的数目,我们的count_if()算法代码可能是这样的:
bool IsPass(int nStandard,int nSocre)
{
return nSocre > nStandard ? true : false;
}
vector<int> vecScore;
// 向容器中添加元素…
// 统计容器中大于60的元素数目
int nPass = count_if(vecScore.begin(),
vecScore.end(), bind1st(ptr_fun(IsPass), 60 ));
我们仅仅是为了统计容器中的某种数据的个数,但是我们却需要定义一个函数IsPass()来做数值的判断,然后在count_if()算法中使用这个函数。本来应该由count_if()完成的很简单的事情,却被我们弄得很复杂。同时,IsPass()函数的定义和它的使用者count_if()相互分离了,这样我们在阅读代码遇到count_if()算法的时候,可能需要打断我们的思路去查看IsPass()函数的具体实现。而VC2010中Lambda表达式的引入,将一些小函数的定义和使用结合在一起,形成匿名函数。这样可以使得代码更加简洁流畅:
int nPass = count_if(vecScore.begin(),
vecScore.end(),
[=](int nScore) -> bool // Lambda表达式
{
return nScore > 60 ? true : false;
});
如果说Lambda表达式仅仅是使得代码更加简洁流畅,没有多大实用价值,那么右值引用的使用,则可以实实在在的提高C++代码的性能。例如在Visual C++ 6.0中, 如果我们想利用函数创建某个复杂的对象,我们的实现可能是这样的:
class BigObject
{
public:
BigObject()
{
cout<<"构造函数"<<endl;
}
BigObject(BigObject& obj)
{
cout<<"拷贝构造函数"<<endl;
}
};
// 创建对象,这里CreateObject()函数返回的是一个右值
BigObject CreateObject()
{
return BigObject();
}
int main(int argc, char* argv[])
{
BigObject obj = CreateObject();
return 0;
}
在Visual C++ 6.0中,这段代码将执行一次BigObject的构造函数,执行两次BigObject的拷贝构造函数。但是在Visual C++ 2010中,因为引入了右值引用,编译器可以直接使用CreateObject()函数返回的右值作为我们要创建的对象obj,这样就省去了两次拷贝构造函数的调用,从而提高代码的性能。也许这里的性能提升效果并不明显,如果拷贝构造函数中执行的是一些耗时的操作,或者是一些对容器的操作中,比如对vector容器的排序操作,右值引用的效果将相当给力。
在Visual C++ 2010中,除了Lambda表达式和右值引用之外,还有很多重要的新特性可供我们利用。比如auto关键字可以省去我们推定变量类型的麻烦,shared_ptr可以为我们进行很好地内存管理,静态断言可以帮助我们对程序进行诊断,增加软件的健壮性等等。在升级过程中,好好利用这些新特性,可以让我们的C++代码更加简洁流畅,性能更高。
第六项:丰富软件在Windows 7上的体验
毫无疑问,Windows 7已经成为继Windows XP之后微软又一成功的Windows操作系统,越来越多的软件开始运行在这个新的操作系统之上。新的操作系统,总是带来很多新的特性。我们将Visual C++ 6.0的项目升级到Visual C++ 2010,不仅仅是为了借助新的编译器和库来提高软件的功能, 我们更要借助新的操作系统所提供的各种新特性,让我们的应用程序更加易用,更加强大,更有利于提高用户的生产效率。因为Visual C++ 2010是伴随着Windows 7而生的,它跟Windows 7有着天然的密不可分的亲近关系。通过Visual C++ 2010这个新的开发平台所提供的各种便利,我们可以轻松地使用Windows 7的各种新特性,例如触摸支持(Multi-Touch),动画管理器(Animation Manager),文件库(Libraries),任务栏缩略图以及Jump LIst等等。
在Visual C++ 2010中,微软已经对MFC进行了大量的扩展,只要我们将项目升级到Visual C++ 2010,就可以直接使用Windows 7的很多新特性。例如,Windows 7通过修改公共对话框,改善了应用程序的文件操作,颜色选择等等。还是相同的打开文件对话框的代码,在Visual C++ 2010中编译后,我们就可以得到新的打开文件对话框,用它们来改善应用程序在Windows 7上的用户体验。
// 创建打开文件公共对话框
CFileDialog dlg(TRUE);
// 显示对话框
if(dlg.DoModal()==IDOK)
FilePathName = dlg.GetPathName();
除了借助MFC的升级,我们可以直接使用Windows 7的很多新特性之外,我们还可以借力MFC的扩展,通过修改代码的方式,给我们的应用程序添加更多Windows 7的特性。例如,任务栏的Jump List是Windows 7给我们带来的一个非常有用的新特性,通过应用程序的Jump List,我们可以快速访问应用程序的常用功能,极大的方便了用户。为了让我们的应用程序轻松具备Jump List这一有用的功能,Visual C++ 2010中的MFC提供了一个CJumpList类,利用这一个新添加的MFC类,我们可以轻松地让一个从Visual C++ 6.0升级而来的应用程序具备Jump List的功能。
首先,在stdafx.h中添加头文件afxadv.h,MFC很多扩展的类都定义在这个头文件中。然后,在应用程序类中添加一个CJumoList类型的成员变量m_nJumplist,然后在应用程序初始化函数InitInstance()中对Jump List进行必要的初始化:
{
AfxEnableControlContainer();
//…
// 初始化Jump List
m_nJumplist.InitializeList();
// 添加两个文类(Category),分别显示最常用的文档和最近打开的文档
m_nJumplist.AddKnownCategory(KDC_FREQUENT);
m_nJumplist.AddKnownCategory(KDC_RECENT);
// 在Jump List添加一个任务,访问某个网站
m_nJumplist.AddTask(_T("http://imcc.blogbus.com"),
NULL, _T("访问[有间客栈]"), NULL, 0);
// 完成对Jump List的修改
m_nJumplist.CommitList();
m_pMainWnd->ShowWindow(SW_SHOW);
m_pMainWnd->UpdateWindow();
return TRUE;
}
通过简单的几行代码,我们的应用程序就轻松拥有了Jump List的功能。在Visual C++ 2010中,利用MFC的扩展使用Windows 7的新特性来丰富应用程序在Windows 7上的表现,真是又快又好。