在Windows应用程序中,经常需要在标题栏添加自定义按钮以增强用户界面的交互性。然而,直接在标题栏上添加按钮并不像在客户区添加按钮那样简单。尽管有一些应用程序已经实现了标题栏上的自定义按钮,但很难找到可重用的代码实现。因此,决定创建一个名为CCaptionButton
的类来实现这个功能。
由于需要在标题栏上绘制按钮,因此需要准备一些图片来模拟按钮的外观。CCaptionButton
类需要一个图片列表,其中包含以下状态的图片:
以下是创建按钮图片列表的示例图片:
// 示例代码
HIMAGELIST himl = ImageList_LoadImage(_Module.GetResourceInstance(), MAKEINTRESOURCE(IDB_BUTTONS), 16, 4, RGB(255, 0, 255));
需要支持一个窗口上添加多个标题栏按钮。每个按钮内部使用以下数据结构存储:
struct _button
{
UINT uID; // 命令ID
int cx; // 宽度
int cy; // 高度
HIMAGELIST himl; // 图片列表
UINT uStatus; // 状态(图片索引)
char szHint[80]; // 提示文本
};
使用向量来内部存储按钮。要添加按钮,只需调用:
int AddButton(UINT uID, int cx, int cy, HIMAGELIST himl, LPCTSTR lpszHint=NULL);
其中uID
是按钮的命令ID。当按钮被点击时,会向窗口发送一个带有uID
参数的WM_COMMAND
消息。因此,处理标题栏按钮点击与处理普通按钮点击是一样的。cx
和cy
指定按钮的大小,这个大小必须与相应图片列表中的图片大小匹配。himl
包含绘制按钮所需的所有图片。它必须至少包含三个图片,按照前面描述的正确顺序,或者如果需要选中和禁用状态,则包含五个图片。lpszHint
是按钮的提示文本。
在哪里绘制这些按钮?自动定位听起来对于一个可重用的类是必须的。然而,发现在所有窗口样式中将按钮放置在正确位置是不可能的。窗口是否是工具窗口,标题栏相对较薄?窗口是否包含最小化按钮?窗口是否包含最大化按钮?窗口是否包含帮助按钮?……所有这些都会使自动定位变得混乱。最后,决定让派生类定位按钮。函数GetButtonPos
被设计为可以覆盖,以为每个按钮提供位置。
POINT GetButtonPos(int index);
CCaptionButton
类提供了GetButtonPos
的默认实现。但它假设目标窗口是一个工具窗口,并且没有现有的系统按钮。对于任何其他样式,必须实现自己的GetButtonPos
来正确定位按钮。通过提供自定义的GetButtonPos
函数,按钮定位变得更加强大和灵活。甚至可以像演示应用程序中那样垂直堆叠两个按钮。
CCaptionButton
类可以轻松添加到任何直接或间接派生自CWindowImpl
的ATL/WTL窗口类中。使用总结:
CCaptionButton
类作为基类。CHAIN_MSG_MAP
将消息链接到CCaptionButton
类。AddButton
向标题栏添加一个或多个按钮。GetButtonPos
函数以为添加的每个按钮提供位置。WM_COMMAND
通知。CheckButton
更改标题栏按钮的选中状态。EnableButton
更改标题栏按钮的启用状态。WM_COMMAND
。附带的示例应用程序演示了CCaptionButton
的使用。CAppBar
类也用于AppBar功能。要获取更多关于CAppBar
的详细信息,请查看这里。示例中使用了五个标题栏按钮。固定按钮控制AppBar窗口的自动隐藏属性;其他四个按钮将窗口停靠到屏幕的四个边缘;“底部停靠”按钮被禁用,以便可以看到禁用按钮的外观。