一.前言
以前对位图自绘按钮很迷茫,一直想对位图自绘按钮有个了解,经过一段时间的搜集和开发,自己重写了一个按钮位图类COwnerdrawBitmapButton。COwnerdrawBitmapButton是一个从CWnd类派生来的MFC控件。此按钮包含了两部分:一个背景色和一个前景色。如果你的操作系统是WinXP和XP,这个可用。背景是从当前资源文件加载位图,否则函数DrawFrameControl用来绘制按钮的背景。前景是用户定义一个单色位图(字形)在按钮背景色上面透明的绘制。
支持的功能:
● 标准或XP主题
● 12个预定义的背景样式
● 用户定义的前景色(单色位图)
● Buttons支持的状态:"NORMAL","HOT","PRESSED" 和 "DISABLED"
● 可以在标题栏区域创建按钮
● Dialog,SDI,MDI支持标题按钮
● 无闪烁绘图
● 内置的工具提示
二.COwnerdrawBitmapButton的使用
若你想在你的工程中使用COwnerdrawBitmapButton类,请看下面几个步骤:
1. 添加ThemeUtil.h, ThemeUtil.cpp, OwnerdrawBitmapButton.h, OwnerdrawBitmapButton.cpp, Tmschema.h and Schemadef.h到你的工程中。
2. 在你适当的头文件中包含OwnerdrawBitmapButton.h – 通常情况下,都是在对话框类中使用COwnerdrawBitmapButton。
1.
//OwnerdrawBitmapButtonDemoDlg.h : header file
2.
#include "OwnerdrawBitmapButton.h"
3.在你的dialog头文件中,定义一个COwnerdrawBitmapButton类型的变量m_ctrlCaptionFrame。
1.
// OwnerdrawBitmapButtonDemoDlg.h : header file
2.
class
COwnerdrawBitmapButtonDemoDlg : CDialog
3.
{
4.
......
5.
private
:
6.
COwnerdrawBitmapButton m_ctrlCaptionFrame;
7.
};
4.创建标题框
在你对话框的OnInitDialog函数中,添加如下代码:
1.
//OwnerBitmapButtonDemoDlg.cpp : definition file
2.
m_ctrlCaptionFrame.CreateCaptionFrame(
this
,IDR_MAINFRAME);
5.创建完主题框后,添加你需要的按钮
添加标题按钮的代码如下,在对话框中的OnInitDialog函数中调用AddCaptionButton:
01.
// OwnerdrawBitmapButtonDemoDlg.cpp : definition file
02.
m_ctrlCaptionFrame.AddCaptionButton(CRect(0,0,0,0),1,
03.
CBNBKGNDSTYLE_CLOSE, FALSE);
04.
m_ctrlCaptionFrame.AddCaptionButton(CRect(0,0,150,0),2,
05.
CBNBKGNDSTYLE_CAPTION, TRUE);
06.
COwnerdrawBitmapButton* pBn1 = m_ctrlCaptionFrame.GetCaptionButtonPtr(1);
07.
if
(pBn1)
08.
{
09.
CBitmap bmpGlyph1;
10.
bmpGlyph1.LoadBitmap(IDB_GLYPH1);
11.
pBn1->SetGlyphBitmap(bmpGlyph1);
12.
pBn1->SetTooltipText(_T("Double click to close the window,
13.
Right click to display the popup menu"));
14.
}
15.
COwnerdrawBitmapButton* pBn2 = m_ctrlCaptionFrame.GetCaptionButtonPtr(2);
16.
if
(pBn2)
17.
{
18.
CBitmap bmpGlyph2;
19.
bmpGlyph2.LoadBitmap(IDB_GLYPH2);
20.
pBn2->SetGlyphBitmap(bmpGlyph2);
21.
pBn2->SetTooltipText(_T(
"Articles by Andrzej Markowski"
));
22.
}
6.在对话框类中,处理从标题按钮的消息WM_NOTIFY。当用户点击按钮时,按钮发送通知消息(NM_CLICK,NM_RCLICK,NM_DBLCLK,NM_RDBLCLK)给它的父窗口,如果你要做什么反应的话,处理这些消息。
01.
// OwnerdrawBitmapButtonDemoDlg.cpp : definition file
02.
BEGIN_MESSAGE_MAP(COwnerdrawBitmapButtonDemoDlg, CDialog)
03.
//{{AFX_MSG_MAP(COwnerdrawBitmapButtonDemoDlg)
04.
ON_NOTIFY(NM_DBLCLK, 1, OnBnDblClickedCaptionbn1)
05.
ON_NOTIFY(NM_RCLICK, 1, OnBnRClickedCaptionbn1)
06.
ON_NOTIFY(NM_CLICK, 2, OnBnClickedCaptionbn2)
07.
//}}AFX_MSG_MAP
08.
END_MESSAGE_MAP()
09.
....
10.
void
COwnerdrawBitmapButtonDemoDlg::OnBnDblClickedCaptionbn1
11.
(NMHDR * pNotifyStruct,
LRESULT
* result)
12.
{
13.
CPoint pt;
14.
::GetCursorPos(& pt);
15.
PostMessage(WM_SYSCOMMAND,SC_CLOSE,MAKEWORD(pt.x,pt.y));
16.
}
17.
....
7.千万不要忘了销毁主题框架,否则将会造成内存泄漏。
1.
//OwnerdrawBitmapButtonDemoDlg.cpp : definition file
2.
void
COwnerdrawBitmapButtonDemoDlg::OnDestroy()
3.
{
4.
m_ctrlCaptionFrame.DestroyCaptionFrame();
5.
CDialog::OnDestroy();
6.
}
三.COwnerdrawBitmapButton类的成员
● 构造和析构函数
● 属性
● 操作函数
● 通知消息
● 错误代码
1. 构造和析构函数
COwnerdrawBitmapButton |
构造一个COwnerdrawBitmapButton对象 |
Create |
创建一个位图按钮,并且把它关联到COwnerdrawBitmapButton对象的实例 |
CreateCaptionFrame |
创建一个主题框架 |
DestoryCaptionFrame |
销毁主题框架 |
2.属性
GetCaptionButtonPtr |
返回一个标题按钮的指针 |
SetTooltipText |
设置按钮的提示文本 |
GetBkStyle |
获取按钮控件的背景风格信息 |
SetBkStyle |
设置按钮的背景风格 |
GetGlyphBitmap |
获取之前用SetGlyphBitmap设置字形位图的句柄 |
SetGlyphBitmap |
设置按钮上面的字形位图 |
EnableWindow |
设置按钮可用或不可用 |
3.操作函数
AddCaptionButton:在标题区中插入一个新按钮
四.COwnerdrawBitmapButton类中的主要成员函数
1. COwnerdrawBitmapButton::COwnerdrawBitmapButton
1.
COwnerdrawBitmapButton();
说明:调用此函数去构造一个COwnerdrawBitmapButton对象。
2. COwnerdrawBitmapButton::Create
1.
BOOL
Create(
DWORD
dwStyle,
const
RECT& rect, CWnd* pParentWnd,
UINT
nID )
返回值:
若初始化对象成功则返回TRUE,否则返回FALSE。
参数:
● dwStyle – 指定按钮的样式
● rect – 指定按钮的大小和位置。它可以是CRect或者RECT类型
● pParentWnd – 指定按钮的父窗口
● nID – 指定按钮的ID
说明:
创建一个位图button,并且将它关联到一个COwnerdrawBitmapButton对象的一个实例。
3.COwnerdrawBitmapButton::CreateCaptionFrame
1.
int
CreateCaptionFrame( CWnd* pCaptionWnd,
int
nIDIcon );
返回值:
若成功返回CBNERRR_NOERROR,否则返回CBNERRR_ERRORCODE。
参数:
● PCaptionWnd – 指定主题区域的所属窗口
● nIDIcon – 指定标题图标的资源ID
说明:
创建一个标题框架。
4.COwnerdrawBitmapButton::DestroyCaptionFrame
1.
int
DestroyCaptionFrame();
返回值:
若成功返回CBNERRR_NOERROR,否则返回CBNERRR_NOERRORCODE。
说明:
销毁主题框架。
5.COwnerdrawBitmapButton::GetCaptionButtonPtr
1.
COwnerdrawBitmapButton* GetCaptionButtonPtr(
int
nButtonID )
const
;
返回值:
若成功则指向一个COwnerdrawBitmapButton的对象,否则返回NULL。
参数:
● nButtonID – 主题按钮的ID
说明:
调用此函数将返回一个指向主题按钮的指针。
6.COwnerdrawBitmapButton::SetTooltipText
1.
int
SetTooltipText( CString sText );
返回值:
若成功返回CBNERRR_NOERROR,否则返回CBNERRR_NOERRORCODE。
参数:
● sText – 指向一个包含有新提示文本的字符串对象。
说明:
改变button的提示文本
7.COwnerdrawBitmapButton::GetBkStyle
1.
int
GetBkStyle();
返回值:
为COwnerdrawBitmapButton对象返回一个按钮背景样式。
说明:
此函数是获取按钮控件背景样式的信息。
8.COwnerdrawBitmapButton::SetBkStyle
1.
int
SetBkStyle(
int
nBkStyle );
返回值:
若成功返回CBNERRR_NOERROR,否则返回CBNERRR_NOERRORCODE。
参数:
nBkStyle – 指定按钮的背景样式。
支持的背景样式有:
● CBNBKGNDSTYLE_CAPTION – frame buttons
● CBNBKGNDSTYLE_CLOSE
● CBNBKGNDSTYLE_MDI
● CBNBKGNDSTYLE_COMBO – combobox dropdown button
● CBNBKGNDSTYLE_SPINUP – spin buttons
● CBNBKGNDSTYLE_SPINDN
● CBNBKGNDSTYLE_SPINUPHOR
● CBNBKGNDSTYLE_SPINDNHOR
● CBNBKGNDSTYLE_SCROLLUP – scrollbar buttons
● CBNBKGNDSTYLE_SCROLLDOWN
● CBNBKGNDSTYLE_SCROLLLEFT
● CBNBKGNDSTYLE_SCROLLRIGHT
说明:
改变按钮的背景样式
9.COwnerdrawBitmapButton::GetGlyphBitmap
1.
HBITMAP
GetGlyphBitmap();
返回值:
一个指向bitmap的句柄,假若之前未指定,则返回NULL
说明:
此函数将获取一个和button相关联的字形位图句柄
10.COwnerdrawBitmapButton::SetGlyphBitmap
1.
int
SetGlyphBitmap(
HBITMAP
hBmpGlyph );
返回值:
若成功返回CBNERRR_NOERROR,否则返回CBNERRR_NOERRORCODE。
参数:
● hBmpGlyph – 位图句柄
说明:
此函数将一个新字形位图关联到按钮。
11.COwnerdrawBitmapButton::EnableWindow
1.
int
EnableWindow(
BOOL
bEnable = TRUE);
返回值:
若成功返回CBNERRR_NOERROR,否则返回CBNERRR_NOERRORCODE。
参数:
● bEnable– 指定给定窗口是否为可用。假如这个参数值为TRUE,则这个窗口是可用的。假如这个值为FALSE,则这个窗口是不可用的。
说明:
调用这个函数使窗口可用或不可用
12.COwnerdrawBitmapButton::AddCaptionButton
1.
int
AddCaptionButton(LPCRECT lpRect,
UINT
nID,
int
nBkStyle,
BOOL
fUserDefWidth);
返回值:
若成功返回CBNERRR_NOERROR,否则返回CBNERRR_NOERRORCODE。
参数:
● lpRect – 若fUserDefWidth为true,则指定button的宽度,否则忽略。
● nID – 指定button的id
● nBkStyle – 指定button的背景样式
● fUserDefWidth – 若为TRUE,则用户定义button的宽度
说明:
此函数的功能是在一个已存在的标题去插入一个新的按钮
五.通知消息
按钮控件支持以下通知代码:
● NM_CLICK – 用户点击了控件按钮的鼠标左键
● NM_RCLICK – 用户点击了控件按钮的鼠标右键
● NM_DBLCLK – 用户双击了控件按钮的鼠标左键
● NM_RDBLCLK – 用户双击了控件按钮的鼠标右键
六.错误代码
在控件按钮函数中,可能会返回下面的错误代码:
● CBNERRR_NOERROR – 操作成功
● CBNERR_OUTOFMEMORY – 可用内存不足,导致函数调用失败
● CBNERR_INCORRECTPARAMETER – 指定了错误的参数导函数调用失败
● CBNERR_INCORRECTBUTTONSTYLE – 指定错误按钮风格导致函数调用失败
● CBNERR_INCORRECTFRAMESTYLE – 未指定WS_CAPTION样式,导致函数调用失败
● CBNERR_INCORRECTFUNCCALL – 错误的函数调用(例如:ob.SetTooltipText(…),而这里ob是一个主题框架对象的一个实例)
● CBNERR_CREATEBUTTONFAILED – 创建按钮控件失败,导致函数调用失败
● CBNERR_CREATETOOLTIPCTRLFAILED – 创建提示控件失败,导致函数调用失败
● CBNERR_COPYIMAGEFAILED – 复制字形图片失败,导致函数调用失败
● CBNERR_SETWINDOWLONGFAILED – 调用SetWindowLong函数失败
● CBNERR_FRAMEALREADYCREATED – 标题框架已经存在,导致调用函数失败
● CBNERR_FRAMENOTCREATED – 标题框架未创建,导致函数调用失败