在Windows应用程序开发中,为了提供更丰富的用户界面,经常需要自定义控件。本文将介绍如何实现一个在WindowsXP主题下具有文本加粗和下划线效果的自定义按钮。
在开发一个消费者应用程序时,客户要求实现一个类似于Windows资源管理器右键菜单中的“搜索...”按钮。这个按钮在选中时文本加粗,鼠标悬停时文本下划线。对于单选按钮和复选按钮,也需要实现类似的效果。
自定义按钮的难点在于处理多种状态和模式。特别是ownerdraw按钮,需要特殊处理才能在主题化的XP下看起来正确。
为了进一步调查,使用了最喜欢的编程工具之一,HPS HwndSpy。它显示按钮并非ownerdraw,这让松了一口气。
既然确定不需要将按钮设置为ownerdraw,决定API可以非常简单,只有显示状态:加粗、下划线或加粗和下划线。
enum Emphasis {
NONE = 0,
BOLD, // 如果GetCheck()为TRUE,则按钮文本将加粗
UNDERLINE, // 如果鼠标悬停,则按钮文本将下划线
BOLD_AND_UNDERLINE
};
CXEmphasisButton::Emphasis GetEmphasis() {
return m_eEmphasis;
}
void SetEmphasis(Emphasis eEmphasis) {
m_eEmphasis = eEmphasis;
SetEmphasisFont();
}
在PreSubclassWindow()中创建四种字体,在DefWindowProc()中处理三个消息:
if (message == BM_SETCHECK) {
if (wParam == BST_CHECKED) {
if (m_eEmphasis == BOLD || m_eEmphasis == BOLD_AND_UNDERLINE) {
if (!m_bBold) {
if (m_bUnderline) {
SetFont(&m_fontBoldAndUnderline);
} else {
SetFont(&m_fontBold);
}
m_bBold = TRUE;
}
}
}
if (wParam == BST_UNCHECKED) {
if (m_eEmphasis == BOLD || m_eEmphasis == BOLD_AND_UNDERLINE) {
if (m_bBold) {
if (m_bUnderline) {
SetFont(&m_fontUnderline);
} else {
SetFont(&m_fontNormal);
}
m_bBold = FALSE;
}
}
}
}
if (message == WM_MOUSEMOVE) {
if (!m_bOverControl) {
m_bOverControl = TRUE;
if (m_eEmphasis == UNDERLINE || m_eEmphasis == BOLD_AND_UNDERLINE) {
if (!m_bUnderline) {
if (m_bBold) {
SetFont(&m_fontBoldAndUnderline);
} else {
SetFont(&m_fontUnderline);
}
m_bUnderline = TRUE;
}
SetTimer(1, 100, NULL);
}
}
}
if (message == WM_TIMER) {
if (m_bOverControl) {
CRect rect;
GetWindowRect(▭);
CPoint point;
GetCursorPos(&point);
if (!rect.PtInRect(point)) {
if (m_bUnderline) {
if (m_bBold) {
SetFont(&m_fontBold);
} else {
SetFont(&m_fontNormal);
}
m_bUnderline = FALSE;
}
m_bOverControl = FALSE;
KillTimer(wParam);
}
}
}
演示应用程序允许尝试各种显示属性的组合。
要将CXEmphasisButton类集成到应用程序中,首先需要将以下文件添加到项目中:
接下来,在适当的项目文件中包含头文件XEmphasisButton.h(通常,这将是对话框类的头文件)。然后将按钮控件的声明替换为:
CXEmphasisButton m_MyButton;
现在可以开始使用CXEmphasisButton了。在对话框的OnInitDialog()函数中,插入一行:
m_MyButton.SetEmphasis(CXEmphasisButton::BOLD_AND_UNDERLINE);
(使用想要的任何显示属性)。