MFC:如何为所有者绘制渲染 Aero 风格的组合框?

Posted

技术标签:

【中文标题】MFC:如何为所有者绘制渲染 Aero 风格的组合框?【英文标题】:MFC: how to render an Aero-style combo box for owner draw? 【发布时间】:2012-03-15 04:20:32 【问题描述】:

我继承了一个大型 MFC 应用程序,其中包含一个覆盖 OnPaintCComboBox 子类。目前,它的所有绘图都是手工完成的(使用线条和矩形),并呈现一个看起来明显是 Windows 98 风格的组合框。但是,它在其他方面工作得很好,并提供了许多我们所依赖的有用的自定义功能,并且重写整个控件可能不是一种选择。

我想对其进行现代化改造,以便 OnPaint 在可用的情况下以 Aero 样式绘制(当现代主题不可用时,回退到旧代码)。我已经使用我们拥有的其他一些自定义控件(如按钮)完成了此操作,它非常适合我们的目的。我知道有一些小行为是无法正确处理的,例如鼠标悬停时的柔和高光,但这对这个应用来说没什么大不了的。

我可以访问CVisualStylesXP ckass,所以我已经有了基础设施,可以很容易地拨打OpenThemeDataGetThemeColorDrawThemeBackground 之类的电话(通过LoadLibrary,所以我们不会强制使用Vista作为最小系统)。不幸的是,我不知道正确的调用顺序来获得带有主题适当边框和下拉按钮的漂亮组合框。

有人知道在这里做什么吗?

【问题讨论】:

【参考方案1】:

老实说,我不知道他们为什么最初试图覆盖 OnPaint。有充分的理由吗?我认为至少 99% 的时间你只是想要覆盖 ComboBox 中项目的绘制。为此,您可以在派生的组合框中覆盖 DrawItem、MeasureItem 和 CompareItem 以获得所需的功能。在这种情况下,操作系统将正确绘制特定于每个操作系统的非用户内容。

【讨论】:

老实说,是的,它基本上看起来像一个普通的组合框,除了中间显示的文本。但我真的不想重新架构它。 实际上,再想一想,它使 Droplist 看起来更像一个 Dropdown(它基本上允许用户键入文本的任何子集,然后列表显示过滤结果)。仅仅像 Droplist 一样绘制是错误的。【参考方案2】:

我认为你最好不要深入 xp 主题和各种系统指标的深度,看看这个项目:http://www.codeproject.com/Articles/2584/AdvComboBox-Version-2-1

检查 CAdvComboBox 类的 OnPaint - 控件重绘的完整实现包括 xp 主题相关问题。

【讨论】:

不幸的是,我已经试过了,它看起来一点也不像 Aero 组合框。在我看来,他们对它进行了黑客攻击并做出有根据的猜测,直到视觉外观与 XP 所做的相匹配,但对于 Aero 来说这是完全错误的。例如,右边缘的箭头按钮包含在一个方形按钮中,这对于 Luna 是正确的,但对于 Aero 是错误的。 哦,我的错。好的,还有另一种可能更复杂,可以从中删除相关代码,但可以更好地使用航空风格。 codeproject.com/Articles/130682/…相关代码在VComboBox.cpp文件中【参考方案3】:

不确定是否是相同的情况 - 但是当我遇到这个问题时(在我的情况下使用子类 CButtons),解决它只需要将控件声明更改为指针并动态创建控件。

假设您的子类控件名为 CComboBoxExt。 你在哪里

CComboBoxExt m_cComboBoxExt;

你现在有

CComboBoxExt* m_pcComboBoxExt; 

在放置控件的窗口的 OnInitDialog 上,您使用

创建它
m_pcComboBoxExt = new CComboBoxExt();  
m_pcComboBoxExt->Create(...)

既然这是一个指针,别忘了调用DestroyWindow() 并在终止时删除指针。

这解决了我的特殊问题 - 如果您的控件以相同的方式声明,请考虑尝试一下。

【讨论】:

这不会修复我的手动绘制线条和填充框的OnPaint

以上是关于MFC:如何为所有者绘制渲染 Aero 风格的组合框?的主要内容,如果未能解决你的问题,请参考以下文章

使用 MFC,如何为带有圆角和阴影的 CEdit 控件设置样式?

使WPF程序应用预置的控件风格, 如Aero, Luna, Royale, Classic等

如何为 OpenGL 文本渲染计算字符映射中的最佳字形边界

如何用c++的mfc绘制柱状图

如何为 MFC 中的多个按钮编写一个消息处理程序?

如何为每种风格生成单独的签名APK?