自画按钮

    技术2022-05-11  80

    要实现定制按钮的功能,可以从MFC的CButton派生出你自己的一个子类,比如CIndicatorButton,其定义如下: class CIndicatorButton : public CButton { // Construction public:     CIndicatorButton(); // Attributes public: // Operations public:     void SetBkColor(COLORREF crBk); // 设置背景颜色     COLORREF GetBkColor() { return m_crBk; } // 得到背景色(用CBrush画时的颜色)     void SetForeColor(COLORREF crFore); // 设置前景颜色(用CPen画时的颜色)     COLORREF GetForeColor() { return m_crFore; } // 得到前景色     // 设置超级连接标志     void SetHypertextFlag(BOOL bIsHypertext = TRUE) { m_bIsHypertext = bIsHypertext; } // Overrides     // ClassWizard generated virtual function overrides     //{{AFX_VIRTUAL(CIndicatorButton)     public:     virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct); // 在这个函数中按你的意愿去画按钮     protected:     virtual void PreSubclassWindow(); // 在这个函数中给按钮加入自画风格     //}}AFX_VIRTUAL // Implementation public:     virtual ~CIndicatorButton();     // Generated message map functions protected:     //{{AFX_MSG(CIndicatorButton)         // NOTE - the ClassWizard will add and remove member functions here.     afx_msg void OnMouseMove(UINT nFlags, CPoint point);     //}}AFX_MSG     DECLARE_MESSAGE_MAP() private:     COLORREF m_crBk;     COLORREF m_crFore;     HCURSOR m_hCursor; // 超级连接时的光标     HCURSOR m_hOldCursor;// 正常时的光标     BOOL m_bIsHypertext; // 如果是超级连接文本 }; 代码如下: // 构造函数,用来初始化变量 CIndicatorButton::CIndicatorButton()     {     m_crBk = RGB(0, 0, 255); // 初始化背景色为蓝色     m_crFore = RGB(255, 255, 0);// 初始化前景色为黄色 } // 按钮子类化之前调用的虚拟函数,在这个函数中修改按钮风格 void CIndicatorButton::PreSubclassWindow() {     // TODO: Add your specialized code here and/or call the base class     UINT uStyle = GetButtonStyle(); // 得到按钮的愿风格     SetButtonStyle(uStyle | BS_OWNERDRAW);// 加入自画风格     CButton::PreSubclassWindow(); } // 设置背景色 void CIndicatorButton::SetBkColor(COLORREF crBk) {     m_crBk = crBk;     Invalidate(); // 通知按钮重绘自己 } // 设置前景色 void CIndicatorButton::SetForeColor(COLORREF crFore) {     m_crFore = crFore;     Invalidate(); } // 根据鼠标的移动来改变按钮的外观 void CIndicatorButton::OnMouseMove(UINT nFlags, CPoint point) {     // TODO: Add your message handler code here and/or call default     CRect rcItem;     GetClientRect(rcItem);     if (rcItem.PtInRect(point))     {         // 只在第一次重绘,否则会闪烁         if (this != GetCapture())         {             SetCapture();             m_crBk = RGB(0, 0, 0);             Invalidate();         }         if (m_bIsHypertext)         {                     if (NULL == m_hCursor)                         m_hCursor = AfxGetApp()->LoadCursor(IDC_CURSOR);                          m_hOldCursor = ::SetCursor(m_hCursor);                 }     }     else     {         ReleaseCapture();         m_crBk = RGB(0, 0, 255);         if (m_bIsHypertext)         {             if (NULL != m_hOldCursor)                 ::SetCursor(m_hOldCursor);         }         Invalidate();     }     CButton::OnMouseMove(nFlags, point); } // 这个函数是关键函数,在这里你几乎可以实现你想要的任何按钮 // DRAWITEMSTRUCT 结构请参看MSDN文档 void CIndicatorButton::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct) {     // TODO: Add your code to draw the specified item     // 如果不是按钮不则不进行任何操作     if (lpDrawItemStruct->CtlType != ODT_BUTTON)         return ;              CDC *pDC = CDC::FromHandle(lpDrawItemStruct->hDC); //     将句柄的DC转化为MFC类,以方便后续操作     CString strCaption; // 按钮标题     GetWindowText(strCaption);// 得到按钮标题,以备后续操作可以在DC上重画按钮标题          // 设置背景模式为透明,否则在画按钮标题时,标题的背景会部分地覆盖掉按钮的背景     pDC->SetBkMode(TRANSPARENT);     // 在这里更改按钮的背景色,当然还有其它的办法,反正只要在这个DC上涂上你所要的背景色即可     pDC->FillRect(&lpDrawItemStruct->rcItem, &CBrush(RGB(0, 0, 255)));          pDC->SetTextColor(m_crFore); // 设置前景色     // 画按钮标题,水平和垂直都居中。当然你也可以用 TextOut等函数来实现,反正你把DC当作一个画布就是了,你想怎么画就怎么画     // 如果要使DT_VCENTER(垂直居中)有效,必须同时设置DT_SINGLELINE(单行)风格     pDC->DrawText(strCaption, lpDrawItemStruct->rcItem, DT_SINGLELINE | DT_CENTER | DT_VCENTER);          // 按钮具有焦点时,画聚焦矩形     if (ODS_FOCUS == itemState || ODA_FOCUS == itemAction)     {             CRect rcFocus(rcItem);// 聚焦矩形         rcFocus.DeflateRect(2, 2); // 聚焦矩形要小些         pDC->DrawFocusRect(&rcFocus);     }          // 余下的自己去完成吧,比如你可以根据鼠标的移动来改变颜色字体等,但要注意不要随意地重绘,     // 因为如果随意地重绘会产生严重的闪烁,所以只有在必要的时候进行重绘,比如在鼠标在进入时重绘次,在没有     // 出来重入之前就不重绘等等 }

    最新回复(0)