为Vista而生:MFC 9
自从2002年引入.NET Framework以来,MFC再没有添加多少新功能了,这多少可归咎于这段时期内微软没有发布新的Windows操作系统,另外,也有着一种潜在的倾向,就是本机开发的衰败使得MFC的改进也有点多余。随着Visual Studio 2008的发布及Windows Vista带来的数千个新的本机API,本机开发又显现出蓬勃生机,而MFC也从中受益,比如说添加了新的控件,及对现有控件的改进以支持Vista外观。
对用Visual C++ 2008新创建的MFC程序来说,当在Vista系统上运行时,所有MFC控件都会自动使用新的Vista控件;另一方面,如果某个程序是由早期版本的Visual C++开发的,由Visual C++ 2008重新编译之后,在Vista上运行时,也会使用Vista的通用控件。当在Windows Server 2003或更早的系统中运行时,这些基于MFC的程序也会自动降级为老式的通用控件。举例来说,Visual C++ 6自带的Scribble示例程序中的文件保存对话框,在用Visual C++ 2008重新编译后,在Windows Vista上运行时如图1所示:
图1:运行在Vista上用Visual C++ 2008编译的Scribble
同一个程序如果运行在Windows Server 2003上时,就会如图2所示:
图2:运行在Windows Server 2003上用Visual C++ 2008编译的Scribble
为了对比,图3是同一程序用Visual C++ 2005编译后运行在Vista上的样子:
图3:运行在Vista上用Visual C++ 2005编译的Scribble
在Scribble这个例子中,MFC的文档视结构自动处理了文件对话框的显示,但如果要在代码中显式创建一个派生自CFileDialog的对话框,就有一个新的可选参数可添加到构造函数中,以指定是否使用Vista样式,如图4所示:
图4:CFileDialog构造函数参数列表
虽然简单地使用Visual C++ 2008重新编译一番代码,也可给程序带来某些Vista外观,但仍有必要手工作一些修改才可完全保持Vista样式。首先,就是要设定好界面控件的字体,以便在Vista上正常显示。在Scribble程序中,Pen Width(笔宽)对话框中的字体为MS San Serif,它是位图字体,且不支持Vista ClearType技术的反锯齿显示。在Vista上使用非ClearType字体看上去有点不相称,如图5:
图5:使用MS San Serif字体的Scribble Pen Width对话框
通过Pen Width对话框的属性窗口,可以将“使用系统字体”(Use System Font)属性设为true,这意味着对话框将使用伪字体“MS Shell Dlg”。在使用这个伪字体之后,会使用注册表的HKEY_LOCAL_MACHINE/Software/Microsoft/Windows NT/Current Version/FontSubstitutes键值来把伪字体翻译为真实字体,比如说,在英文版Vista安装时,将会是Microsoft Sans Serif字体。与名字类似的MS San Serif相比,Microsoft Sans Serif是一种OpenType字体格式,而OpenType字体可使用ClearType技术中的反锯齿。尽管名字上差别很小,但在Vista中,尤其ClearType已是标准的情况下,效果差别还是很明显的,如图6所示:
图6:把System Font设为true之后,Vista上的Scribble Pen Width对话框
其次,是在界面中使用Windows XP中的Windows Common Controls(Windows通用控件)版本6。因为与之前版本的通用控件差别过大,因此除非显式要求,否则不会使用版本6的控件。所以,要把一个老的MFC程序升级为使用新控件,最简单的方法就是在stdafx.h文件中添加以下代码:
#pragma comment(linker,"/manifestdependency:/"type='win32'
name='Microsoft.Windows.Common-Controls' version='6.0.0.0'
processorArchitecture='x86' publicKeyToken='6595b64144ccf1df'
language='*'/"")
这些pragma注释在清单文件中添加了一个节,以告之Windows使用通用控件版本6,图7是运行在Vista上,使用版本6控件的Scribble Pen Width对话框。
图7:运行在Vista上,使用版本6控件的Scribble Pen Width对话框
最后,就是菜单栏的自动隐藏,且会在按下ALT键时显示出来。CFrameWnd类有一个新方法名为SetMenuBarVisibility,它控制着菜单栏默认情况下是否可见。对菜单栏的可见性有三个设置:AFX_MBV_KEEPVISIBLE、AFX_MBV_DISPLAYONFOCUS(菜单栏在按下ALT键时显示)、AFX_MBV_DISPLAYONF10(菜单栏在按下F10时显示)。而Scribble示例程序是一个MDI程序,因此CMDIFrameWnd隐藏了SetMenuBarVisibility以防止菜单栏被隐藏。这是因为Visual C++小组的Sarita Bafna所言:“与子窗口关联的,在菜单栏之上的最小化、还原、关闭按钮行为不明确;及大多数MDI程序都有较复杂的菜单,而Vista界面方针也不鼓励隐藏复杂的菜单栏”。
要允许scribblee有可隐藏菜单,必须把它转换为SDI程序,这可以通过把一些MFC基类由MDI版本替换为SDI版本,示例中还从Visual C++ 2008生成的MFC程序中复制了主窗体图标,这些图标支持48*48像素,且包含8位及24位色深的版本。Scribble最终看起来像图8这样:
图8:更新图标后,且有自动隐藏菜单栏的Scribble