自定义按钮的实现与应用

在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.cpp
  • XEmphasisButton.h

接下来,在适当的项目文件中包含头文件XEmphasisButton.h(通常,这将是对话框类的头文件)。然后将按钮控件的声明替换为:

CXEmphasisButton m_MyButton;
        

现在可以开始使用CXEmphasisButton了。在对话框的OnInitDialog()函数中,插入一行:

m_MyButton.SetEmphasis(CXEmphasisButton::BOLD_AND_UNDERLINE);
        

(使用想要的任何显示属性)。

沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485