在音频频谱分析中,经常需要以直观的方式展示不同频率成分的置信度。一种常见的方法是使用颜色渐变,其中颜色的强度随着置信度的增加而增强,当置信度为零时则渐变为白色。这样的渐变不仅美观,而且能够提供丰富的信息。然而,实现这种渐变效果并非易事,尤其是在不同的分辨率下保持一致性,并且考虑到人眼对颜色的非线性响应。
不喜欢手动输入表格并进行实验,也不想使用PowerPoint或Corel PhotoPaint等工具来创建渐变,然后将结果手动转换为C/C++代码。因此,编写了一个小工具程序,它可以创建并读取RGB声明,这些声明适合包含在C/C++源文件中。
在创建这个工具之后,对代码进行了一些清理,并决定将其发布,作为一个自定义控件的示例。其中一个控件是自定义绘制按钮,详细内容可以在关于“更好的位图按钮”的配套文章中找到。另一个控件是一个自定义绘制的ListBox,它在“日志ListBox控件”文章中以另一种形式出现。
ComboBox控件的有趣之处在于,它是带有LBS_HASSTRINGS的自定义绘制,而ListBox则是没有LBS_HASSTRINGS的自定义绘制,因此可以研究两种不同的风格。
下面是一个控件的示例。请注意,ListBox中的选择高亮并不延伸到整个条目(考虑到要显示颜色,这是没有意义的),而且选择高亮是灰色的,因为ListBox当前没有焦点。一个按钮数组允许立即选择常见的R、G和B值。在ListBox中,只存储COLORREF值,字符串和颜色是在绘制时生成的;在ComboBox中,ItemData存储COLORREF,字符串值存储名称,但颜色样本和颜色值是在绘制时生成的。示例颜色样本区域代表一个简单的CStatic,颜色是通过一个简单的OnEraseBkgnd处理程序绘制的。
由于这最初是为了解决特定问题而快速构建的解决方案,没有应用所有的标准生产质量技术(例如,将所有英文字符串保存在STRINGTABLE中),所以它并不代表认为可以交付给客户的代码,但它是一个接近的近似。
以下是实现颜色渐变的C++代码示例:
#include <windows.h>
void CreateColorGradient(HDC hdc, int x, int y, int width, int height) {
// 初始化渐变开始和结束的颜色
int startColor = RGB(255, 0, 0); // 红色
int endColor = RGB(255, 255, 255); // 白色
// 创建渐变效果
for (int i = 0; i < height; ++i) {
int r = GetRValue(startColor) + (GetRValue(endColor) - GetRValue(startColor)) * i / height;
int g = GetGValue(startColor) + (GetGValue(endColor) - GetGValue(startColor)) * i / height;
int b = GetBValue(startColor) + (GetBValue(endColor) - GetBValue(startColor)) * i / height;
int color = RGB(r, g, b);
// 在指定位置绘制一条水平线
Rectangle(hdc, x, y + i, x + width, y + i + 1);
}
}