技术开发 频道

升级到Visual C++ 2010的三纪律八注意

  第四项:应用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()函数,它提供了丰富的参数让我们可以设置任务对话框的各个属性,让任务对话框的创建和显示更加简单。

VC6升级VC2010八项注意之项目文件标准
更多信息的任务对话框

  任务对话框的使用,可以提高软件的用户体验,而重启管理器则可以增强软件的健壮性。重启管理器是 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 PreLoadState() {}    // 在文档加载之前被调用
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表达式的引入,将一些小函数的定义和使用结合在一起,形成匿名函数。这样可以使得代码更加简洁流畅:

// 使用Lambda表达式的count_if()算法
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上的用户体验。

CString FilePathName;
// 创建打开文件公共对话框
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进行必要的初始化:

BOOL CUpgradeDemoApp::InitInstance()
{
    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上的表现,真是又快又好。

2
相关文章