MFC + CxImage 实现自绘半透明按钮

环境:VS2008 + CxImage

btn.h

#pragma once


// CBtn
#include "ximage/ximage.h"

class CBtn : public CButton
{
	DECLARE_DYNAMIC(CBtn)
private:
	CxImage * m_pImgNormal;
	CxImage * m_pImgOver;
	CxImage * m_pImgDown;
	CxImage * m_pImgFocus;
	CxImage * m_pImgDisable;

	BOOL m_bTracking;
	BOOL m_bMouseOver;
	BOOL m_bLBtnDown;
public:
	CBtn(UINT imgID_LbtnDown,UINT imgID_Over,UINT imgID_Normal,UINT imgID_Disabled=0,UINT imgID_Focus=0);
	virtual ~CBtn();

protected:
	DECLARE_MESSAGE_MAP()
public:
	virtual void DrawItem(LPDRAWITEMSTRUCT /*lpDrawItemStruct*/);
	afx_msg void OnDestroy();
	afx_msg BOOL OnEraseBkgnd(CDC* pDC);
	afx_msg void OnMouseMove(UINT nFlags, CPoint point);
	afx_msg void OnMouseLeave();
	afx_msg void OnMouseHover(UINT nFlags, CPoint point);
protected:
	virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
public:
	void PaintParent();
	virtual BOOL Create(LPCTSTR lpszCaption, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID);
	afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
	afx_msg void OnLButtonUp(UINT nFlags, CPoint point);
	afx_msg void OnBnDoubleclicked();
	afx_msg void OnKillFocus(CWnd* pNewWnd);
};

btn.cpp

// Btn.cpp : 实现文件
//

#include "stdafx.h"
#include "Btn.h"


// CBtn

IMPLEMENT_DYNAMIC(CBtn, CButton)

CBtn::CBtn(UINT imgID_LbtnDown,UINT imgID_Over,UINT imgID_Normal,UINT imgID_Disabled,UINT imgID_Focus):
	  m_pImgNormal(NULL)
	, m_pImgOver(NULL)
	, m_pImgDown(NULL)
	, m_pImgFocus(NULL)
	, m_pImgDisable(NULL)
	, m_bTracking(FALSE)
	, m_bMouseOver(FALSE)
	, m_bLBtnDown(FALSE)
{
	if(imgID_Normal > 0)
	{
		if(!m_pImgNormal)
			m_pImgNormal = new CxImage(CXIMAGE_FORMAT_PNG);
		m_pImgNormal ->LoadResource(FindResource(NULL,MAKEINTRESOURCE(imgID_Normal),L"PNG"),CXIMAGE_FORMAT_PNG);
	}
	if(imgID_Focus > 0)
	{
		if(!m_pImgFocus)
			m_pImgFocus = new CxImage(CXIMAGE_FORMAT_PNG);
		m_pImgFocus ->LoadResource(FindResource(NULL,MAKEINTRESOURCE(imgID_Focus),L"PNG"),CXIMAGE_FORMAT_PNG);
	}
	if( imgID_LbtnDown>0 )
	{
		if(!m_pImgDown)
			m_pImgDown = new CxImage(CXIMAGE_FORMAT_PNG);
		m_pImgDown ->LoadResource(FindResource(NULL,MAKEINTRESOURCE(imgID_LbtnDown),L"PNG"),CXIMAGE_FORMAT_PNG);
	}
	if( imgID_Disabled > 0 )
	{
		if(!m_pImgDisable)
			m_pImgDisable = new CxImage(CXIMAGE_FORMAT_PNG);
		m_pImgDisable ->LoadResource(FindResource(NULL,MAKEINTRESOURCE(imgID_Disabled),L"PNG"),CXIMAGE_FORMAT_PNG);
	}
	if( imgID_Over > 0)
	{
		if(!m_pImgOver)
			m_pImgOver = new CxImage(CXIMAGE_FORMAT_PNG);
		m_pImgOver ->LoadResource(FindResource(NULL,MAKEINTRESOURCE(imgID_Over),L"PNG"),CXIMAGE_FORMAT_PNG);
	}
}

CBtn::~CBtn()
{
}

BEGIN_MESSAGE_MAP(CBtn, CWnd)
	ON_WM_DESTROY()
	ON_WM_ERASEBKGND()
	ON_WM_MOUSEMOVE()
	ON_WM_MOUSELEAVE()
	ON_WM_MOUSEHOVER()
	ON_WM_LBUTTONDOWN()
	ON_WM_LBUTTONUP()
	ON_CONTROL_REFLECT(BN_DOUBLECLICKED, &CBtn::OnBnDoubleclicked)
	ON_WM_KILLFOCUS()
END_MESSAGE_MAP()


// CBtn 消息处理程序
void CBtn::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{
	CDC ButtonDC; 
	CRect rc;
    
    ButtonDC.Attach(lpDrawItemStruct->hDC); //得到用于绘制按钮的DC 
	rc=lpDrawItemStruct->rcItem; //获取按钮所占的矩形大小

	UINT state = lpDrawItemStruct->itemState; //获取按钮目前所处的状态,根据不同的状态绘制不同的按钮 

	if(state&ODS_DISABLED && m_pImgDisable) 
    { 
		m_pImgDisable ->Draw(ButtonDC.GetSafeHdc(),rc);
	}
	else
	{

		if( m_bLBtnDown && m_pImgDown)
		{
			m_pImgDown ->Draw(ButtonDC.GetSafeHdc(),rc);
		}
		else if(m_bMouseOver && m_pImgOver)
		{
			m_pImgOver ->Draw(ButtonDC.GetSafeHdc(),rc);
		}
		else if(state&ODS_FOCUS && m_pImgFocus) 
		{ 
			m_pImgFocus ->Draw(ButtonDC.GetSafeHdc(),rc);
		}
		else if(m_pImgNormal)
		{
			m_pImgNormal ->Draw(ButtonDC.GetSafeHdc(),rc);
		}
	}
}

void CBtn::OnDestroy()
{
	CButton::OnDestroy();

	// TODO: 在此处添加消息处理程序代码
	if(m_pImgNormal)
	{
		m_pImgNormal ->Destroy();
		delete m_pImgNormal;
		m_pImgNormal = NULL;
	}
	if(m_pImgOver)
	{
		m_pImgOver ->Destroy();
		delete m_pImgOver;
		m_pImgOver = NULL;
	}
	if(m_pImgDown)
	{
		m_pImgDown ->Destroy();
		delete m_pImgDown;
		m_pImgDown = NULL;
	}
	if(m_pImgFocus)
	{
		m_pImgFocus ->Destroy();
		delete m_pImgFocus;
		m_pImgFocus = NULL;
	}
	if(m_pImgDisable)
	{
		m_pImgDisable ->Destroy();
		delete m_pImgDisable;
		m_pImgDisable = NULL;
	}
}

BOOL CBtn::OnEraseBkgnd(CDC* pDC)
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值
	return TRUE;
	//return CButton::OnEraseBkgnd(pDC);
}

BOOL CBtn::PreCreateWindow(CREATESTRUCT& cs)
{
	// TODO: 在此添加专用代码和/或调用基类
	cs.style |= BS_OWNERDRAW;

	return CButton::PreCreateWindow(cs);
}

void CBtn::OnMouseMove(UINT nFlags, CPoint point)
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值
	m_bMouseOver = TRUE;
	if (!m_bTracking)
	{
		TRACKMOUSEEVENT   tme; 
		tme.cbSize		=   sizeof(TRACKMOUSEEVENT); 
		tme.dwFlags		=   TME_LEAVE|TME_HOVER; //
		tme.hwndTrack   =   GetSafeHwnd(); 
		tme.dwHoverTime	=   8; 
		_TrackMouseEvent(&tme);
		m_bTracking = TRUE;
	}
	CButton::OnMouseMove(nFlags, point);
	::SetCursor(AfxGetApp() ->LoadCursor(IDC_CURSOR_HAND));
}

void CBtn::OnMouseLeave()
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值
	m_bMouseOver	=   FALSE; 
	m_bTracking		=   FALSE;  
	m_bLBtnDown		=	FALSE;
	PaintParent();
	CButton::OnMouseLeave();
}

void CBtn::OnMouseHover(UINT nFlags, CPoint point)
{
	m_bMouseOver = TRUE;
	PaintParent();
	::SetCursor(AfxGetApp() ->LoadCursor(IDC_CURSOR_HAND));
}

void CBtn::PaintParent()
{
	CRect   rect; 
	GetWindowRect(&rect); 
	GetParent()-> ScreenToClient(&rect); 
	GetParent()-> InvalidateRect(&rect);
}

BOOL CBtn::Create(LPCTSTR lpszCaption, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID)
{
	BOOL OK=CButton::Create(lpszCaption, dwStyle, rect, pParentWnd, nID);
	ModifyStyleEx(0, WS_EX_TRANSPARENT);// WS_EX_LAYERED||WS_EX_TRANSPARENT  
	return OK;
}

void CBtn::OnLButtonDown(UINT nFlags, CPoint point)
{
	m_bLBtnDown = TRUE;
	PaintParent();
	CButton::OnLButtonDown(nFlags, point);
	::SetCursor(AfxGetApp() ->LoadCursor(IDC_CURSOR_HAND));
}

void CBtn::OnLButtonUp(UINT nFlags, CPoint point)
{
	m_bLBtnDown = FALSE;
	PaintParent();
	CButton::OnLButtonUp(nFlags, point);
	::SetCursor(AfxGetApp() ->LoadCursor(IDC_CURSOR_HAND));
}

void CBtn::OnBnDoubleclicked()
{
	// TODO: 在此添加控件通知处理程序代码
	::SetCursor(AfxGetApp() ->LoadCursor(IDC_CURSOR_HAND));
}

void CBtn::OnKillFocus(CWnd* pNewWnd)
{
	CButton::OnKillFocus(pNewWnd);

	// TODO: 在此处添加消息处理程序代码
	PaintParent();
}

调用

///头文件中添加
...
#include "Btn.h"
...
        enum {emTestBtnId1=8099,emTestBtnId2,emTestBtnId3};
	CBtn m_btnTest1,m_btnTest2,m_btnTest3;//test

///在构造函数初始化列表中初始化变量(IDB_PNG_BTN_TEST_*为Png图片资源ID)   
    , m_btnTest1(IDB_PNG_BTN_TEST_DOWN,
            IDB_PNG_BTN_TEST_MOUSEOVER,
            IDB_PNG_BTN_TEST_NORMAL,
            IDB_PNG_BTN_TEST_DISABLE,
            IDB_PNG_BTN_TEST_FOCUS) 
    , m_btnTest2(IDB_PNG_BTN_TEST_DOWN,
            IDB_PNG_BTN_TEST_MOUSEOVER,
            IDB_PNG_BTN_TEST_NORMAL,
            IDB_PNG_BTN_TEST_DISABLE/*,IDB_PNG_BTN_TEST_FOCUS*/) 
    , m_btnTest3(IDB_PNG_BTN_TEST_DOWN,
            IDB_PNG_BTN_TEST_MOUSEOVER,
            IDB_PNG_BTN_TEST_NORMAL,
            IDB_PNG_BTN_TEST_DISABLE/*,IDB_PNG_BTN_TEST_FOCUS*/)

在OnInitDialog()函数中创建按钮
    //test 
    m_btnTest1.Create(_T("test"),WS_VISIBLE | WS_CHILD/* |WS_DISABLED*/,CRect(10,10,58,58),this,emTestBtnId1); 
    m_btnTest2.Create(_T("test"),WS_VISIBLE | WS_CHILD/* |WS_DISABLED*/,CRect(10,60,58,108),this,emTestBtnId2); 
    m_btnTest3.Create(_T("test"),WS_VISIBLE | WS_CHILD |WS_DISABLED,CRect(10,110,58,158),this,emTestBtnId2);


效果图



  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: 以下是MFC中将24位图转换成1位位图的代码实现: 1. 首先,需要打开24位图像文件,并将其加载到内存中。可以使用CImage类来实现这个过程: CImage img; img.Load(_T("24bit.bmp")); 2. 然后,需要创建一个新的1位位图,并将其大小设置为与原始图像相同。可以使用CBitmap和CDC类来实现这个过程: CBitmap bmp; bmp.CreateBitmap(img.GetWidth(), img.GetHeight(), 1, 1, NULL); CDC memDC; memDC.CreateCompatibleDC(NULL); memDC.SelectObject(&bmp); 3. 接下来,需要将原始图像的每个像素转换为黑白像素,并将其写入新的1位位图中: for (int y = 0; y < img.GetHeight(); y++) { for (int x = 0; x < img.GetWidth(); x++) { COLORREF pixel = img.GetPixel(x, y); int r = GetRValue(pixel); int g = GetGValue(pixel); int b = GetBValue(pixel); int gray = (r + g + b) / 3; if (gray < 128) { memDC.SetPixel(x, y, RGB(0, 0, 0)); } else { memDC.SetPixel(x, y, RGB(255, 255, 255)); } } } 4. 最后,需要将转换后的1位位图保存到文件中: CImageConverter converter; converter.SaveBitmapToFile(bmp, _T("1bit.bmp"), _T("BMP")); 完整的代码如下: CImage img; img.Load(_T("24bit.bmp")); CBitmap bmp; bmp.CreateBitmap(img.GetWidth(), img.GetHeight(), 1, 1, NULL); CDC memDC; memDC.CreateCompatibleDC(NULL); memDC.SelectObject(&bmp); for (int y = 0; y < img.GetHeight(); y++) { for (int x = 0; x < img.GetWidth(); x++) { COLORREF pixel = img.GetPixel(x, y); int r = GetRValue(pixel); int g = GetGValue(pixel); int b = GetBValue(pixel); int gray = (r + g + b) / 3; if (gray < 128) { memDC.SetPixel(x, y, RGB(0, 0, 0)); } else { memDC.SetPixel(x, y, RGB(255, 255, 255)); } } } CImageConverter converter; converter.SaveBitmapToFile(bmp, _T("1bit.bmp"), _T("BMP")); ### 回答2: MFC提供了一种简单的方法将24位图像转换为1位位图,可以通过使用CImage类和相关函数来实现。下面是一个示例代码: ```cpp // 加载24位图像 CImage img; img.Load(_T("24bit_image.bmp")); // 获取图像宽度和高度 int width = img.GetWidth(); int height = img.GetHeight(); // 创建1位位图 CImage img1bit; img1bit.Create(width, height, 1); HBITMAP hBitmap1bit = img1bit; CDC* pDC = CDC::FromHandle(img1bit.GetDC()); // 对每个像素进行转换 for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { // 获取像素的RGB值 RGBQUAD color; img.GetPixel(x, y, &color); // 将RGB值转换为灰度值 int gray = (color.rgbRed + color.rgbGreen + color.rgbBlue) / 3; // 如果灰度值大于128,则设置像素为白色;否则设置为黑色 if (gray > 128) { pDC->SetPixel(x, y, RGB(255, 255, 255)); // 白色 } else { pDC->SetPixel(x, y, RGB(0, 0, 0)); // 黑色 } } } // 保存1位位图到文件 img1bit.Save(_T("1bit_image.bmp")); img1bit.ReleaseDC(); ``` 以上代码首先使用CImage类加载24位图像。然后创建一个与原图像具有相同宽度和高度的1位位图。接下来对每个像素进行遍历,将其RGB值转换为灰度值,然后根据灰度值设置对应像素为黑色或白色。最后,保存1位位图到文件。 ### 回答3: MFC是一个用于开发Windows图形用户界面应用程序的框架。要将24位图转换为1位位图,可以使用MFC中的GDI+图形库来实现。以下是实现该功能的代码示例: 1. 首先,需要包含必要的MFC头文件和命名空间: ``` #include <afxwin.h> using namespace Gdiplus; ``` 2. 创建一个MFC对话框应用程序,并在对话框类的头文件中添加下面的声明: ``` class CMyDialog : public CDialog { protected: virtual void DoDataExchange(CDataExchange* pDX); DECLARE_MESSAGE_MAP() // 存储24位图和1位位图的变量 CImage m_img24bit; CImage m_img1bit; }; ``` 3. 在对话框类的实现文件中,添加下面的代码来实现图像转换: ``` void CMyDialog::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); DDX_Control(pDX, IDC_PICTURE, m_picture); // IDC_PICTURE是对话框上的图片框控件的ID } void CMyDialog::OnButtonConvert() { // 加载24位图 m_img24bit.Load(_T("24bit.bmp")); // 24bit.bmp是要转换的24位图文件路径 // 创建1位位图 m_img1bit.Create(24, 24, 1); // 创建一个24x24像素的1位位图 // 获取24位图的位图数据 BYTE* pBits24bit = (BYTE*)m_img24bit.GetBits(); // 获取1位位图的位图数据 BYTE* pBits1bit = (BYTE*)m_img1bit.GetBits(); // 将24位图转换为1位位图 for(int i = 0; i < 24 * 24; i++) { // 分别获取24位图中每个像素点的RGB值 BYTE r = pBits24bit[3 * i + 2]; BYTE g = pBits24bit[3 * i + 1]; BYTE b = pBits24bit[3 * i]; // 计算1位位图中每个像素点的索引 int index = (r + g + b) > 383 ? 1 : 0; // 设置1位位图中每个像素点的值 pBits1bit[i] = index; } // 显示1位位图 m_picture.SetBitmap((HBITMAP)m_img1bit.GetSafeHandle(), CxImage::CBORROW); // 保存1位位图到文件 m_img1bit.Save(_T("1bit.bmp")); // 1bit.bmp是转换后的1位位图文件路径 } ``` 以上代码示例假设24位图和1位位图的尺寸都是24x24像素。在实际使用时,请根据具体需求进行调整。同时,请注意替换代码中的文件路径和控件ID,以适应实际情况。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值