Visual C++

探究 Visual Studio 2010 中的新增 C++ 和 MFC 功能

Sumit Kumar

Visual Studio 2010 为 C++ 开发人员提供了巨大的好处。从利用 Windows 7 所提供的新功能到通过使用大型基本代码提高工作效率的增强功能,每个 C++ 开发人员都可获得新的或改进的功能。

在本文中,我将解释 Microsoft 对 C++ 开发人员所面临的一些广泛问题的解决方式。具体而言, Visual Studio 2010 通过依据即将发布的 C++0x 标准添加核心语言功能,并通过修改标准库来利用这些新的语言功能,提供了一种更为先进的编程模型。有新的并行编程库和工具可简化并行程序的创建。有了 IntelliSense 和扩展到大型基本代码的代码理解功能,您还会发现整体性能和开发人员工作效率的提高。并且,您将在设计时、生成时、编译时和链接时从改进的库性能 和其他功能获益。

Visual Studio 2010 将生成系统迁移到 MSBuild,使其具有更高的可自定义程度并支持本机多定向。MFC 库中的增强功能可利用新 Windows 7 API 的功能,使您能够编写出色的 Windows 7 应用程序。

下面我将详细介绍 Visual Studio 2010 中这些针对 C++ 的改进。

C++0x 核心语言功能

下一个 C++ 标准很快就会完成。为帮助您开始使用 C++0x 扩展,Visual Studio 2010 中的 Visual C++ 编译器启用了六项 C++0x 核心语言功能:lambda 表达式、auto 关键字、rvalue 引用、static_assert、nullptr 和 decltype。

lambda 表达式隐式定义并构造未命名函数对象。lambda 提供了一种轻型自然语法来定义使用 lambda 的函数对象,而不产生性能开销。

函数对象是自定义标准模板库 (STL) 算法行为的非常强大的方式,可以封装代码和数据(与普通函数不同)。但定义函数对象不太方便,因为需要编写完整的类。此外,它们不是在要用到它们的源代码中定义的,这种非局部性增加了这些对象的使用难度。库已尝试缓解一些复杂性和非局部性问题,但帮助不大,因为语法有点复杂而且编译器错误不是很友好。使用库中的函数对象也会降低效率,因为定义为数据成员的函数对象不是内联对象。

lambda 表达式解决了这些问题。下面的代码段显示了一个 lambda 表达式,该表达式在程序中用于从整数向量中删除变量 x 和 y 之间的整数。

v.erase(remove_if(v.begin(),
   v.end(), [x, y](int n) { 
   return x < n && n < y; }),
   v.end());

第二行显示了该 lambda 表达式。方括号(称为 lambda 引导)指示 lambda 表达式的定义。此 lambda 采用整数 n 为参数,lambda 生成的函数对象具有数据成员 x 和 y。若与一个等效的手写函数对象进行比较,可看到 lambda 的方便性和省时性:

class LambdaFunctor {
public:
  LambdaFunctor(int a, int b) : m_a(a), m_b(b) { }
  bool operator()(int n) const {
    return m_a < n && n < m_b; }
private:
  int m_a;
  int m_b;
};
v.erase(remove_if(v.begin(), v.end(),
  LambdaFunctor(x, y)), v.end());

auto 关键字在 C++ 中一直存在,但很少使用,因为它没有提供任何附加价值。C++0x 将此关键字的作用改为根据变量初始值设定项自动确定变量的类型。auto 可降低复杂性并帮助突出重要代码。它还可避免类型不匹配和截断错误。该关键字通过允许编写不太在意中间表达式类型的模板帮助而提高代码的通用性,并能有效处理 lambda 之类的未记录类型。下面的代码演示 auto 如何帮您省去在循环访问向量的 for 循环中键入模板类型的麻烦:

vector<int> v;
for (auto i = v.begin(); i != v.end(); ++i) {
// code 
}

Rvalue 引用是 C++0x 中引入的一种新的引用类型,可帮助解决不必要的复制问题并实现完美转发。当赋值语句的右侧是 rvalue 时,左侧对象可以从右侧对象窃取资源而不是进行单独分配,这样就可以实现 move 语义。

完美转发允许您只编写一个函数模板,该模板采用 n 个任意参数并以透明方式将它们转发给另一个任意函数。参数的性质(modifiable、const、lvalue 或 rvalue)在此转发过程中被保留。

template <typename T1, typename T2> void functionA(T1&& t1, T2&& t2) {
  functionB(std::forward<T1>(t1), std::forward<T2>(t2));
}

有关 rvalue 引用的详细解释超出了本文的范围。有关详细信息,请查看 msdn.microsoft.com/library/dd293668(VS.100) 上的 MSDN 文档。

Static_assert 允许在编译时而不是执行时测试断言。使用它可以触发包含易于阅读的错误消息的编译器错误。Static_assert 对于验证模板参数特别有用。例如,编译以下代码将给出错误“错误 C2338:自定义断言:n 应小于 5”:

template <int n> struct StructA {
  static_assert(n < 5, "custom assert: n should be less than 5");
};

int _tmain(int argc, _TCHAR* argv[]) {
  StructA<4> s1;
  StructA<6> s2;
  return 0;
}

Nullptr 为 null 指针增添了类型安全性,并且与 rvalue 引用密切相关。宏 NULL(定义为 0)和文本 0 通常用作 null 指针。到目前为止还没有什么问题,但此代码在 C++0x 中不能很好地运行,因为在完美转发中存在潜在问题。因此,专门引入了 nullptr 关键字来避免完美转发函数中出现不为人知的失败。

Nullptr 是一个 nullptr_t 类型的常量,可以转换为任意指针类型,但不能转换为 int 或 char 之类的其他类型。除了在完美转发函数中使用外,nullptr 还可在使用宏 NULL 作为 null 指针的任意位置使用。

但请注意:编译器仍支持 NULL,尚未用 nullptr 将其取代。这主要是为了避免由于普遍存在的常常不合适的 NULL 使用而导致现有代码的失败。但在将来,以前使用 NULL 的所有地方都应使用 nullptr,NULL 只被视为用于支持向后兼容性的功能。

最后,decltype 允许编译器根据任意表达式推断函数的返回类型并使完美转发更为通用。在过去的版本中,对于两个任意类型 T1 和 T2,无法推断使用这两个类型的表达式的类型。例如,decltype 功能允许您声明具有模板参数的表达式(例如 sum<T1, T2>())具有类型 T1+T2。

标准库改进

标准 C++ 库的大部分都已重新编写,以便利用新的 C++0x 语言功能并提高性能。此外,还引入了许多新算法。

标准库充分利用 rvalue 引用来提高性能。如向量和列表这样的类型现在有其自己的 move 构造函数和 move 赋值运算符。向量重新分配通过选择 move 构造函数利用 move 语义,因此如果您的类型有 move 构造函数和 move 赋值运算符,库将自动选择使用它们。

现在,在构造对象时,可以在新的 C++0x 函数模板 make_shared<T> 的帮助下同时创建一个指向该对象的共享指针:

auto sp = 
  make_shared<map<string,vector>>
  (args);

在 Visual Studio 2008 中获得同样的功能须编写以下代码:

shared_ptr<map<string,vector>> 
  sp(new map<string,vector>(args));

使用 make_shared<T> 更方便(必须键入类型名称的次数减少)、更强大(因为指针和对象是同时创建的,避免了以往常见的未命名 shared_ptr 泄露)并且效率更高(执行一次动态内存分配而不是两次)。 

库中现在包含一个新的更加安全的智能指针类型 unique_ptr(已由 rvalue 引用启用)。结果就是弃用了 auto_ptr;unique_ptr 通过变得可移动但不可复制避免了 auto_ptr 的缺陷。这允许您实现严格的所有权语义而不影响安全性。它也适用于识别 rvalue 引用的 Visual C++ 2010 容器。

现在容器有了新的成员函数 cbegin 和 cend,它们提供了一种不考虑容器类型而使用 const_iterator 进行检查的方式:

vector<int> v;
 
for (auto i = v.cbegin(); i != v.cend(); ++i) {
  // i is vector<int>::const_iterator
}

Visual Studio 2010 在标准库中增加了各种 C++0x 文章中建议的大多数算法。标准库中现在提供了 Dinkumware 转换库的一个子集,因此可以轻松进行像 UTF-8 到 UTF-16 这样的转换。标准库通过 exception_ptr 启用异常传播。标头 <random> 中进行了许多更新。此版本中有一个名为 forward_list 的单链表。库具有标头 <system_error> 来改进诊断。此外,上一版本中存在于命名空间 std::tr1 中的许多 TR1 功能(如 shared_ptr 和 regex)现在都纳入了标准库中的 std 命名空间。

并发编程改进

Visual Studio 2010 引入了并行计算平台,可帮助您快速编写高性能并行代码并避免不易发现的并发 Bug。这样可以避开以往与并发有关的常见问题。

并行计算平台有四个主要部分:并发运行时 (ConcRT)、并行模式库 (PPL)、异步代理库以及并行调试和分析。

ConcRT 是争用资源的多个并发组件中与操作系统对话并进行仲裁的最低软件层。因为它是用户模式进程,所以在使用其协作性阻止机制时可以回收资源。ConcRT 能够感知局部性并避免在不同处理器之间切换任务。它还使用 Windows 7 用户模式计划 (UMS),因此即使未使用协作性阻止机制, 它也可以提升性能。

PPL 提供了用于编写并行代码的模式。如果一个计算可分解为多个可由函数或函数对象表示的子计算,则这些子计算中的每一个都可以表示为一个任务。任务概念与问题域更加相近,这与线程不同,线程会使人想到硬件、操作系统、关键部分等从而让您远离问题域。一项任务可与其他任务并行执行,而无论其他任务的目的是什么。例如,对一个数组的两部分排序可由两个 不同任务并行进行。

PPL 包含并行类(task_handle、task_group 和 structured_task_group)、并行算法(parallel_invoke、parallel_for 和 parallel_for_each)、并行容器(combinable、concurrent_queue 和 concurrent_vector)以及识别 ConcRT 的同步基元(critical_section、event 和 reader_writer_lock),它们都将任务视为第一级概念。PPL 的所有组件都位于并发命名空间中。

使用任务组可以执行一组任务并等待所有任务完成。因此,在排序示例中,分别处理数组两个部分的任务可以组成一个任务组。您一定会看到这两项任务在 wait 成员函数调用末尾完成,如以下代码示例所示,此示例是一个使用并行任务和 lambda 编写的递归 quicksort:

void quicksort(vector<int>::iterator first,
vector<int>::iterator last) {
  if (last - first < 2) { return; }
  int pivot = *first;
  auto mid1 = partition(first, last, [=](int elem) { 
    return elem < pivot; });
  auto mid2 = partition( mid1, last, [=](int elem) { 
    return elem == pivot; });
  task_group g;
  g.run([=] { quicksort(first, mid1); });
  g.run([=] { quicksort(mid2, last); });
  g.wait();
}

使用由 parallel_invoke 算法启用的结构化任务组可对此进一步改进。它使用 2 到 10 个函数对象,使用 ConcRT 提供的尽可能多的内核并行执行这些函数对象,并等待它们完成:

parallel_invoke(
  [=] { quicksort(first, mid1); },
  [=] { quicksort(mid2, last); } );

parallel_invoke(
  [=] { quicksort(first, mid1); },
  [=] { quicksort(mid2, last); } );

这些任务中的每一个都可以创建多个子任务。任务和执行线程之间的映射(以及对优化利用所有内核的保证)由 ConcRT 管理。因此,将计算分解为尽可能多的任务有助于利用所有可用内核。

另一个有用的并行算法是 parallel_for,它可以用于以并发方式循环访问索引:

parallel_for(first, last, functor);
parallel_for(first, last, step, functor);

这会使用每个索引并发调用函数对象,从第一个开始,到 最后一个结束。

异步代理库为您提供一个基于数据流的编程模型,其中计算取决于变为可用的必需数据。此库基于代理、消息块和消息传递函数的概念。一个代理就是一个应用程序组件,它执行特定的计算并与其他代理异步通信以解决更大的计算问题。代理之间的这种通信通过消息传递函数和消息块实现。

代理具有历经不同阶段的可观察的生命周期。它们不用于通过 PPL 任务实现的精细并行特性。代理在 ConcRT 的计划和资源管理组件上生成,可帮助您避免因在并发应用程序中使用共享内存而引发的问题。

不需要链接或重新分发任何其他组件就可利用这些模式。ConcRT、PPL 和异步代理库已在 msvcr100.dll、msvcp100.dll 和 libcmt.lib/libcpmt.lib 中随标准库一起实现。PPL 和异步代理库基本是纯标头实现。

Visual Studio 调试器现在识别 ConcRT,这样便于您调试并发问题,这与不支持高级并行概念的 Visual Studio 2008 不同。使用 Visual Studio 2010 的并发探查器可以可视化并行应用程序的行为。调试器具有新窗口,可以可视化应用程序及其调用堆栈中的所有任务的状态。图 1 显示了“并行任务”和“并行堆栈”窗口。

图 1“并行堆栈”和“并行任务”调试窗口
图 1**“并行堆栈”和“并行任务”调试窗口**

IntelliSense 和设计时效率

Visual Studio 2010 中包含了全新的 IntelliSense 和浏览基础结构。除了帮助调整和响应具有大型基本代码的项目,此基础结构改进还带来了一些新的设计时效率功能。

如实时错误报告和快速信息工具提示这样的 IntelliSense 功能基于新的编译器前端,即使代码文件正在修改中,该前端也能分析完整的转换单元以提供关于代码语义的丰富且准确的信息。

所有代码浏览功能(如类视图和类层次结构)现在都使用 SQL 数据库中存储的源代码信息,该数据库启用了索引功能并具有固定的内存占用量。与以前的版本不同,Visual Studio 2010 IDE 始终具有响应能力,当编译单元由于头文件发生更改而重新分析时,您不再需要等待。

IntelliSense 实时错误报告(我们熟悉的红色波浪线)在浏览和编辑代码时显示编译器质量语法和语义错误。将鼠标悬停在错误上可查看错误消息(请参见图 2)。错误列表窗口也会显示当前查看的文件中的错误以及编译单元其他位置的 IntelliSense 错误。不必进行生成即可获得所有这些信息。

图 2 显示 IntelliSense 错误的实时错误报告
图 2 显示 IntelliSense 错误的实时错误报告

此外,在键入 #include 时会在下拉列表中显示相关包含文件的列表,此列表随您的键入而精简。

新的“定位到”(“编辑”|“定位到”或 Ctrl+逗号)功能将帮助您更有效地搜索文件或符号。此功能根据您键入的子串给出实时搜索结果,将您的输入字符串与任意项目中的符号和文件对照匹配(请参见图 3)。此功能还适用于 C# 和 Visual Basic 文件,并且可进行扩展。

图 3 使用“定位到”功能
图 3 使用“定位到”功能

调用层次结构(使用 Ctrl+K、Ctrl+T 或从右键单击菜单中调用)可以定位到从某一特定函数调用的所有函数,以及对特定函数进行调用的所有函数。这是以前的 Visual Studio 版本中存在的“调用浏览器”功能的改进版本。“调用层次结构”窗口组织得更好,对同一窗口中出现的任何函数同时提供调用来源和调用目标树。

请注意,虽然所有代码浏览功能都可用于纯 C++ 和 C++/CLI,但像实时错误报告和快速信息这样的 IntelliSense 相关功能在 Visual Studio 2010 最终版中不可用于 C++/CLI。 

此版本中还对其他一些主要编辑器功能做出了改进。例如,用于在整个解决方案中搜索对代码元素(类、类成员、函数等)的引用的“查找所有引用”功能现在更为灵活。使用右键单击上下文 菜单中的“解析结果”选项可进一步精简搜索结果。

非活动代码现在通过维护颜色设置(而不是成为灰色)保留语义信息。图 4 显示了非活动代码虽然变暗,但仍显示不同颜色来传达语义信息。

图 4 非活动代码块保留颜色设置
图 4 非活动代码块保留颜色设置

除了上面介绍过的功能外,常规编辑器体验在 Visual Studio 2010 中也得到了增强。为消除混乱并提高可读性,新的基于 Windows Presentation Foundation (WPF) 的 IDE 经过了重新设计。像代码编辑器和设计视图这样的文档窗口现在可以浮动在主 IDE 窗口之外,并可在多个监视器中显示。使用 Ctrl 键和鼠标滚轮可以轻松缩放代码编辑器窗口。IDE 还增强了可扩展性支持。

生成和项目系统

Visual Studio 2010 还在针对 C++ 项目的生成系统和项目系统方面做出了重要改进。

最重要的更改是现在使用 MSBuild 生成 C++ 项目。MSBuild 是可扩展的、基于 XML 的生成业务流程引擎,在以前的 Visual Studio 版本中已经用于 C# 和 Visual Basic 项目。MSBuild 现在是所有语言通用的 Microsoft 生成系统。在生成实验室和各开发人员计算机上都可使用该系统。

C++ 生成过程现在按照 MSBuild 目标和任务文件定义,提高了可自定义性、可控性和透明性。

C++ 项目类型有了新的扩展名:.vcxproj。Visual Studio 会自动将旧的 .vcproj 文件和解决方案升级为新格式。还有一个命令行工具 vcupgrade.exe 用于从命令行升级单个项目。

过去,只能使用随您的当前 Visual Studio 版本提供的工具集(编译器和库等等)。您必须等到能够迁移到新工具集,然后才能开始使用新的 IDE。Visual Studio 2010 允许您以多个工具集版本为目标进行生成,从而解决了这一问题。例如,您可以将 Visual C++ 9.0 编译器和库作为目标,同时在 Visual Studio 2010 中工作。图 5 显示了属性页上的本机多定向设置。

5 以多个平台为目标的工具集
图 5 以多个平台为目标的工具集

使用 MSBuild 大大增加了 C++ 生成系统的可扩展性。当默认生成系统不足以满足您的需求时,可以通过添加自己的工具或任意其他生成步骤扩展该系统。MSBuild 使用任务作为可执行代码的可重复使用单元来执行生成操作。可以创建您自己的任务并通过在 XML 文件中定义它们来扩展生成系统。MSBuild 从这些 XML 文件动态生成任务。

通过向 ImportBefore 和 ImportAfter 文件夹中添加附加步骤的 .props 和 .targets 文件可扩展现有平台和工具集。这对于要扩展现有生成系统的库及工具提供商特别有用。您还可以定义自己的平台工具集。此外,MSBuild 还提供更好的诊断信息,使您可以更加轻松地调试生成问题,这还提高了增量生成的可靠性。此外,您还可以使创建的生成系统与源代码管理和生成实验室关系更为密切,而对开发人员计算机配置依赖更少。

生成系统顶部的项目系统也利用 MSBuild 提供的灵活性和可扩展性。项目系统了解 MSBuild 过程并允许 Visual Studio 以透明方式显示通过 MSBuild 提供的信息。

自定义项是可见的,并且可通过属性页进行配置。您可以配置项目系统使用您自己的平台(如现有的 x86 或 x64 平台)或您自己的调试器。使用属性页可以对组件进行编写和集成,使之动态更新依赖于上下文的属性的值。使用 Visual Studio 2010 项目系统甚至可以自编自定义 UI 来读写属性,而不必使用属性页。

更快的编译和更好的性能

除了到目前为止已经介绍的设计时体验改进之外,Visual Studio 2010 还通过多方面增强编译器后端的代码生成功能,提高了使用 Visual C++ 编译器生成的应用程序的编译速度、质量和性能。

某些特定应用程序的性能取决于工作集。通过此版本中进行的多项优化,x64 体系结构的代码大小缩减了 3% 到 10%,从而提高了此类应用程序的性能。

单指令多数据 (SIMD) 代码生成(对于游戏、音频、视频和图形开发人员非常重要)已经过优化,可以提高性能和代码质量。所做改进包括打破错误依赖关系、向量化常量向量初始化以及通过更好地分配 XMM 寄存器消除多余的负载、存储和移动。此外,还优化了 __mm_set_**、__mm_setr_** 和 __mm_set1_** 固有系列。

为改进性能,应使用链接时间代码生成 (LTCG) 和按配置优化 (PGO) 生成应用程序。

x64 平台上的编译速度已通过优化 x64 代码生成而得到提高。LTCG 编译(为更好地优化推荐使用)通常比非 LTCG 编译需要更长时间,对于大型应用程序更是如此。在 Visual Studio 2010 中,LTCG 编译速度提高高达 30%。在此版本中引入了一个写入 PDB 文件的专用线程,因此您在使用 /DEBUG 开关时会看到链接时间的缩减。

通过添加对被检测二进制文件的非锁定版本的支持,PGO 检测的运行速度有所提高。还有一个新的 POGO 选项 PogoSafeMode,用于指定优化应用程序时使用安全模式还是快速模式。快速模式是默认行为。安全模式是线程安全的,但比快速模式要慢。

编译器生成的代码的质量有所提高。现在完全支持高级矢量扩展 (AVX),这对于 AMD 和 Intel 处理器中通过固有选项和 /arch:AVX 选项进行大量浮点计算的应用程序非常重要。使用 /fp:fast 选项可以使浮点计算更为精确。

生成 Windows 7 应用程序

Windows 7 引入了多项激动人心的新技术和新功能以及新的 API,Visual Studio 2010 提供了对所有新 Windows API 的访问。Visual Studio 2010 提供了为本机 Windows API 编写代码所需的 Windows SDK 组件。您可以通过使用 Visual Studio 2010 中的 SDK 头文件和库来利用如 Direct3D 11、DirectWrite、Direct2D 和 Windows Web Service API 之类的革新。

除了向开发人员开放所有 Windows API 以外,此版本的 Visual Studio 还使您可以在增强的 MFC 的帮助下更轻松地编写 Windows 应用程序。可通过 MFC 库访问主要的 Windows 7 功能,而不必直接写入本机 API。只需重新编译,您现有的 MFC 应用程序就可以在 Windows 7 上大放异彩。而且,您的新应用程序可以充分利用新增的功能。

MFC 与 Windows Shell 的集成现在有所增强。通过使用此版本中增加的文件处理程序进行预览、创建缩略图和搜索,现在您的应用程序可以更好地与 Windows 资源管理器集成。这些功能作为 MFC 应用程序向导中的选项提供,如图 6 所示。MFC 将自动生成实现这些处理程序的 ATL DLL 项目。

图 6 带文件处理程序选项的 MFC 应用程序向导
图 6 带文件处理程序选项的 MFC 应用程序向导

Windows 7 中最值得注意的一项用户界面更改就是新任务栏。MFC 允许您快速利用这些功能,如跳转列表、选项卡式缩略图、缩略图预览、进度条、图标覆盖等。图 7 显示了一个选项卡式 MDI MFC 应用程序的缩略图预览和选项卡式缩略图。

图 7 MFC 应用程序中的选项卡式缩略图和缩略图预览
图 7 MFC 应用程序中的选项卡式缩略图和缩略图预览

功能区 UI 现在也拥有了 Windows 7 样式功能区,通过使用如图 8 所示的样式下拉列表,您的应用程序可以在开发过程中随时将 UI 从几种 Office 样式功能区动态切换为 Windows 7 功能区。

图 8 MFC 应用程序中的功能区样式下拉列表
图 8 MFC 应用程序中的功能区样式下拉列表

MFC 可以使您的应用程序成为多点触控感知应用程序,并在各种不同的触控事件发生时调用相应的消息供您处理。您只需注册触控和手势事件就可为您的应用程序路由这些事件。MFC 还默认为应用程序实现高 DPI 识别功能,应用程序因此可以适应高 DPI 屏幕,而不会出现像素化或模糊现象。MFC 在内部缩放并更改字体和其他元素,以确保您的 UI 在高 DPI 显示器上也一样清晰。

除了新的 Windows 7 功能外,现在还包含了自 Windows Vista 起就存在但未纳入旧版 MFC 的其他一些 Windows 功能。例如,重新启动管理器是 Windows Vista 中引入的一项有用的功能,可以使应用程序在终止前执行保存操作。应用程序可以调用此功能,然后在重新启动时还原其状态。现在,您可以在 MFC 应用程序中充分利用重新启动管理器,更妥善地处理崩溃和重新启动。只需在您的现有应用程序中添加一行代码即可启用重新启动和恢复:

CMyApp::CMyApp() {
  m_dwRestartManagerSupportFlags = 
    AFX_RESTART_MANAGER_SUPPORT_RESTART;
// other lines of code ...
}

新的 MFC 应用程序通过使用 MFC 应用程序向导自动获得此功能。自动保存机制适用于保存文档的应用程序,自动保存间隔可由用户定义。在 MFC 应用程序向导中,应用程序可以只选择重新启动支持或应用程序恢复启动(适用于文档/视图类型的应用程序)。

另一项新增功能是 Windows 任务对话框,这是一种改进的消息框(请参见图 9)。MFC 现在为该任务对话框提供一个包装,可供您在自己的应用程序中使用。

图 9 任务对话框
图 9 任务对话框

MFC 类向导回来了

此版本不仅在 MFC 库中添加了新功能,还简化了在 Visual Studio IDE 中使用 MFC 的方式。作为一项用户最常要求使用的功能之一,MFC 类向导现已恢复使用并且得以改进(如图 10 所示)。现在可以使用 MFC 类向导向您的应用程序中添加类、事件处理程序和其他元素。

图 10 MFC 类向导
图 10 MFC 类向导

功能区设计器是另一个新增组件,使用它可以采用图形方式设计您的功能区 UI(而不是像 Visual Studio 2008 中那样在代码中定义)并将其存储为 XML 资源。此设计器对创建新应用程序特别有用,而且现有应用程序也可以利用此设计器更新其 UI。向功能区 UI 的现有代码定义临时添加一行代码即可创建 XML 定义:

m_wndRibbonBar.SaveToXMLFile(L"YourRibbon.mfcribbon-ms");

然后,就可以使用得到的 XML 文件作为资源文件,并可以使用功能区设计器进行进一步修改。

总结

Visual Studio 2010 是 Visual C++ 演变过程中的一个主要版本,为开发人员在很多方面带来了方便。在本文中,我只是介绍了众多与 C++ 相关改进中的皮毛。有关各功能的进一步讨论,请参考 MSDN 文档和 Visual C++ 团队的博客,博客网址是 blogs.msdn.com/vcblog(本文部分章节内容也参考了其中的文章)。   

Sumit Kumar 是 Visual C++ IDE 团队的一名项目经理。他拥有达拉斯德克萨斯大学计算机科学专业硕士学位。

感谢以下技术专家: Stephan T. Lavavej、Marian Luparu 和 Tarek Madkour