我正在使用 Visual C++ 的资源编辑器创建一个对话框。
当我运行编辑器的测试按钮时,对话框的组件以现代的外观显示,而当运行创建并显示对话框的应用程序时,它以旧的外观显示......我只是使用 WINAPI 调用显示对话框,而不是 MFC。
以下是屏幕截图(上图是设计时 UI 外观的示例,另一张是运行时 UI 外观的示例):
有人知道我做错了什么吗?
您是否已正确设置清单以在项目中使用 commctl32.dll 版本 6?如果没有,您将无法获得主题控件。
在 Visual Studio 的更高版本中,这通常是使用 #pragma 完成的,如下所示(这个适用于 x86,从 VS2005 生成的新项目复制):
#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='x86' publicKeyToken='6595b64144ccf1df' language='*'\"")
如果您将其添加到项目中的源文件之一并重建,清单将由链接器生成并添加到您的应用程序中。对于其他处理器架构,您需要更改“processorArchitecture”值。 (为什么VS自己无法弄清楚这一点,这是一个留给读者去解决的谜......)
(正如其他一些人所指出的,您还可以手动生成清单并将其添加到 .rc 文件中。这比较冗长,但确实可以让您完全控制清单的内容。)
您的应用程序清单是否指定您要使用 comctl32.dll 版本 6?这是在 Windows XP 中使用视觉样式和更现代的外观的要求之一。
创建清单并使您的应用程序能够使用视觉样式。
链接到 ComCtl32.lib 并调用 InitCommonControls(请参阅 MSDN 库中的 Platform SDK 文档)。
将名为 YourApp.exe.manifest 的文件添加到具有以下 XML 格式的源树:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity
version="1.0.0.0"
processorArchitecture="X86"
name="CompanyName.ProductName.YourApp"
type="win32"
/>
<description>Your application description here.</description>
<dependency>
<dependentAssembly>
<assemblyIdentity
type="win32"
name="Microsoft.Windows.Common-Controls"
version="6.0.0.0"
processorArchitecture="X86"
publicKeyToken="6595b64144ccf1df"
language="*"
/>
</dependentAssembly>
</dependency>
</assembly>
将清单添加到应用程序的资源文件中,如下所示
CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST "YourApp.exe.manifest"
注意:将上一个条目添加到资源时,必须将其格式化为一行。或者,您可以将 XML 清单文件放置在与应用程序的可执行文件相同的目录中。操作系统将首先从文件系统加载清单,然后检查可执行文件的资源部分。文件系统版本优先。
一旦应用程序绑定到 Comctl32.dll 6.0 版,某些 Windows 窗体控件就会呈现其新外观。以及如何实现这一点,请参阅在 Windows 窗体上使用带有控件的 Windows XP 视觉样式
我有一个针对 VC6 的解决方案,但我不确定它是否适用于 VS 2008。
(另请检查本文以了解导致问题的原因)
这是我用来解决这个问题的简单清单文件的示例:
创建以下 XML 文件,
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1"
manifestVersion="1.0">
<assemblyIdentity
version="1.0.0.0"
processorArchitecture="X86"
name="Microsoft.Windows.YourApplication"
type="win32"
/>
<description>YourApplication</description>
<dependency>
<dependentAssembly>
<assemblyIdentity
type="win32"
name="Microsoft.Windows.Common-Controls"
version="6.0.0.0"
processorArchitecture="X86"
publicKeyToken="6595b64144ccf1df"
language="*"
/>
</dependentAssembly>
</dependency>
</assembly>
首先,我们在resource.h 文件中添加两行。只需复制并粘贴以下内容:
#define IDR_MANIFEST 1
#define RT_MANIFEST 24
现在,打开应用程序自定义资源文件。通常,它位于 res 目录中;默认扩展名是 .rc2。手动添加以下行:
// Add manually edited resources here...
IDR_MANIFEST RT_MANIFEST MOVEABLE PURE
"res\\ApplicationManifestXMLFile"
将 ApplicationManifestXMLFile 替换为实际文件名(您创建的 XML)。
该问题指定了 C++,并且 另一个问题展示了如何更干净地完成它。
对于.Net 2.0+,请参阅>这篇MSDN文章<了解如何用一行代码完成它,即:
Main()
{
Application.EnableVisualStyles();
}
我希望这可以帮助搜索该主题的人。
扩展现有答案...
将以下内容放入 stdafx.h 对我来说效果很好,并有助于在运行时显示 VS 对话框资源编辑器中显示的细边框样式:
#ifdef UNICODE
#if defined _M_IX86
#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='x86' publicKeyToken='6595b64144ccf1df' language='*'\"")
#elif defined _M_IA64
#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='ia64' publicKeyToken='6595b64144ccf1df' language='*'\"")
#elif defined _M_X64
#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='amd64' publicKeyToken='6595b64144ccf1df' language='*'\"")
#else
#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
#endif
#endif
如果有人因为与我相同的原因找到这篇文章,我想知道为什么(在某些 Python 应用程序中)调用 PrintDlgW() 会导致旧版打印对话框,而不是 Win 10/11 的“现代”UWP 打印对话框。
这不是关于缺少清单的问题(据我所知,Python 的 ctypes/libffi 在加载像 comdlg32 这样的 Windows dll 时会处理这个问题),但事实证明,关键因素是传递给 PrintDlgW() 的 PRINTDLGW 结构的“hwndOwner”字段. 仅当您将 hwndOwner 设置为实际窗口的 HWND 时,如果将其设置为 NULL,您将获得现代打印对话框版本(或者,在 Python 中,根本不设置它,因为 ctypes 将所有“结构”字段设置为 NULL默认)您将获得旧版打印对话框版本。