在本文中,将探讨如何使用特定的类来自定义窗口标题栏,包括背景颜色、文本字体和颜色,以及如何实现多行标题栏。这些类可以独立地为任何选定的窗口更改活动和非活动窗口标题栏的背景颜色和文本字体及颜色。此外,还提供了一个示例类,允许使用位图作为标题栏背景,例如用于徽标,或实现木纹或石纹效果。
几年前,正在编写一个使用VC++/MFC MDI数据库查询应用程序,该程序将查询结果以表格或数据列表的形式呈现在MDI子窗口中。一个与特定窗口使用的查询相关的标题显示问题出现了,例如“生产力排行榜:英国媒体公司,其中净营业额 > 2500万英镑且员工人数 > 3500”。一些标题甚至比这更长,并且在作为窗口标题栏显示时常常被截断。当用户平铺多个这样的窗口时,情况变得更糟,因为他们最终会得到五个或六个窗口,标题分别是“生产力排行榜:英国...”和“公司新闻头条:金融...”,等等。显然,当他们的标题栏看起来都在说同样的事情时,找到感兴趣的特定窗口是一个令人头痛的问题!
有几种解决方案可以解决这类问题,例如使用工具提示或仅依赖于客户端区域中的标题,但所有这些似乎都有令人烦恼的缺点。不禁觉得,即使对于像这样的长标题,标题栏也是正确的位置,这样可以一目了然地知道窗口是关于什么的。尝试使用1997年微软系统杂志C++问答文章中Paul DiLascia描述的拥有绘制渐变色标题栏背景的方法,实验了拥有绘制标题栏的方法。结果比预期的要好,所以想把它们重新加工成任何人都可以使用的东西。
以下是一些关键类及其功能:
声明一个标题对象(CSingleLineCaption、CMultiLineCaption或CMultiLineCaptionEx)作为框架窗口类的成员:
#include "..\CustomCaption\MultiLineCaptionEx.h"
class CChildFrame : public CMDIChildWnd {
...
private:
// 声明一个标题对象(这是一个扩展的多行标题)
CMultiLineCaptionEx m_Caption;
...
};
在框架窗口类的OnCreate()方法中安装标题(可能需要使用ClassWizard来插入此函数。注意:选择'WM_CREATE'消息,而不是'Create'消息):
int CChildFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) {
if (CMDIChildWnd::OnCreate(lpCreateStruct) == -1)
return -1;
// TODO: 添加专业创建代码
// 安装标题到框架
m_Caption.Install(this);
return 0;
}
就是这样!如果像上面那样安装了一个多行标题,太长而无法适应单行的标题将自动包装到新行上。可以使用SetMaxLines()方法更改标题将允许的最大行数。
现在可以使用标题对象来设置标题的颜色和字体。为此,请使用CCaption方法访问CCaptionBackground和CCaptionTextAttributes对象,并修改它们的内容,例如:
// 设置活动文本和背景颜色
COLORREF colorText = RGB(txt_red, txt_green, txt_blue);
COLORREF colorBk = RGB(bk_red, bk_green, bk_blue);
m_caption.GetTextAttributes()->
SetActiveColor(colorTxt);
m_caption.GetBackground()->
SetActiveColor(colorBk);
// 获取活动字体并将其更改为Arial斜体
LOGFONT lf;
m_caption.GetTextAttributes()->
GetActiveFont()->
GetLogFont(&lf);
lf.lfFaceName = "Arial";
lf.lfItalic = TRUE;
m_caption.GetTextAttributes()->
SetActiveFont(lf);
// 刷新标题,使更改立即生效
m_Caption.Refresh();
要更改为不同的背景样式,或一次性替换所有文本属性,可以创建一个新的CCaptionBackground或CCaptionTextAttributes对象,按照要求初始化它,并使用CCaption方法SetBackground()或SetTextAttributes()将其设置到标题中:
// 构造一个渐变背景对象
CCaptionBackground* pNewBackground = new CGradientCaptionBackground();
// 设置所需的颜色
pNewBackground->
SetCustomColors(ACTIVE_COLOR, INACTIVE_COLOR);
// 设置新背景
m_Caption.SetBackground(pNewBackground);
不用担心删除背景或文本属性对象,标题会为处理的。
如果有人能解释一下在显示窗口系统菜单后发生的Windows 95和WinNT秘密标题栏绘制的奇怪特性,将非常感兴趣(尝试安装一个CMultiLineCaption,设置一个长窗口标题,使标题栏包装到多行,然后点击窗口图标以显示系统菜单,就会明白意思。正常的窗口标题在鼠标穿过非客户区域或在标题栏中点击时会被重绘,而没有发送任何NC_PAINT消息)。为什么?
显示标题栏中位图的提示 - 如果希望在更大的位图顶部显示一个短标题,请在标题后追加一长串空格,以说服它包装到更多行。
下载演示可执行文件 - 32 KB。这包含演示应用程序可执行文件CaptionDemo.exe和自定义标题DLL CustomCaption.dll。
下载演示项目 - 75 KB。演示项目实际上是一个VC++6.0工作区,包含两个项目,Caption Demo应用程序和Custom Caption DLL项目。它们安装到不同的文件夹中,所以应该使用路径信息进行解压缩。
仅下载源代码 - 25 KB。这仅包含Custom Caption类的源代码。