EosPro 之MFC 对 Button的绘制
自绘按钮
一、位图按钮的实现方法:首先,我们创建一个基于对话框的应用程序CmyDialogA、MFC的CBitmapButton类,这也是最简单的功能最强的位图按钮。
采取如下的步骤:1. 为按钮指定唯一的按钮标题(此例子为OK按钮,这里设置按钮标题为OK)并选中Ownerdraw属性,然后在项目中加一些位图资源,并用名字标示这些资源而不要用数字ID,其ID分别为”OKU”、”OKD”、”OKF”、”OKX”(一定要加双引号),分别对应于按钮的“松开(Up)”、“按下(Down)”、“获得输入焦点(focused)”和“禁止(Disable)”状态。2. 我们还要在对话框类中加入CBitmapButton m_aBmpBtn; 数据成员。3. 在初始化中为这个成员调用:…m_aBmpBtn. AutoLoad(IDOK,this);…点击编译按钮,成功后运行程序,哈哈,看看效果,我们的位图按钮已经建立了。/*如果以上方法不行请检查你的BITMAP 资源,APPSTUDIO中,"OKU"和 "OKD" 等的资源名称都是需要用引号引起来的, AutoLoad不成功,很可能就是由此产生的。 */改变CANCLE按钮的标题,可以设置其标题为ICON或者BITMAP :(这里演示bitmap的用法,Icon按钮读者可以按照下面的代码处理)
B、使用图标制作按钮1. 打开ICON按钮的属性页,在Style中选中Icon 。2. 在对话框类的头文件中定义成员变量(使用ClassWizard加入这个成员变量)CButton m_ IconBtn;//对应于图标按钮3. 创建相应的图标或者位图资源:图标资源:IDI_ICONBUTTON4.在初始化中加入如下代码:…//对应于图标按钮HICON hIcon=AfxGetApp()->LoadIcon(IDI_ ICONBUTTON);m_IconBtn.SetIcon(hIcon);…重新编译运行程序,奇妙的图像按钮呈现在眼前了。C、使用位图制作按钮1. 打开BITMAP按钮的属性页,在Style中选中Bitmap。2. 对话框类的头文件中定义成员变量(使用ClassWizard加入这个成员变量)CButton m_BmpBtn;3.创建位图资源:位图资源:IDB_BITMAPBUTTON4.在初始化中加入如下代码://对应于位图按钮…HBITMAP hBmp=::LoadBitmap(AfxGetInstanceHandle(),MAKEINTRESOURCE(IDB_ BITMAPBUTTON));m_BmpBtn.SetBitmap(hBmp);
二、
A、只加载一张位图的方法:
1. 装入bmp资源,id为IDB_BMP,按钮的bitmap属性设为true,icon属性为false。
2,
CButton *pBtn = (CButton *)GetDlgItem(IDB_BMP);CBitmap bitMap;HBITMAP hBit ;if(bitMap.LoadBitmapW(IDB_NORMAL_BTN)){hBit = (HBITMAP)bitMap.Detach();pBtn->SetBitmap(hBit);}
缺点:图片不会自动拉伸。
B、为按钮的不同状态加载不同的位图:(使用CBitmapButton类)这种方法还可以。1,按钮属性 Owner Draw选上,按钮ID: IDC_BUTTON1
为IDC_BUTTON1添加CButton变量m_button,2,然后手动将CButton m_button改为CBitmapButton m_button;3,在初始化里边m_button.LoadBitmaps(IDB_BITMAP1, IDB_BITMAP2);//IDB_BITMAP1:平时;IDB_BITMAP2:按下m_button.SubclassDlgItem(IDC_BUTTON1, this);m_button.SizeToContent();
或者用另一种方式,不必为IDC_BUTTON1添加关联的变量。直接声明CBitmapButton m_button;,在初始化里边调用
m_BitmapBtn.AutoLoad(IDC_BUTTON1_AREA,this);//把按钮和变量联系起来
m_BitmapBtn.LoadBitmaps(IDB_BITMAP1, IDB_BITMAP2);
m_button.SizeToContent();
缺点:1,无法显示文字,需重载DrawItem函数。
2,无法去掉图片的背景色,即只能显示矩形按钮。
// NOTE: CMyButton is a class derived from CButton. The CMyButton
// object was created as follows:
//CMyButton 类继承CButton
// CMyButton myButton;
// myButton.Create(_T("My button"),
// WS_CHILD|WS_VISIBLE|BS_PUSHBUTTON|BS_OWNERDRAW,
// CRect(10,10,100,30), pParentWnd, 1);
//
// This example implements the DrawItem method for a CButton-derived
// class that draws the button's text using the color red.
//例子中实现了DrawItem方法以特定RGB颜色画文字
void CMyButton::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{
UINT uStyle = DFCS_BUTTONPUSH;
// This code only works with buttons.
ASSERT(lpDrawItemStruct->CtlType == ODT_BUTTON);
// If drawing selected, add the pushed style to DrawFrameControl.
if (lpDrawItemStruct->itemState & ODS_SELECTED)
uStyle |= DFCS_PUSHED;
// Draw the button frame.
::DrawFrameControl(lpDrawItemStruct->hDC, &lpDrawItemStruct->rcItem,
DFC_BUTTON, uStyle);
// Get the button's text.
CString strText;
GetWindowText(strText);
// Draw the button text using the text color red.
COLORREF crOldColor = ::SetTextColor(lpDrawItemStruct->hDC, RGB(255,0,0));
::DrawText(lpDrawItemStruct->hDC, strText, strText.GetLength(),
&lpDrawItemStruct->rcItem, DT_SINGLELINE|DT_VCENTER|DT_CENTER);
::SetTextColor(lpDrawItemStruct->hDC, crOldColor);
}
//继承CBitmapButton的例子
void MyButton::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct){// TODO: Add your code to draw the specified item//从lpDrawItemStruct获取控件的相关信息CRect rect=lpDrawItemStruct-> rcItem;CDC *pDC=CDC::FromHandle(lpDrawItemStruct-> hDC);int nSaveDC=pDC-> SaveDC();UINT state = lpDrawItemStruct-> itemState;TCHAR strText[MAX_PATH + 1];::GetWindowText(m_hWnd, strText, MAX_PATH);CBitmapButton::DrawItem(lpDrawItemStruct);CRect rect1=rect;rect.SetRect(rect1.left,rect1.top,rect1.left+75,rect1.top+24);//显示按钮的文本pDC-> SetTextColor(TextColor);if (strText!=NULL){CFont* hFont = GetFont();CFont* hOldFont = pDC-> SelectObject(hFont);CSize szExtent = pDC-> GetTextExtent(strText, lstrlen(strText));CPoint pt( rect.CenterPoint().x - szExtent.cx / 2, rect.CenterPoint().y - szExtent.cy / 2);if (state & ODS_SELECTED)pt.Offset(1, 1);int nMode = pDC-> SetBkMode(TRANSPARENT);if (state & ODS_DISABLED)pDC-> DrawState(pt, szExtent, strText, DSS_DISABLED, TRUE, 0, (HBRUSH)NULL);elsepDC-> DrawState(pt, szExtent, strText, DSS_NORMAL, TRUE, 0, (HBRUSH)NULL);pDC-> SelectObject(hOldFont);pDC-> SetBkMode(nMode);}pDC-> RestoreDC(nSaveDC);}
C、继承CButton类,重写OnPaint函数,为Button的不同状态画位图(BitBlt,TransparentBlt,StretchBlt ,MaskBlt,PlgBlt )。
D、可以采用CButtonST控件,挺好用的,比MFC的那些封装好用。假设按钮ID为IDC_BUTTON11.添加成员变量CButtonST m_btn;2.添加位图资源,ID设为IDB_BITMAP13.在OnInitDialog函数中初始化按钮m_btn.SubclassDlgItem(IDC_BUTTON1,this);m_btn.SetBitmaps(IDB_BITMAP1,RGB(0,0,0));m_btn.OffsetColor(CButtonST::BTNST_COLOR_BK_IN, 30);注: 上面的SetBitmaps函数会将图片中颜色值为RGB(0,0,0)的点设为透明。
E、把button按钮属性设置为ower draw然后映射onDrawItem消息,在ondraw函数内自己绘制就可以了void CUi6Dlg::OnDrawItem(int nIDCtl, LPDRAWITEMSTRUCT lpDrawItemStruct){if(nIDCtl == IDC_HELLO_CFAN){//绘制按钮框架UINT uStyle = DFCS_BUTTONPUSH;//是否按下去了?if (lpDrawItemStruct->itemState & ODS_SELECTED)uStyle |= DFCS_PUSHED;CDC dc;dc.Attach(lpDrawItemStruct->hDC);dc.DrawFrameControl(&lpDrawItemStruct->rcItem, DFC_BUTTON, uStyle);//输出文字dc.SelectObject(&m_Font);dc.SetTextColor(RGB(0, 0, 255));dc.SetBkMode(TRANSPARENT);CString sText;m_HelloCFan.GetWindowText(sText);dc.TextOut(lpDrawItemStruct->rcItem.left + 20, lpDrawItemStruct->rcItem.top + 20, sText);//是否得到焦点if(lpDrawItemStruct->itemState & ODS_FOCUS){//画虚框CRect rtFocus = lpDrawItemStruct->rcItem;rtFocus.DeflateRect(3, 3);dc.DrawFocusRect(&rtFocus);}return;}CDialog::OnDrawItem(nIDCtl, lpDrawItemStruct);}