C++ CBUTTON类重载以实现按钮贴图

首先写这篇文章的时候要感谢 CRongQ 以及 csdndenglu 两位博主
尤其是后者,本文实现的代码类基本是源自于

这篇博文,改进而来
https://blog.csdn.net/csdndenglu/article/details/80499556?spm=1001.2014.3001.5502

增添的是按照不同IDC对应的控件如何添加不同的点击前后的值
以及利用指针绕开 CDC CBITMAP等 CObject类无法直接复制而显得代码臃肿的问题 具体修改结合代码来说。

运行环境 VS2010

首先 :
1、建立基于对话框的MFC程序QR code,对话框上添加三个按钮,
对应按钮的ID为IDC_CREAT,IDC_PRINT,IDC_CANCEL。
到resource.h文件中查看这三个控件对应的define值
我这里是1000,1001,1004为例。

2、项目名上右击->添加->类,添加MFC类(选MFC类非C++类),派生于CButton 的名为CMyButton的类。

3、分别给IDC_CREAT,IDC_PRINT,IDC_CANCEL添加CMyButton类型的变量m_creat,m_print,m_cancel。
(右键对话框上的控件选择添加成员变量,成员类的类名手动输入你创建的类 我的是CMyButton)
顺便把这几个控件的属性里的 onwer draw 改成 true。

4、添加六个.bmp位图,ID分别为IDB_BITMAP1,IDB_BITMAP2,IDB_BITMAP3,IDB_BITMAP4,IDB_BITMAP5,IDB_BITMAP6。

5、项目,类向导中查看我们创建的CMyButton这个类,
选择虚函数成员里的drawitem 重载该函数并进行修改即可
仿照下面的CMyButton.h,CMyButton.cpp修改你添加的类代码即可。

CMyButton.h
#pragma once

//添加的一个MFC类  基于CButton类  创建的MFC类
// CMyButton

class CMyButton : public CButton
{
	DECLARE_DYNAMIC(CMyButton)

public:
	CMyButton();
	virtual ~CMyButton();

protected:
	DECLARE_MESSAGE_MAP()
	 
public:
	//向控件填入图片 点击之前点击之后 
	//对应的UINT均为resource.h对应的图片IDB IDC值    
	//第二个参数表示当前按钮状态 选中或者未选中
	//bmp_before和bmp_after对应resource.h里面的位图 
	//为选中前后的图片  带*的指针传递避免复制CObject报错
	void idc_load_bmp(UINT idc_control,
	                  UINT now,
	                  UINT bmp_before,
	                  UINT bmp_after,
		              CDC* ButtonDC,    
		              CBitmap* bitmapTrans,
		              CDC* mem,
		              CRect rc);   

  //CMyButton类中重载 DRAWItem函数
	virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct);   
};
// MyButton.cpp : 实现文件
#include "stdafx.h"
#include "QR code.h"
#include "MyButton.h"
// CMyButton
IMPLEMENT_DYNAMIC(CMyButton, CButton)
CMyButton::CMyButton()
{
}
CMyButton::~CMyButton()
{
}
BEGIN_MESSAGE_MAP(CMyButton, CButton)
END_MESSAGE_MAP()
// CMyButton 消息处理程序
//重载函数DrawItem的具体内容
void CMyButton::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{
	CDC* ButtonDC=new CDC ;            //指针引用
	CDC* mem=new CDC ;                 //指针引用    
	CBitmap* bitmapTrans=new CBitmap;  //指针引用
	CRect rc;          //得到用于绘制按钮的DC
	//获取lpDrawItemStruct内所需要的值
	ButtonDC->Attach(lpDrawItemStruct->hDC);   
	mem->CreateCompatibleDC(ButtonDC);    
	//获取按钮自身大小用于修改bmp位图大小       
	rc=lpDrawItemStruct->rcItem;    
	//获取按钮的状态 这里不选择focus而选择select用于修改贴图                    
	UINT state = lpDrawItemStruct->itemState;  
	//获取控件对应的 IDC 资源列表的值 以IDC_CREAT为例应为1000           
	UINT ID = lpDrawItemStruct->CtlID;                    

	switch (ID)             
	{
	case IDC_CREAT:   //1000 为IDC_CREAT的值 下同 
	   //类中自己写的一个成员函数 定义在下面
		idc_load_bmp(ID,state,IDB_BITMAP1,IDB_BITMAP2,
			         ButtonDC,bitmapTrans,mem,rc);
		break;
	case IDC_PRINT:   // IDC_PRINT 的值
		idc_load_bmp(ID,state,IDB_BITMAP3,IDB_BITMAP4,
			ButtonDC,bitmapTrans,mem,rc);
		break;
	case IDC_CANCEL:  // IDC_CANCEL 的值
		idc_load_bmp(ID,state,IDB_BITMAP5,IDB_BITMAP6,
			ButtonDC,bitmapTrans,mem,rc);
		break;
	default: 
		break;
	}
	
}

//类中自己定义的一个函数成员 参数含义参考头文件函数定义处
void CMyButton::idc_load_bmp(UINT idc_control,
                             UINT now,
                             UINT bmp_before,
                             UINT bmp_after,
	                         CDC* ButtonDC,
	                         CBitmap* bitmapTrans,
	                         CDC* mem,
	                         CRect rc)           
{
                 //成员函数开始
	BITMAP bmp;                //预备加载位图
	 //选中按钮 没有选中该按钮时重置该按钮 
	 //实现效果比ODS_FOCUS要好
	if (now&ODS_SELECTED)     //如果点击中按钮
	{
		bitmapTrans->LoadBitmap(bmp_after);   //加载点中后图片
		bitmapTrans->GetBitmap(&bmp);
		//向按钮位置传输位图
		CBitmap *old = mem->SelectObject(bitmapTrans);  
		//使用StretchBlt使得位图按按钮大小变换 照抄就行了
		ButtonDC->StretchBlt(rc.left,rc.top,rc.right,rc.bottom,
		                      mem,0,0,
		                      bmp.bmWidth,
		                      bmp.bmHeight,
		                      SRCCOPY);
		mem->SelectObject(old);        //载入该位图
		bitmapTrans->DeleteObject();   //释放
	}
	else   //参照上面的注释
	{
		bitmapTrans->LoadBitmap(bmp_before);
		CBitmap *old2 = mem->SelectObject(bitmapTrans);
		bitmapTrans->GetBitmap(&bmp);
		CBitmap *old = mem->SelectObject(bitmapTrans);
		ButtonDC->StretchBlt(rc.left,rc.top,rc.right,rc.bottom,
		                      mem,0,0,
		                      bmp.bmWidth,
		                      bmp.bmHeight,
		                      SRCCOPY);
		mem->SelectObject(old2);
		bitmapTrans->DeleteObject();
	}
}

大功告成,收工。再次感谢二位博主的文章学习,让我获益匪浅。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值