MFC的PNG贴图按钮类(详细注释)

(转载请注明出处)

作者:梦镜谷雨


萌新第二次写帖子,请多多包涵。末尾附上相应代码(PS公司繁体系统所以部分注释繁体请别介意)。

因自带控件不美观,于是网上参考学习了些代码做了个按钮类。可以载入通过资源的ID加载也可以通过外部动态加载PNG图片,可以选择半透明贴膜效果。

参考代码:https://blog.csdn.net/qq_16123279/article/details/82858238

参考代码:https://blog.csdn.net/zhongbin104/article/details/8730935


一.思路

Step1.重载DrawItem函数

Step2.保存父窗口位置被遮挡的背景

Step3.保存需要的PNG贴图和其他设置

Step4.画上父窗口位置被遮挡的背景后再按设置画上需要的其他元素

二.使用例子演示

Step1.创建控件

Step2.导入资源(Add Resoure)(可以不用导入资源,类里面也有动态加载PNG图片的接口)

原来效果

创建对象后:

  protected:
    CPngButton m_BTN_Menu;
    CPngButton m_BTN_Button1;
    CPngButton m_BTN_Button3;

初始化里给Menu按钮添加白色半透明贴膜和设置文字:

  #define ShowColor RGB(255,255,255)
  m_BTN_Menu.SubclassDlgItem(IDC_BUTTON_Menu,this);
  m_BTN_Menu.SetTitle(_T("菜单1"));//設置按鈕顯示文字
  m_BTN_Menu.SetColor(ShowColor,,);//設置按鈕顯示半透明貼膜
  m_BTN_Menu.SetSize(,);//設置按鈕大小

给最顶端按钮添加贴膜和设置文字后的效果:

1.正常显示:

2.鼠标悬浮在Menu按钮上

3.按下Menu按钮

初始化里给Button1按钮添加贴图和白色半透明贴膜

  m_BTN_Button1.SubclassDlgItem(IDC_BUTTON1,this);
  m_BTN_Button1.SetImagePng(IDB_PNG_BUTTON1);
  m_BTN_Button1.SetColor(RGB(,,),,);//設置按鈕顯示半透明貼膜

给左边按钮添加一张贴图和设置贴膜后的效果:

1.正常显示

2.鼠标悬浮在Button1按钮上

3.按下Button1按钮

初始化里给Button3按钮添加几种不同情况下贴图

m_BTN_Button3.SubclassDlgItem(IDC_BUTTON3,this);
m_BTN_Button3.SetImagePng(IDB_PNG_BUTTON1,IDB_PNG1,IDB_PNG2);

给右边按钮贴上几种不同状态的贴膜效果:

1.正常显示

2.鼠标悬浮在Button3按钮上

3.按下Button3按钮

三.相关代码

.h代码

#pragma once
#include "afxwin.h"

// CPngButton

class CPngButton : public CButton
{
  //功能:加載透明PNG設置半透明的按鈕類
  //注:如出現貼膜顏色為黑色情況請檢查是否有SetColor因為m_BaseColor初始化為RGB(0,0,0)
public:
//-------------------------------------------------------------------
//函數名SetColor
//功能:設置觸摸按鍵的半透明顏色
//參數:COLORREF color - 按鈕觸碰后的背景色
// UINT OnTransparent = 0x0F - 鼠標懸浮時膜的透明度
// UINT DownTransparent = 0x3F - 按鈕按下時膜的透明度
//返回值:判斷輸入值是否合理
//注:貼膜專用,OnTransparent和DownTransparent正常範圍0 - FF,值越小越透明
//-------------------------------------------------------------------
  BOOL SetTransparentColor(COLORREF color,UINT OnTransparent = 0x0F,UINT DownTransparent = 0x3F);
  //設置字體顏色
  void SetFontColor(COLORREF color);
//-------------------------------------------------------------------
//函數名:SetTitle
//功能:設置按鍵的標題
//參數:CString csTitle - 按鍵顯示的圖片信息
//返回值:判斷是否設置成功
//-------------------------------------------------------------------
  BOOL SetTitle(const CString &csTitle);
//-------------------------------------------------------------------
//函數名SetImagePng
//功能:設置插入PNG背景資源
//參數:UINT nIDNormal - 一般情況背景圖片資源的ID
// :UINT nIDOn - 鼠標懸浮情況的圖片資源的ID
// :UINT nIDDown - 按鈕按下情況的圖片資源的ID
// :UINT nIDDisable =0 - 按鈕失能情況的圖片資源的ID
//返回值:無
//注:SetImagePng(UINT nIDNormal,UINT nIDDisable =0);自動設置為貼膜模式
// SetImagePng(UINT nIDNormal,UINT nIDOn,UINT nIDDown,UINT nIDDisable =0);自動設置為貼圖模式
//-------------------------------------------------------------------
  void SetImagePng(UINT nIDNormal,UINT nIDDisable =0);
  void SetImagePng(const CString& PathNormal,const CString& PathDisable = _T(""));
  void SetImagePng(UINT nIDNormal,UINT nIDOn,UINT nIDDown,UINT nIDDisable =0);
  void SetImagePng(const CString& PathNormal,const CString& PathOn,const CString& PathDown,const CString& PathDisable = _T(""));
//-------------------------------------------------------------------
//函數名SaveBG
//功能:更新控件擋住是背景,改變父窗口背景后需調用一次
//參數:無
//返回值:無
//-------------------------------------------------------------------
  void SaveBG(void);
//-------------------------------------------------------------------
//函數名SizeToContent
//功能:使按鈕大小和PNG資源大小一致
//參數:無
//返回值:無
//-------------------------------------------------------------------
  void SizeToContent(void);
//-------------------------------------------------------------------
//函數名SetSize
//功能:自定義設置控件大小
//參數:int iWidth - 設置控件寬度
// :int iHeight - 設置控件高度
//返回值:無
//-------------------------------------------------------------------
  void SetSize(int iWidth,int iHeight);
//-------------------------------------------------------------------
//函數名SetShowState
//功能:設置按鈕風格
//參數:BOOL NeedColorSet - 設置是否顯示貼膜
// :BOOL NeedTextSet - 設置是否打印文字
// :BOOL NeedImageSet - 設置是否打印PNG圖片
//返回值:無
//-------------------------------------------------------------------
  BOOL SetShowState(BOOL NeedColorSet, BOOL NeedTextSet,BOOL NeedImageSet);
//-------------------------------------------------------------------
//函數名SetContinueShow
//功能:設置按鈕是否需要一直顯示為按下狀態
//參數:BOOL ContinueShow - 是否顯示為按下狀態
//返回值:無
//-------------------------------------------------------------------
  void SetContinueShow(BOOL ContinueShow);
//********************************************************************
  DECLARE_DYNAMIC(CPngButton)
protected:
  enum ButtonState
  {
  Disable = 0,Normal,On,Down
  };

  enum ButtonMode
  {
  MaskMode = 0,PictureMode
  };
public:
  CPngButton();
  virtual ~CPngButton();
protected:
  void LoadImage(CImage &image,UINT nID);
  BOOL LoadImage(CImage &image,const CString& Path);
  CImage m_image[4];
  void Draw(UINT nID,CDC* pDC,CRect rect);//畫PNG貼圖
protected:
  DECLARE_MESSAGE_MAP()
  void CancelHover(void);//修改鼠標不在懸浮于控件上的標誌
protected:
  CDC m_MemDCBG;//保持的父窗口擋住的背景
  COLORREF m_BaseColor;//半透明貼膜的顏色
  COLORREF m_FontColor;//字體的顏色

  BOOL m_bFlagIsFirst;//是否為第一次取得父窗口背景的標誌位

  BOOL m_bFlagIsColorSet;//是否需要貼膜
  int m_iOnTransparent;//鼠標懸浮在按鈕上時半透明貼膜的透明度
  int m_iDownTransparent;//鼠標按下是半透明貼膜的透明度

  BOOL m_bFlagIsTextSet;//是否需要打印出文字
  BOOL m_bFlagIsImageSet;//是否需要打印圖片
  //CFont m_font;
  //LOGFONT m_lf;
  //int m_iTitleSize;//按鈕文字的大小

  int m_iState;//按鈕的風格(0為採用半透明貼膜效果,1為使用3張以上PNG資源來區分狀態)
protected:
  BOOL m_bMouseOnButton;//鼠標是否在按鈕上
  BOOL m_bIsPressed;//按鍵是否按下
  BOOL m_bIsFocused;//按鍵是否得到焦點
  BOOL m_bFlagContinueShow;//這個為TRUE時按鈕的繪圖會一直保持在按下狀態
protected:
  virtual void PreSubclassWindow();//設置按鈕分割為重繪

  virtual void DrawItem( LPDRAWITEMSTRUCT lpDrawItemStruct );//重繪按鈕圖案

  //一些判斷按鈕狀態的系統函數
  afx_msg BOOL OnEraseBkgnd(CDC* pDC);//防止擦灰背景
  afx_msg void OnMouseMove(UINT nFlags, CPoint point);//鼠標移動到上面時判斷狀態
  LRESULT OnMouseLeave(WPARAM wParam, LPARAM lParam);//鼠標離開時消息判斷狀態
  afx_msg void OnKillFocus(CWnd* pNewWnd);//失去焦點時判斷狀態
};

.c代码

// PngButton.cpp : implementation file
//

#include "stdafx.h"
#include "PngButton.h"
// CPngButton

IMPLEMENT_DYNAMIC(CPngButton, CButton)

CPngButton::CPngButton()
: m_bFlagIsColorSet(FALSE)
, m_bFlagIsTextSet(FALSE)
, m_bFlagIsImageSet(FALSE)
, m_bFlagIsFirst(TRUE)
, m_bMouseOnButton(FALSE)
, m_bIsPressed(FALSE)
, m_bIsFocused(FALSE)
//, m_iTitleSize(90)
, m_iOnTransparent(0)
, m_iDownTransparent(0)
, m_iState(Disable)
, m_bFlagContinueShow(FALSE)
{
//DEL initGDI();
  m_BaseColor = RGB(0,0,0);
  m_FontColor = RGB(0,0,0);
}

CPngButton::~CPngButton()
{
}

BEGIN_MESSAGE_MAP(CPngButton, CButton)
  ON_WM_ERASEBKGND()
  ON_WM_MOUSEMOVE()
  ON_WM_KILLFOCUS()
  ON_MESSAGE(WM_MOUSELEAVE, OnMouseLeave)
END_MESSAGE_MAP()

// CPngButton message handlers

void CPngButton::LoadImage(CImage &image,UINT nID)
{
  HINSTANCE hInst = AfxGetResourceHandle();
  HRSRC hRsrc = ::FindResource(hInst,MAKEINTRESOURCE(nID), _T("PNG"));
  if (hRsrc == NULL)
    return;

  DWORD len = SizeofResource(hInst, hRsrc);
  BYTE* lpRsrc = (BYTE*)LoadResource(hInst, hRsrc);
  if (lpRsrc == NULL)
    return;

  HGLOBAL m_hMem = GlobalAlloc(GMEM_FIXED, len);
  BYTE* pmem = (BYTE*)GlobalLock(m_hMem);
  memcpy(pmem,lpRsrc,len);
  IStream* pstm;
  CreateStreamOnHGlobal(m_hMem,FALSE,&pstm);

  image.Destroy();
  image.Load(pstm);

  GlobalUnlock(m_hMem);
  GlobalFree(m_hMem);
  pstm->Release();
  FreeResource(lpRsrc);

  if (image.GetBPP() == 32)
  {
    for(int i = 0; i < image.GetWidth(); i++)
    {
      for(int j = 0; j < image.GetHeight(); j++)
      {
        unsigned char* pucColor = reinterpret_cast<unsigned char *>(image.GetPixelAddress(i , j));
        pucColor[0] = pucColor[0] * pucColor[3] / 255;
        pucColor[1] = pucColor[1] * pucColor[3] / 255;
        pucColor[2] = pucColor[2] * pucColor[3] / 255;
      }
    }
  }
}

BOOL CPngButton::LoadImage(CImage &image,const CString& Path)
{
  CDC *pDC = GetDC();
  image.Destroy();
  image.Load(Path);
  if (image.IsNull())
  {
    return FALSE;
  }
  if (image.GetBPP() == 32) //确认该图像包含Alpha通道
  {
    int i;
    int j;
    for (i = 0; i < image.GetWidth(); i++)
    {
      for (j = 0; j < image.GetHeight(); j++)
      {
        byte *pByte = (byte *)image.GetPixelAddress(i, j);
        pByte[0] = pByte[0] * pByte[3] / 255;
        pByte[1] = pByte[1] * pByte[3] / 255;
        pByte[2] = pByte[2] * pByte[3] / 255;
      }
    }
  }
  ReleaseDC(pDC);
}
/*檢測和判斷按鈕狀態的消息功能們*/

void CPngButton::CancelHover(void)
{
  //功能:取消鼠標懸浮標誌位
  //參數:無
  //返回值:無
  if (m_bMouseOnButton)
  {
    m_bMouseOnButton = FALSE;
    Invalidate();
  } // if
} // End of CancelHover

void CPngButton::OnMouseMove(UINT nFlags, CPoint point)
{
  //功能:鼠標移動消息
  //參數:nFlag為指示各种虚拟按键是否按下,point為鼠標當前位置
  //返回值:無
  CWnd* wndUnderMouse = NULL;
  CWnd* wndActive = this;
  TRACKMOUSEEVENT csTME;

  CButton::OnMouseMove(nFlags, point);

  ClientToScreen(&point);
  wndUnderMouse = WindowFromPoint(point);

// If the mouse enter the button with the left button pressed then do nothing
  if (nFlags & MK_LBUTTON && m_bMouseOnButton == FALSE)//鼠標左鍵按下闖過著跳過處理
    return;

  if (wndUnderMouse && wndUnderMouse->m_hWnd == m_hWnd && wndActive)//判斷并更新按鈕當前狀態
  {
    if (!m_bMouseOnButton)
    {
      m_bMouseOnButton = TRUE;

      Invalidate();

      csTME.cbSize = sizeof(csTME);
      csTME.dwFlags = TME_LEAVE;
      csTME.hwndTrack = m_hWnd;
      ::_TrackMouseEvent(&csTME);
    } // if
  } else CancelHover();
  CButton::OnMouseMove(nFlags, point);
}

LRESULT CPngButton::OnMouseLeave(WPARAM wParam, LPARAM lParam)
{
  //功能:鼠標離開按鈕消息
  //參數:wParam,lParam鼠標位置參數
  //返回值:LRESULT
  CancelHover();//取消懸浮狀態
  return 0;
} // End of OnMouseLeave

void CPngButton::OnKillFocus(CWnd* pNewWnd)
{
  //功能:失去焦點時消息處理
  //參數:pNewWnd指定指向接收输入焦点的窗口
  //返回值:無
  CButton::OnKillFocus(pNewWnd);
  // TODO: Add your message handler code here
  CancelHover();
}

BOOL CPngButton::OnEraseBkgnd(CDC* pDC)
{
  //功能:擦除背景消息處理
  //參數:pDC為此按鈕的DC
  //返回值:無
  return TRUE;// CButton::OnEraseBkgnd(pDC);
}

/*設置相關參數*/
void CPngButton::PreSubclassWindow()
{
  //功能:按鈕設置自繪模式
  //參數:無
  //返回值:無
  ModifyStyle(0,BS_OWNERDRAW);
  CButton::PreSubclassWindow();
}

void CPngButton::SetSize(int iWidth,int iHeight)
{
  //功能:設置按鈕大小
  //參數:iWidth為按鈕寬度,iHeight為按鈕高度
  //返回值:無
  SetWindowPos( NULL, -1, -1, iWidth, iHeight,
  SWP_NOMOVE | SWP_NOZORDER | SWP_NOREDRAW | SWP_NOACTIVATE);
}

BOOL CPngButton::SetTransparentColor(COLORREF color,UINT OnTransparent,UINT DownTransparent)
{
  //功能:設置半透明貼膜參數
  //參數:color貼膜的顏色,OnTransparent是鼠標懸浮在按鈕時其透明度,DownTransparent是按鈕按下時其透明度
  //返回值:BOOL是否設置成功
  m_BaseColor = color;//載入貼膜顏色
  //DEL int ibrightness = 0.299*GetRValue(color) + 0.587*GetGValue(color) + 0.114*GetBValue(color);//亮度
  //DEL if (ibrightness > 225 || ibrightness < 15)
  //DEL {
  //DEL m_bFlagIsColorSet = FALSE;
  //DEL return FALSE;
  //DEL }
  //DEL else
  //DEL {
  //DEL m_bFlagIsColorSet = TRUE;
  //DEL return TRUE;
  //DEL }
  if (OnTransparent < 0xFF && DownTransparent < 0xFF)//半透明參數需要小於255,否則不設置貼膜
  {
  //設置貼膜有效,并載入半透明度
    m_bFlagIsColorSet = TRUE;
    m_iOnTransparent = OnTransparent;
    m_iDownTransparent = DownTransparent;
  }else{
    m_bFlagIsColorSet = FALSE;//設置貼膜無效
  }
  return m_bFlagIsColorSet;//返回貼膜設置狀態
}

void CPngButton::SetFontColor(COLORREF color)
{
  m_FontColor = color;
}

BOOL CPngButton::SetTitle(const CString &csTitle)
{
  //功能:設置標題
  //參數:csTitle為標題
  //返回值:BOOL標題是否顯示
  this->SetWindowTextW(csTitle);
  m_bFlagIsTextSet = TRUE;
  //m_font.DeleteObject();
  //m_font.CreatePointFont(m_iTitleSize, _T("微軟雅黑"));
  return m_bFlagIsTextSet;
}

void CPngButton::SetImagePng(UINT nIDNormal,UINT nIDDisable)
{
  //功能:設置按鈕對應PNG圖片
  //參數:nID為按鈕普通狀態的PNG貼圖資源,nIDDisable為按鈕失能狀態下的PNG貼圖資源
  //返回值:無
  m_bFlagIsImageSet = TRUE;;
  if (m_bFlagIsImageSet)
  {
    LoadImage(m_image[Disable],nIDDisable);
    LoadImage(m_image[Normal],nIDNormal);
    m_iState = MaskMode;
  }
  SizeToContent();
}

void CPngButton::SetImagePng(const CString& PathNormal,const CString& PathDisable)
{
  m_bFlagIsImageSet = TRUE;;
  if (m_bFlagIsImageSet)
  {
    LoadImage(m_image[Disable],PathDisable);
    LoadImage(m_image[Normal],PathNormal);
    m_iState = MaskMode;
  }
  SizeToContent();
}

void CPngButton::SetImagePng(UINT nIDNormal,UINT nIDOn,UINT nIDDown,UINT nIDDisable)
{
  //功能:設置按鈕對應PNG圖片
  //參數:nID為按鈕普通狀態的PNG貼圖資源,nIDOn為鼠標懸浮在按鈕上狀態的PNG貼圖資源,nIDDown為按鈕按下狀態的PNG貼圖資源,nIDDisable為按鈕失能狀態下的PNG貼圖資源
  //返回值:無
  m_bFlagIsImageSet = TRUE;
  if (m_bFlagIsImageSet)
  {
    if(m_image[Disable].IsNull() == FALSE)
      m_image[Disable].Destroy();
    LoadImage(m_image[Disable],nIDDisable);

    if(m_image[Normal].IsNull() == FALSE)
      m_image[Normal].Destroy();
    LoadImage(m_image[Normal],nIDNormal);

    if(m_image[On].IsNull() == FALSE)
      m_image[On].Destroy();
    LoadImage(m_image[On],nIDOn);

    if(m_image[Down].IsNull() == FALSE)
      m_image[Down].Destroy();
    LoadImage(m_image[Down],nIDDown);
    m_iState = PictureMode;
  }
  SizeToContent();
}

void CPngButton::SetImagePng(const CString& PathNormal,const CString& PathOn,const CString& PathDown,const CString& PathDisable)
{
  m_bFlagIsImageSet = TRUE;;
  if (m_bFlagIsImageSet)
  {
    if(m_image[Disable].IsNull() == FALSE)
      m_image[Disable].Destroy();
    LoadImage(m_image[Disable],PathDisable);

    if(m_image[Normal].IsNull() == FALSE)
      m_image[Normal].Destroy();
    LoadImage(m_image[Normal],PathNormal);

    if(m_image[On].IsNull() == FALSE)
      m_image[On].Destroy();
    LoadImage(m_image[On],PathOn);

    if(m_image[Down].IsNull() == FALSE)
      m_image[Down].Destroy();
    LoadImage(m_image[Down],PathDown);
    m_iState = PictureMode;
  }
  SizeToContent();
}

void CPngButton::SetContinueShow(BOOL ContinueShow)
{
  //功能:設置是否一直顯示為按下狀態
  //參數:ContinueShow為是否要一直顯示為按下狀態
  //返回值:無
  m_bFlagContinueShow = ContinueShow;
}

void CPngButton::SizeToContent(void)
{
  //功能:使按鈕大小和載入的圖片大小一致
  //參數:無
  //返回值:無
  if (m_image[1] != NULL)
  {
    SetWindowPos( NULL, -1, -1, m_image[1].GetWidth(),m_image[1].GetHeight() ,
    SWP_NOMOVE | SWP_NOZORDER | SWP_NOREDRAW | SWP_NOACTIVATE);
  } // if
} // End of SizeToContent

void CPngButton::SaveBG(void)
{
  //功能:保存父窗口擋住的背景
  //參數:無
  //返回值:無
  CRect rc;
  this->GetWindowRect(&rc);
  CDC* pDC = GetDC();
  CBitmap memBitmap;

  //得到父窗口句柄以及控件在父窗口的位置
  CDC* pParentDC = GetParent()->GetDC();
  CPoint pt(0,0);
  MapWindowPoints(GetParent(),&pt,1);

  if (m_MemDCBG == NULL)//如果已經m_MemDCBG已經創建了就不用再創建了,否則下次調用時會錯誤
    m_MemDCBG.CreateCompatibleDC(pDC);

  //將擋住的父窗口背景部分保存入m_MemDCBG中
  memBitmap.CreateCompatibleBitmap(pDC, rc.Width(), rc.Height());
  m_MemDCBG.SelectObject(&memBitmap);
  m_MemDCBG.BitBlt(0,0,rc.Width(),rc.Height(),pParentDC,pt.x,pt.y,SRCCOPY);

  ::ReleaseDC(GetParent()->m_hWnd,*pParentDC);
  ::ReleaseDC(this->m_hWnd,*pDC);
}

BOOL CPngButton::SetShowState(BOOL NeedColorSet, BOOL NeedTextSet,BOOL NeedImageSet)
{
  //功能:設置按鈕風格
  //參數:NeedColorSet為是否顯示貼膜,NeedTextSet為是否打印文字,NeedImageSet為是否打印PNG圖片
  //返回值:無
  BOOL bFlagSuccessSet = TRUE;
  //設置是否顯示貼膜
  if (NeedColorSet)
  {
    if (m_BaseColor == NULL)
    {
      bFlagSuccessSet = FALSE;
    }else
      m_bFlagIsColorSet = NeedColorSet;
  }else{
    m_bFlagIsColorSet = NeedColorSet;
  }
  //設置是否顯示文字
  m_bFlagIsTextSet = NeedTextSet;
  //設置是否顯示png資源
  if (m_image[Disable] == NULL)
    ;
  else
    m_bFlagIsImageSet = NeedImageSet;
  return bFlagSuccessSet;
}

/*繪製按鈕*/
void CPngButton::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{
  //功能:繪製按鈕,參考BitButtonNL類
  //參數:lpDrawItemStruct按鈕參數
  //返回值:無
  m_bIsFocused = (lpDrawItemStruct->itemState & ODS_FOCUS);//按鈕是否有焦點
  m_bIsPressed = (lpDrawItemStruct->itemState & ODS_SELECTED);//按鈕是否按下
  if (m_bFlagIsFirst)//第一次調用保存父窗口擋住的背景
  {
    SaveBG();
    m_bFlagIsFirst = FALSE;
    DrawItem(lpDrawItemStruct);
  }else{
    CRect rc;
    this->GetWindowRect(&rc);
    CDC* pDC = CDC::FromHandle(lpDrawItemStruct->hDC);
    pDC->SetBkMode(TRANSPARENT);

    CDC MemDC;
    CBitmap bmp;

    //創建雙緩存用的MemDC
    MemDC.CreateCompatibleDC(pDC);
    bmp.CreateCompatibleBitmap(pDC,rc.Width(),rc.Height());
    MemDC.SelectObject(&bmp);

    MemDC.BitBlt(0,0,rc.Width(),rc.Height(),&m_MemDCBG,0,0,SRCCOPY); //畫父窗口擋住的背景
    if(IsWindowEnabled())
    {
      switch(m_iState)
      {
      case MaskMode:
        if ((m_bFlagIsColorSet && m_bMouseOnButton ) || m_bFlagContinueShow)
        {
          //畫半透明貼膜
          CDC MemDCBK;
          CDC* pDCDrawBG;
          pDCDrawBG = GetDC();
          CBitmap bmpBK;

          //創建半透明貼膜
          MemDCBK.CreateCompatibleDC(pDCDrawBG);
          bmpBK.CreateCompatibleBitmap(pDCDrawBG,rc.Width(),rc.Height());
          MemDCBK.SelectObject(&bmpBK);
          MemDCBK.FillSolidRect(0,0,rc.Width(),rc.Height(),m_BaseColor);

          //半透明參數設置
          BLENDFUNCTION bf;
          bf.BlendOp=AC_SRC_OVER;
          bf.BlendFlags=0;
          if(m_bIsPressed || m_bFlagContinueShow)
            bf.SourceConstantAlpha=m_iDownTransparent;
          else
            bf.SourceConstantAlpha=m_iOnTransparent;
          bf.AlphaFormat=0;

          MemDC.AlphaBlend(0,0,rc.Width(),rc.Height(),&MemDCBK,0,0,rc.Width(),rc.Height(),bf);//貼膜

          ::ReleaseDC(this->m_hWnd, *pDCDrawBG);
        }//end if ((m_bFlagIsColorSet && m_bMouseOnButton ) || m_bFlagContinueShow)
        if (m_bFlagIsImageSet)
        {
          m_image[Normal].Draw(MemDC.m_hDC,0,0);
        }//end if (m_bFlagIsImageSet)
        break;
      case PictureMode:
        if (m_bMouseOnButton || m_bFlagContinueShow)
        {
          if(m_bIsPressed || m_bFlagContinueShow)
            m_image[Down].Draw((&MemDC)->m_hDC,0,0);
          else
            m_image[On].Draw((&MemDC)->m_hDC,0,0);
        }else{//end if (m_bMouseOnButton || m_bFlagContinueShow)
          m_image[Normal].Draw((&MemDC)->m_hDC,0,0);
        }//end if (m_bMouseOnButton || m_bFlagContinueShow)...else
        break;
      }//end switch(m_iState)
    }else{//endif(IsWindowEnabled())
      if (m_image[Disable] != NULL)
        m_image[Disable].Draw((&MemDC)->m_hDC,0,0);
      else
        m_image[Normal].Draw((&MemDC)->m_hDC,0,0);
    }
    if (m_bFlagIsTextSet)
    {
      //畫文字
      CString sTitle;
      GetWindowText(sTitle);

      //設置文字風格
      SetBkMode(MemDC, TRANSPARENT);
      SetTextColor(MemDC,m_FontColor);
      //設置畫在控件中心
      CRect captionRect = lpDrawItemStruct->rcItem;
      captionRect.top--;

      MemDC.SelectObject(GetFont());
      MemDC.DrawText((LPCTSTR)sTitle, &captionRect,DT_SINGLELINE | DT_VCENTER | DT_WORDBREAK | DT_CENTER);
    }//end if (m_bFlagIsTextSet)
  pDC->BitBlt(0,0,rc.Width(),rc.Height(),&MemDC,0,0,SRCCOPY);
  }//end if (m_bFlagIsFirst)..else
}

四.结语

  今年年前写的类代码吧整整懒得优化了就发出来,有需要再优化好了.

  比较前一篇感觉代码规范了点(mmp手动缩进半天才发现可以贴代码),感觉都挺简单的应该看注释都能懂.

  看不懂也没关系按前面例子看.h试着用就完事了啦,注:有贴图的话按钮大小会跟贴图大小变化.

  海星的感觉(在公司补班打代码累了就摸了波鱼把自己搞的类贴出来,啊,摸鱼真是件幸福的事情~)

MFC的PNG贴图按钮类(详细注释)的更多相关文章

  1. UML类图及类与类之间的关系

    原文地址:http://www.uml.org.cn/oobject/201211231.asp 类图用于描述系统中所包含的类以及它们之间的相互关系,帮助人们简化对系统的理解,它是系统分析和设计阶段的 ...

  2. UML(一) 类图及类间关系

    原创文章,同步发自作者个人博客,http://www.jasongj.com/uml/class_diagram/ UML类图 UML类图介绍 在UML 2.*的13种图形中,类图是使用频率最高的UM ...

  3. PowerDesigner(八)-面向对象模型(用例图,序列图,类图,生成Java源代码及Java源代码生成类图)(转)

    面向对象模型 面向对象模型是利用UML(统一建模语言)的图形来描述系统结构的模型,它从不同角度实现系统的工作状态.这些图形有助于用户,管理人员,系统分析人员,开发人员,测试人员和其他人员之间进行信息交 ...

  4. UML九种图-包图、类图

    UML九种图-包图.类图 一.包 (一)相关概念: 1.包: 一个包=一层=一个命名空间=一个文件夹 2.包的命名: 简单名:王老二 路径名:中国.河北省.廊坊市.廊坊师范学院.信息技术提高班.九期班 ...

  5. MFC关于多线程中传递窗口类指针时ASSERT_VALID出错的另类解决 转

    MFC关于多线程中传递窗口类指针时ASSERT_VALID出错的另类解决   在多线程设计中,许多人为了省事,会将对话框类或其它类的指针传给工作线程,而在工作线程中调用该类的成员函数或成员变量等等. ...

  6. MFC编程之数值调节按钮

    MFC编程之数值调节按钮 一丶数值调节按钮使用的注意事项 CSpinButtonCtrl类是MFC封装的数值调节按钮. 我们要使用数值调节按钮需要注意的事项. 1.数值调节按钮跟一个编辑框配合使用. ...

  7. MFC控件编程之 按钮编辑框.静态文本的使用,以及访问控件的七种方法.

    MFC控件编程之 按钮编辑框.静态文本的使用以及访问控件的七种方法. 一丶按钮.静态文本的通用属性. 他们都有一个属性.就是可以输入标题内容.以及可以自定义控件ID. 创建一个MFC Dlg对话框. ...

  8. WorldWind源码剖析系列:图层管理器按钮类LayerManagerButton和菜单条类MenuBar

    WorldWindow用户定制控件类中所包含的的可视化子控件主要有:图层管理器按钮类LayerManagerButton和菜单条类MenuBar.BmngLoader类中所包含的的可视化子控件主要有: ...

  9. 八、面向对象模型(用例图,序列图,类图,生成Java源代码及Java源代码生成类图)

    面向对象模型 面向对象模型是利用UML(统一建模语言)的图形来描述系统结构的模型,它从不同角度实现系统的工作状态.这些图形有助于用户,管理人员,系统分析人员,开发人员,测试人员和其他人员之间进行信息交 ...

随机推荐

  1. 提升node.js中使用redis的性能

    问题初现 某基于node.js开发的业务系统向外提供了一个dubbo服务,提供向第三方缓存查询.设置多项业务数据并聚合操作结果.在QPS达到800时(两台虚拟机,每台机器4Core8G4node进程) ...

  2. 湖南省队集训 Day 2

    从这里开始 Problem A 走路 Problem B 游戏 Problem C 有趣的字符串题 暴力分又没骗满sad..... Problem A 走路 $O(n^2)$动态规划是显然的. 更新方 ...

  3. Oracle错误——ORA-39002:操作无效、ORA-39070:无法打开日志文件、ORA-06512:在“SYS.UTL_FILE”,line

    错误 在使用数据泵impdp导入文件时,出现错误,无法导入数据 Next 问题原因 初步猜测,应该是Oracle用户权限出现问题,是对Directory目录无操作权限所致,经过一番修改和测试,发现使用 ...

  4. time模块和os模块,json模块

    import time # def month(n): # time.local() # struct_time=time.strptime("%Y-%m-1","%Y- ...

  5. (Code) Python implementation of phrase extraction from sentence

    import os import numpy as np import pandas as pd from tqdm import tqdm import numpy as np import str ...

  6. Redis集群(主从模式)

    主从模型   在Redis的集群当中,每个节点(实例)都有一个身份:Master或者Slave,Master:主要负责数据写入,Slave一般提供数据读取,Master与Slave之间是一对多关系,M ...

  7. jQuery添加删除

    //代码 <!DOCTYPE HTML> <html> <head> <meta charset="utf-8"> <titl ...

  8. 51nod 1201 整数划分 dp

    1201 整数划分 基准时间限制:1 秒 空间限制:131072 KB   收藏  关注 将N分为若干个不同整数的和,有多少种不同的划分方式,例如:n = 6,{6} {1,5} {2,4} {1,2 ...

  9. 爬坑之路---Google map

    google.maps.event.adddDomListen(window, 'load', callback);当文档流中所有的dom加载完成后,执行回调函数,可以不用在script中使用defe ...

  10. 在Python中使用SMTP发送电子邮件

    Python中有内置的smtplib模块,完成一封邮件的发送,需要做很多准备工作.第三方的py_smtp这个包也是基于smtplib的,在Python中使用py_smtp发送电子邮件非常方便,只要填写 ...