在MFC应用程序开发中,按钮控件是用户界面中不可或缺的一部分。虽然MFC提供了标准的按钮控件,但有时需要更灵活、更具有个性化的按钮。本文介绍的FooButton类,是一个轻量级的自定义按钮类,它提供了多种按钮样式和功能,可以满足开发者的多样化需求。
FooButton类提供了多种按钮样式,包括标准按钮、带下拉指示器的按钮、多按钮(类似于IE浏览器的“后退”和“前进”按钮)、复选按钮、超链接、静态文本控件、复选框和单选按钮。此外,它还支持以下特性:
要使用FooButton,首先需要在对话框中将一个标准按钮控件(例如IDC_FOO_BUTTON)与FooButton对象的实例关联起来。
// MyDialog.h
#include "FooButton.h"
...
FooButton m_fooButton;
// MyDialog.cpp
void CMyDialog::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
DDX_Control(pDX, IDC_FOO_BUTTON, m_fooButton);
}
然后在对话框的OnInitDialog()方法中初始化实例,以满足需求。例如,可以将按钮设置为显示位图和下拉指示器。
// 初始化FooButton
m_fooButton.setBitmapId(IDB_FOO_BUTTON);
m_fooButton.setType(FooButton::Type::pushButtonDropDown);
FooButton类提供了多种方法,用于获取和设置按钮的属性。以下是一些常用的方法:
可以在运行时自由更改按钮的任何属性。以下代码片段将按钮转换为复选按钮并选中它。
// 将其转换为复选按钮并选中
m_fooButton.setType(FooButton::Type::checkButton);
m_fooButton.check(true);
ASSERT(m_fooButton.isChecked());
通过调用setGradient()方法,可以将按钮设置为显示渐变阴影背景。如果按钮不是标准按钮或复选按钮,则此方法无效。
// 使用渐变阴影背景
m_fooButton.setGradient(true);
可以通过将复选按钮添加到按钮组中,使它们像单选按钮一样相互排斥。按钮组只是一个命名的按钮集合。FooButton自动处理组的创建、成员资格和清理。
// 使"大小"复选按钮互斥
m_btnSmall.addToGroup(_T("foo"));
m_btnMedium.addToGroup(_T("foo"));
m_btnLarge.addToGroup(_T("foo"));
m_btnXLarge.addToGroup(_T("foo"));
要响应按钮点击并在按钮下方显示弹出菜单,请调用displayPopupMenu()方法。可以为任何类型的FooButton调用此方法。
void CMyDialog::OnFooButton()
{
CMenu menu;
menu.LoadMenu(IDR_POPUP_MENU);
CMenu* pPopupMenu = menu.GetSubMenu(0);
int nResult = m_fooButton.displayPopupMenu(pPopupMenu);
if (0 != nResult)
PostMessage(WM_COMMAND, nResult);
}
多按钮的行为类似于两个按钮合二为一,类似于IE浏览器的“后退”和“前进”按钮。当用户点击按钮的下拉区域时,FooButton将其“多点击”属性设置为true。可以通过调用isMultiClicked()查询此属性。无论用户点击按钮的主区域还是下拉区域,都会向父窗口发送标准通知。要清除按钮的多点击属性,请调用clearMultiClick()。
void CMyDialog::OnFooButton()
{
if (m_fooButton.isMultiClicked()) {
// 如果点击了下拉区域,则显示菜单
CMenu menu;
menu.LoadMenu(IDR_POPUP_MENU);
CMenu* pPopupMenu = menu.GetSubMenu(0);
int nResult = m_fooButton.displayPopupMenu(pPopupMenu);
if (0 != nResult)
PostMessage(WM_COMMAND, nResult);
// 记得清除按钮的多点击属性
m_fooButton.clearMultiClick();
} else {
// 否则执行默认操作
PostMessage(WM_COMMAND, IDC_DEFAULT_ACTION);
}
}
可以通过使用FooButton::Type::checkBox和FooButton::Type::radio类型,使FooButton看起来像标准的复选框或单选按钮。当然,这在想同时显示位图或添加菜单支持到按钮时才真正有用。
// 作为复选框和单选按钮出现
m_fooButton1.setType(FooButton::Type::checkBox);
m_fooButton2.setType(FooButton::Type::radio);
超链接按钮只是一个普通的按钮,它将自己渲染为超链接。可以在按钮的处理程序中导航到URL或执行任何其他操作。
// 作为超链接出现
m_fooButton.setType(FooButton::Type::hyperlink);
可以随时通过调用setTextColor()方法来更改按钮文本的颜色。超链接按钮的文本总是以C_HyperlinkColor渲染,而禁用按钮的文本总是以标准蚀刻格式渲染。
// 以红色绘制标题
m_fooButton.setTextColor(RGB(192, 0, 0));
默认情况下,FooButton不显示焦点矩形。通过调用setFocusStyle()方法并传入FooButton::Focus::normalFocus,可以启用按钮显示焦点矩形。
// 允许显示焦点矩形
m_fooButton.setFocusStyle(FooButton::Focus::normalFocus);
要启用默认FooButton显示其标准暗边框,请调用setFocusStyle()方法并传入FooButton::Focus::defaultFocus。
// 允许显示焦点矩形和默认指示器
m_fooButton.setFocusStyle(FooButton::Focus::defaultFocus);
使用标准的MFCEnableWindow() API来启用和禁用按钮。FooButton使用其原始位图来渲染禁用版本。
// 启用按钮
m_fooButton.EnableWindow(TRUE);
// 禁用按钮
m_fooButton.EnableWindow(FALSE);