这是一个老掉牙的问题了,现在写,一是因为我才接触这一类界面美化(以前一直以功能为主,需要漂亮界面也都是自己画的),二是发现网上的内容很多不准确,所以在这里整理一下。
1,Manifest方法,即通过Microsoft Windows Common Controls 的DLL文件Comctl32.dll(版本6)来加载具备XP风格的组件。这个dll和ocx的版本6不同。下面其它方法也都是以此为基础的。
- 用文本编辑器编写一个App.exe.Manifest文件,放到App.exe同文件夹下,注意与App同名。
-
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"> <assemblyIdentity name="XP style manifest" processorArchitecture="x86" version="1.0.0.0" type="win32"/> <dependency> <dependentAssembly> <assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0" processorArchitecture="x86" publicKeyToken="6595b64144ccf1df" language="*" /> </dependentAssembly> </dependency> </assembly>
※ 风格代码需要在加载窗体之前运行,所以不要在Form_load中初始化,否则窗口无法加载
-
在启动窗体代码中加入窗口初始化代码。
-
Private Declare Sub InitCommonControls Lib "comctl32.dll" () Private Sub Form_Initialize() InitCommonControls End Sub
-
或者在模块中加入类似代码,并把启动过程设置为Sub Main(),上面的简单,下面的复杂,两个实测都可用。
-
函数InitCommonControls是个空函数,不做任何事情,只改变入口点,会影响(大部分)通用控件。InitCommonControlsEx则可以指定要初始化的控件。
-
Private Declare Function InitCommonControlsEx Lib "comctl32.dll" _ (iccex As tagInitCommonControlsEx) As Boolean Private Type tagInitCommonControlsEx lngSize As Long lngICC As Long End Type Private Const ICC_USEREX_CLASSES = &H200 'VB实现XP风格的初始化函数 Public Function InitCommonControlsVB() As Boolean On Error Resume Next Dim iccex As tagInitCommonControlsEx With iccex .lngSize = LenB(iccex) .lngICC = ICC_USEREX_CLASSES End With InitCommonControlsEx iccex InitCommonControlsVB = (Err.Number = 0) On Error GoTo 0 End Function Sub Main() '需要设置以此为启动函数 InitCommonControlsVB '调用初始化函数 Form1.Show End Sub
编译后运行可以看到基础控件、Microsoft Windows Common Controls 5.0控件(6.0不行,下图右侧是6.0控件)都变成XP/Win7风格(我是在Win7下测试的,XP没看到)
2,资源(.RES)方法,即把上面的.manifest文件作为资源参与编译。要点:
- 资源类型必须是24,标识号为1,自定义无法添加(类型会有""号),所以需要使用资源编译工具。
- .manifest文件长度必须可被4整除(可以在文本末加空格凑数)。
在.manifest目录中,新建一个文本文件,内容为
1 24 App.exe.manifest
保存后将文件改名为xp.rc,然后在命令提示符下进入VB安装目录的Wizard目录(如C:\Program Files\Microsoft Visual Studio\VB98\Wizards),在提示符处输入下行命令:
rc /r 文件所在路径\xp.rc
这样,资源文件xp.res就编译好了,这个资源可以在任意工程中使用,不需要另外的处理。
3,使用工具eXeScope。打开eXeScope,选择文件->打开,打开你的程序。再选择编辑->XP样式,在对话框中确定即可。
这里是自动保存的,所以需要的话请事先备份。
4,未证实的问题:
- Form_Initialize不太保险,最好还是用Sub Main()
- 即便是使用eXeScope,也需要对程序进行处理如下(按照方法二推论,实际是不需要这个处理的)
API声明:Private Declare Function InitCommonControls Lib "Comctl32.dll" () As LongPrivate Sub Form_Initialize()
InitCommonControls
End Sub在主窗口结束处添加代码,没有这些代码,程序结束后可能提示错误。Private Sub Form_Unload(Cancel As Integer)
On Error Resume Next
End
End Sub
- 把.exe.manifest配置好后,可以看到win7风格,把manifest改名后,win7风格没了。然后再改名回来,win7风格没恢复!
- 有时候使用屏幕缩放显示(比如125%显示),会造成一些早期的程序,比如VB编译的程序显示界面的文字或者线条模糊,可以使用dpi自动设置的manifest:
- Setting the default DPI awareness for a process (Windows) - Win32 apps | Microsoft Learnhttps://learn.microsoft.com/en-us/windows/win32/hidpi/setting-the-default-dpi-awareness-for-a-process
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0" xmlns:asmv3="urn:schemas-microsoft-com:asm.v3">
<asmv3:application>
<asmv3:windowsSettings>
<dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true</dpiAware>
<dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2</dpiAwareness>
</asmv3:windowsSettings>
</asmv3:application>
</assembly>