当前位置:C++技术网 > 资讯 > MFC如何配置使用Win7风格的控件而不是XP风格控件

MFC如何配置使用Win7风格的控件而不是XP风格控件

更新时间:2016-06-01 20:56:22浏览次数:1+次

    今天在项目中使用了控件,然后发现控件很丑。经过上网一番查找,勉强找到了一个解决办法,然而却不知所以然,还是稀里糊涂的。尽管解决了,但是不知道为什么,必将在以后遇到时又很烦躁。所以,就索性深入研究一下。下面分享研究的成果。

    VS项目使用的字符集会影响使用的界面控件的版本,从而影响界面效果。Unicode版会自动嵌入Win7风格的控件,多字节版则不会嵌入Win7风格控件,而是使用很老风格的控件。而不同的字符集默认情况下会决定使用的控件版本。表面上,修改字符集就可以达到修改使用的控件版本了。如果你使用了多字节字符集发现控件变成了很老的控件样子,可以切换字符集为Unicode即可解决。
    然而,如果你因为代码中必须使用多字节字符集,是不是没有办法解决这个问题了呢?不是的。有时候你也会发现,不管你切换为哪个字符集,都没有用,控件还是那个很丑的版本。下面看两张图:

第一张:使用Unicode字符集的控件样子

使用Unicode字符集的控件样子

第二张:使用多字节字符集的控件的样子

使用多字节字符集的控件的样子

    可以说,使用多字节字符集的控件的样子实在是太丑了,都没法凑合着看。如果你还停留在切换字符集实现控件版本的切换,那就太Low了。实际上,有的项目因为设置太多,可能设置乱了,也就导致切换字符集根本就没有卵用。而且,有时候,已有的代码只能工作在多字节字符集下,这不是懵逼了么!

    其实,实现控件版本切换的是一个后缀为manifest的文件,通常名称为:应用软件名称.exe.manifest。如果程序名称为cjjjs.com,那么这个文件名为:cjjjs.com.exe.manifest。这个manifest是应用程序的配置文件,实际上就是一个xml文件。正是这个文件的设置不对,才导致了控件版本设置的不合人意。
    如果你使用多字节字符集编译的话,manifest文件内容如下:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
<security>
<requestedPrivileges>
<requestedExecutionLevel level="asInvoker" uiAccess="false"></requestedExecutionLevel>
</requestedPrivileges>
</security>
</trustInfo>
<application xmlns="urn:schemas-microsoft-com:asm.v3">
<windowsSettings>
<ms_windowsSettings:dpiAware xmlns:ms_windowsSettings="http://schemas.microsoft.com/SMI/2005/WindowsSettings" xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true</ms_windowsSettings:dpiAware>
</windowsSettings>
</application>
</assembly>
    VS自动生成manifest文件内容只有一行,我打成很多行了,便于阅读。你在这个manifest文件中找不到任何控件版本的信息。
    然后,我们再来看Unicode字符集生成的manifest文件的内容:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<dependency>
<dependentAssembly>
<assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0" processorArchitecture="x86" publicKeyToken="6595b64144ccf1df" language="*">
</assemblyIdentity>
</dependentAssembly>
</dependency>
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
<security>
<requestedPrivileges>
<requestedExecutionLevel level="asInvoker" uiAccess="false">
</requestedExecutionLevel>
</requestedPrivileges>
</security>
</trustInfo>
<application xmlns="urn:schemas-microsoft-com:asm.v3">
<windowsSettings>
<ms_windowsSettings:dpiAware xmlns:ms_windowsSettings="http://schemas.microsoft.com/SMI/2005/WindowsSettings" xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true</ms_windowsSettings:dpiAware>
</windowsSettings>
</application>
</assembly>
    同样,VS自动生成的manifest文件只有一行,我打成很多行了,便于阅读。此时看到的manifest文件多了一些内容。很明显,你可以看到Microsoft.Windows.Common-Controls字样,然后看到version="6.0.0.0"的字样,这已经表明了这个配置文件确定使用的控件版本为win7风格的控件。假如你将下面这一段包含控件版本信息的删掉,然后保存编译。你会发现,控件又恢复了老版本控件风格,删除的内容如下:
<dependency>
<dependentAssembly>
<assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0" processorArchitecture="x86" publicKeyToken="6595b64144ccf1df" language="*">
</assemblyIdentity>
</dependentAssembly>
</dependency>
    很明显,这一段配置也就是决定控件风格的东西。实际上与项目使用的字符集没有直接关系,只是说,默认情况下,设置了Unicode字符集,VS会自动加上这一段配置信息。但是也有情况加不上,也就导致了即使是Unicode字符集,也老版本控件。问题就出在manifest配置文件没有控件版本的信息。如果有,还得确保版本是6.0.0.0哦。
    好了,到了这里,谜团解开了。你再也不用纠结于字符集的问题了。那么我这两个manifest文件内容是如何得来的呢?当然不会在网上找,不靠谱。而是直接在VS中生成的文件中得来的。

    看看VS项目属性的一个配置文件清单设置,如下图所示:

VS项目属性的一个配置文件清单设置

    清单工具其实就是设置manifest配置文件的相关信息的。默认情况下,生成的manifest配置文件会嵌入到exe文件内部。这样在运行的时候,不用随着exe带着一个manifest配置文件。当然,如果像图中一样取消嵌入清单选项,那么VS会将manifest配置文件生成在exe同一目录下,而且名字就是exe文件名称.exe.manifest。exe运行时就会读取manifest配置文件,然后决定使用什么版本的控件。如果缺少manifest配置文件,那么exe将无法启动。
    自然,我就是不让它将manifest配置文件嵌入exe,设置了不同的字符集,然后得到了不同字符集下的manifest配置文件的内容,也就发现了Unicode字符集生成的manifest配置文件含了使用win7风格的控件版本信息。
    所以,你即使是多字节字符集,你只要将描述exe使用的控件版本信息放入多字节字符集生成的manifest配置文件中,就可以在多字节字符集的项目中使用win7风格控件了。
    好了,原因和解决方法都说明了。现在是实战动手的时候了。
    你想修改manifest配置文件,首先就要像上图一样,将嵌入清单取消,然后你可以得到Unicode版的manifest配置文件。然后你将项目的字符集切换为多字节字符集,然后编译生成了多字节字符集的manifest配置文件,你用Unicode版的manifest配置文件去替换一下,然后重新编译,就可以实现了多字节字符集下的win7风格控件了。
    当然,此时你的manifest配置文件是不内嵌的,所以在运行的时候,使用要和exe一起,不能缺少。这样也就不方便了。如果你直接改为内嵌清单文件,你又不能控制使用的控件版本了(可以通过代码的方式控制,不过一下子不知道如何做,如果你知道,请告知一下)。所以看似又没法起作用了。
    不急,在清单工具上,不是有一个【附加清单文件】的选项吗!你将得到的Unicode版的manifest配置文件放在代码文件夹下(cpp文件所在的文件夹),然后在【附加清单文件】中填入manifest配置文件的名称。【嵌入清单】选项设置为是。此时表示,你将要使用指定的manifest配置文件配置程序,且将manifest配置文件的内容内嵌到exe中,这样决定控件版本的就是代码文件夹下的manifest配置文件了。只要这文件里含了使用win7风格控件的配置信息,也就可以使用win7风格控件了,而且无视项目字符集的影响。
    如果你懒得从VS中生成使用win7风格控件的manifest配置文件,可以直接将文中的内容保存到manifest配置文件中即可。这是最快的方式了。
    而【输入资源清单】中,可以填写资源的ID,也可以使用manifest配置文件。当然前提是,你要想添加一个位图资源一样,将manifest配置文件添加到项目中,然后设置好ID,然后填在【输入资源清单】中,也可以实现这个效果。