【自绘Button之一】带Icon的按钮控件

来源:互联网 发布:机械制图用什么软件 编辑:程序博客网 时间:2024/04/25 05:07
参考:CButtonST的源码Demo下载:CIconBtn_DemoDemo程序图片:使用示例:
m_btn1.SetIcon(IDI_ICON_TEST);  //设置Icon// 设置Icon与Text的对齐方式为:Icon在左Text在右m_btn1.SetAlign(CIconBtn::IBTN_ICON_LEFT_TEXT_RIGHT);m_btn2.SetIcon(IDI_ICON_TEST);// 设置Icon与Text的对齐方式为:Icon在右Text在左m_btn2.SetAlign(CIconBtn::IBTN_ICON_RIGHT_TEXT_LEFT);m_btn3.SetIcon(IDI_ICON_TEST);// 设置Icon与Text的对齐方式为:Icon在顶Text在底m_btn3.SetAlign(CIconBtn::IBTN_ICON_TOP_TEXT_BOTTOM);m_btn4.SetIcon(IDI_ICON_TEST);// 设置Icon与Text的对齐方式为:Icon在底Text在顶m_btn4.SetAlign(CIconBtn::IBTN_ICON_BOTTOM_TEXT_TOP);
    可以先查看之前的一篇博文:WM_DRAWITEM通告消息    这篇文章比较详细的讲述了怎样绘制和标准PushButton一样的按钮。
CIconBtn类:
class CIconBtn : public CButton{DECLARE_DYNAMIC(CIconBtn)public:CIconBtn();virtual ~CIconBtn();virtual BOOL PreTranslateMessage(MSG* pMsg);virtual void PreSubclassWindow();virtual void DrawItem(LPDRAWITEMSTRUCT /*lpDrawItemStruct*/);enum{IBTN_ICON_LEFT_TEXT_RIGHT = 0,  // Left:Icon   Right:TextIBTN_ICON_RIGHT_TEXT_LEFT,      // Right:Icon  Left:TextIBTN_ICON_TOP_TEXT_BOTTOM,      // Top:Icon    Bottom:TextIBTN_ICON_BOTTOM_TEXT_TOP       // Bottom:Icon Top:Text};protected:void DrawBackground();void DrawBorder();void Draw3DBorderForRect(CDC *pDC, CRect *pRect);void DrawFocusRect();void DrawIcon();void DrawText();void PrepareDrawIconAndText();public:BOOL SetIcon(int nIcon, int nCxDesired = 0, int nCyDesired = 0);BOOL SetAlign(BYTE byAlign);private:BYTE  m_byAlign;            // text与icon的对齐方式CDC*  m_pDC;                // dc handle pointerCRect m_rcBtn;              // 按钮rectbool  m_bIsFocused;         // 按钮是否获得焦点bool  m_bIsPressed;         // 按钮是否被按下bool  m_bIsDisabled;        // 按钮是否DisableHICON m_hIcon;              // Icon handleint   m_nIconWidth;         // Icon widthint   m_nIconHeight;        // Icon heightint   m_nFocusRectOffset;// 焦点矩形的偏移量int   m_nCxIconStart;       // Draw icon的起始点x坐标int   m_nCyIconStart;       // Draw icon的起始点y坐标RECT  m_rcText;             // Draw text的矩形区域protected:DECLARE_MESSAGE_MAP()};
一. override PreTranslateMessage将鼠标双击消息解释为两次鼠标单击消息。
BOOL CIconBtn::PreTranslateMessage(MSG* pMsg){// TODO: Add your specialized code here and/or call the base classif (pMsg->message == WM_LBUTTONDBLCLK)pMsg->message = WM_LBUTTONDOWN;return CButton::PreTranslateMessage(pMsg);}
二. override PreSubclassWindow将控件更改为Owner-Draw风格。
void CIconBtn::PreSubclassWindow(){// TODO: Add your specialized code here and/or call the base classModifyStyle(BS_TYPEMASK, BS_OWNERDRAW, SWP_FRAMECHANGED);CButton::PreSubclassWindow();}
三. override DrawItem
void CIconBtn::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct){// 获取DC及按钮大小m_pDC = CDC::FromHandle(lpDrawItemStruct->hDC);m_pDC->SetBkMode(TRANSPARENT);m_rcBtn = lpDrawItemStruct->rcItem;// 监测按钮状态m_bIsFocused  = lpDrawItemStruct->itemState & ODS_FOCUS;m_bIsPressed  = lpDrawItemStruct->itemState & ODS_SELECTED;m_bIsDisabled = lpDrawItemStruct->itemState & ODS_DISABLED;// Draw backgroundthis->DrawBackground();// Draw borderthis->DrawBorder();// Draw focus rectthis->DrawFocusRect();// 计算Draw icon的位置及Draw text的矩形this->PrepareDrawIconAndText();// Draw iconif (m_hIcon)this->DrawIcon();// Draw textCString strText;GetWindowText(strText);if (!strText.IsEmpty())this->DrawText();}//// Draw background//void CIconBtn::DrawBackground(){CBrush brushBk(::GetSysColor(COLOR_BTNFACE));if (m_bIsFocused){m_rcBtn.DeflateRect(1, 1);m_pDC->FillRect(&m_rcBtn, &brushBk);m_rcBtn.DeflateRect(-1, -1);CBrush brushFrame(RGB(0, 0, 0));m_pDC->FrameRect(&m_rcBtn, &brushFrame);}else{m_pDC->FillRect(&m_rcBtn, &brushBk);}}//// Draw border//void CIconBtn::DrawBorder(){if (m_bIsPressed){m_rcBtn.DeflateRect(1, 1);CBrush brBtnShadow(::GetSysColor(COLOR_BTNSHADOW));m_pDC->FrameRect(&m_rcBtn, &brBtnShadow);m_rcBtn.DeflateRect(-1, -1);}else if (m_bIsFocused){m_rcBtn.DeflateRect(1, 1);this->Draw3DBorderForRect(m_pDC, &m_rcBtn);m_rcBtn.DeflateRect(-1, -1);}else{this->Draw3DBorderForRect(m_pDC, &m_rcBtn);}}//// 为pRect绘制3D边框//void CIconBtn::Draw3DBorderForRect(CDC *pDC, CRect *pRect){CPen penBtnHiLight(PS_SOLID, 0, GetSysColor(COLOR_BTNHILIGHT)); // WhiteCPen pen3DLight(PS_SOLID, 0, GetSysColor(COLOR_3DLIGHT));       // Light grayCPen penBtnShadow(PS_SOLID, 0, GetSysColor(COLOR_BTNSHADOW));   // Dark grayCPen pen3DDKShadow(PS_SOLID, 0, GetSysColor(COLOR_3DDKSHADOW)); // Black// Draw top-left borders// White lineCPen* pOldPen = pDC->SelectObject(&penBtnHiLight);pDC->MoveTo(pRect->left, pRect->bottom-1);pDC->LineTo(pRect->left, pRect->top);pDC->LineTo(pRect->right, pRect->top);// Light gray linepDC->SelectObject(pen3DLight);pDC->MoveTo(pRect->left+1, pRect->bottom-1);pDC->LineTo(pRect->left+1, pRect->top+1);pDC->LineTo(pRect->right, pRect->top+1);// Draw bottom-right borders// Black linepDC->SelectObject(pen3DDKShadow);pDC->MoveTo(pRect->left, pRect->bottom-1);pDC->LineTo(pRect->right-1, pRect->bottom-1);pDC->LineTo(pRect->right-1, pRect->top-1);// Dark gray linepDC->SelectObject(penBtnShadow);pDC->MoveTo(pRect->left+1, pRect->bottom-2);pDC->LineTo(pRect->right-2, pRect->bottom-2);pDC->LineTo(pRect->right-2, pRect->top);//pDC->SelectObject(pOldPen);}//// 绘制焦点矩形//void CIconBtn::DrawFocusRect(){if (m_bIsFocused){m_rcBtn.DeflateRect(m_nFocusRectOffset, m_nFocusRectOffset);m_pDC->DrawFocusRect(&m_rcBtn);m_rcBtn.DeflateRect(-m_nFocusRectOffset, -m_nFocusRectOffset);}}//// 计算绘制icon与text的位置//void CIconBtn::PrepareDrawIconAndText(){// 判断有无text与iconbool bIsHasText = false;bool bIsHasIcon  = false;CString cstrCaption;this->GetWindowText(cstrCaption);bIsHasText = !cstrCaption.IsEmpty();if (m_hIcon)bIsHasIcon = true;// 计算绘制icon与text的位置if (bIsHasText && bIsHasIcon)//既有text又有icon{switch (m_byAlign){case IBTN_ICON_LEFT_TEXT_RIGHT:{m_nCxIconStart = m_rcBtn.left + m_nFocusRectOffset;m_nCyIconStart = m_rcBtn.top + (m_rcBtn.Height() - m_nIconHeight) / 2;m_rcText.left = m_rcBtn.left + m_nFocusRectOffset + m_nIconWidth;m_rcText.top = m_rcBtn.top + m_nFocusRectOffset;m_rcText.right = m_rcBtn.right - m_nFocusRectOffset;m_rcText.bottom = m_rcBtn.bottom - m_nFocusRectOffset;}break;case IBTN_ICON_RIGHT_TEXT_LEFT:{m_nCxIconStart = m_rcBtn.right - m_nFocusRectOffset - m_nIconWidth;m_nCyIconStart = m_rcBtn.top + (m_rcBtn.Height() - m_nIconHeight) / 2;m_rcText.left = m_rcBtn.left + m_nFocusRectOffset;m_rcText.top = m_rcBtn.top + m_nFocusRectOffset;m_rcText.right = m_rcBtn.right - m_nFocusRectOffset - m_nIconWidth;m_rcText.bottom = m_rcBtn.bottom - m_nFocusRectOffset;}break;case IBTN_ICON_TOP_TEXT_BOTTOM:{m_nCxIconStart = m_rcBtn.left + (m_rcBtn.Width() - m_nIconWidth) / 2;m_nCyIconStart = m_rcBtn.top + m_nFocusRectOffset;m_rcText.left = m_rcBtn.left + m_nFocusRectOffset;m_rcText.top = m_rcBtn.top + m_nFocusRectOffset + m_nIconHeight;m_rcText.right = m_rcBtn.right - m_nFocusRectOffset;m_rcText.bottom = m_rcBtn.bottom - m_nFocusRectOffset;}break;case IBTN_ICON_BOTTOM_TEXT_TOP:{m_nCxIconStart = m_rcBtn.left + (m_rcBtn.Width() - m_nIconWidth) / 2;m_nCyIconStart = m_rcBtn.bottom - m_nFocusRectOffset - m_nIconHeight;m_rcText.left = m_rcBtn.left + m_nFocusRectOffset;m_rcText.top = m_rcBtn.top + m_nFocusRectOffset;m_rcText.right = m_rcBtn.right - m_nFocusRectOffset;m_rcText.bottom = m_rcBtn.bottom - m_nFocusRectOffset - m_nIconHeight;}break;default:break;}}else if (!bIsHasText && bIsHasIcon)//没有text只有icon{m_nCxIconStart = m_rcBtn.left + (m_rcBtn.Width() - m_nIconWidth) / 2;m_nCyIconStart = m_rcBtn.top + (m_rcBtn.Height() - m_nIconHeight) / 2;m_rcText.left = 0;m_rcText.top = 0;m_rcText.right = 0;m_rcText.bottom = 0;}else if (bIsHasText && !bIsHasIcon)  //只有text没有icon{m_nCxIconStart = 0;m_nCyIconStart = 0;m_rcText.left = m_rcBtn.left;m_rcText.top = m_rcBtn.top;m_rcText.right = m_rcBtn.right;m_rcText.bottom = m_rcBtn.bottom;}else{m_nCxIconStart = 0;m_nCyIconStart = 0;m_rcText.left = 0;m_rcText.top = 0;m_rcText.right = 0;m_rcText.bottom = 0;}}//// 绘制ICON//void CIconBtn::DrawIcon(){// 判断有无iconif (!m_hIcon)return;// 如果Disabled则灰掉// 如果Pressed则icon向右及向下各移1格UINT flag = DST_ICON | (m_bIsDisabled ? DSS_DISABLED : DSS_NORMAL);int nCxIconStart = m_bIsPressed ? m_nCxIconStart + 1 : m_nCxIconStart;int nCyIconStart = m_bIsPressed ? m_nCyIconStart + 1 : m_nCyIconStart;// Draw icon::DrawState(m_pDC->m_hDC, NULL, NULL, (LPARAM)m_hIcon, NULL,nCxIconStart, nCyIconStart, m_nIconWidth, m_nIconHeight, flag);}//// 绘制Text//void CIconBtn::DrawText(){// 判断有无textCString strText;GetWindowText(strText);if (strText.IsEmpty())return;// 如果按下则text向右及向下各移动一格if (m_bIsPressed){m_rcText.left += 2;}else{m_rcText.bottom -= 2; // 使text真正垂直居中}// Draw textif (m_bIsDisabled)//draw text并灰掉text{CRect rcText(&m_rcText);rcText.OffsetRect(1, 1);m_pDC->SetTextColor(::GetSysColor(COLOR_3DHILIGHT));m_pDC->DrawText(strText, &rcText, DT_SINGLELINE | DT_VCENTER | DT_CENTER);rcText.OffsetRect(-1, -1);m_pDC->SetTextColor(::GetSysColor(COLOR_3DSHADOW));m_pDC->DrawText(strText, &rcText, DT_SINGLELINE | DT_VCENTER | DT_CENTER);}else  // draw text{m_pDC->DrawText(strText, &m_rcText, DT_SINGLELINE | DT_VCENTER | DT_CENTER);}}
四. 开放接口
//// 设定Icon//BOOL CIconBtn::SetIcon(int nIcon, int nCxDesired, int nCyDesired){HICON hIcon = (HICON)::LoadImage(::GetModuleHandle(NULL), MAKEINTRESOURCE(nIcon), IMAGE_ICON, nCxDesired, nCyDesired, 0);if (hIcon){// 先释放先前的ICON::DestroyIcon(m_hIcon);//m_hIcon = hIcon;// Get icon sizeICONINFO ici;  ::GetIconInfo(m_hIcon, &ici);  BITMAP bm;  ::GetObject(ici.hbmColor, sizeof(BITMAP), &bm);  m_nIconWidth = bm.bmWidth;  m_nIconHeight = bm.bmHeight; ::DeleteObject(ici.hbmColor);  ::DeleteObject(ici.hbmMask);  return TRUE;}elsereturn FALSE;}//// 设定Icon与Text的对齐方式//BOOL CIconBtn::SetAlign(BYTE byAlign){switch (byAlign){case IBTN_ICON_LEFT_TEXT_RIGHT:case IBTN_ICON_RIGHT_TEXT_LEFT:case IBTN_ICON_TOP_TEXT_BOTTOM:case IBTN_ICON_BOTTOM_TEXT_TOP:m_byAlign = byAlign;default:return FALSE;}return TRUE;}
原创粉丝点击