codeproject下载的按钮类,我研究该源码,发现一个有趣的问题CKbcButton是封装的按钮类,其中有一个函数源码为:BOOL CKbcButton::OnEraseBkgnd(CDC* pDC) 
{
// do not draw back ground. just return here, so we can see the background.
// if you have curiosity about this, then remove ON_WM_ERASEBKGND() and test..
return TRUE;
// return CButton::OnEraseBkgnd(pDC);
}
我手贱了一下, 把return TRUE注释掉后,用 return CButton::OnEraseBkgnd(pDC);替换return TRUE.发现了  最终按钮的效果为:
而没有替换那句代码之前,按钮的效果为:
该类的头文件:class CKbcButton : public CButton
{
public:
enum BUTTON_STATE
{
BUTTON_ENABLE = 0,
BUTTON_HOVER,
BUTTON_CLICK,
BUTTON_DISABLE
};

void SetButtonImage(CString strFileName,UINT nMakse); // set button image..
void SetButtonEnable();// make button enable/disable
void SetButtonDisable();
void SetToolTipText(CString strText);// set tooltip message
void SetCursor(HCURSOR hCursor);// set cursorprotected:
CKbcBmp m_bmpImage; // save image.
UINT m_nMask; // save mask
BOOL m_bDisable; // enable or disable
CRect m_rectButton; // about button's position
CRect m_rectButtonPos; // about button's position
BOOL m_bCursorOnButton;  // cursor is on button or not.
BOOL m_bHover; // determine button state is hover or not.
CToolTipCtrl m_ToolTip; // for tooltip message..
BOOL m_bSetCursor;
HCURSOR m_hCursor; // set cursor
// Construction
public:
CKbcButton();// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CKbcButton)
public:
virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct);
virtual BOOL PreTranslateMessage(MSG* pMsg);
//}}AFX_VIRTUAL// Implementation
public:
virtual ~CKbcButton(); // Generated message map functions
protected:
//{{AFX_MSG(CKbcButton)
afx_msg void OnMouseMove(UINT nFlags, CPoint point);
afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
afx_msg BOOL OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message);
afx_msg BOOL OnEraseBkgnd(CDC* pDC);
//}}AFX_MSG
afx_msg LRESULT OnMouseLeave(WPARAM wparam, LPARAM lparam);
afx_msg LRESULT OnMouseHover(WPARAM wparam, LPARAM lparam);
DECLARE_MESSAGE_MAP()
};
重载了几个重要的函数:第一个是 DrawItem! 第2个是OnEraseBkgnd,我们知道DraItem是在 OnErasebkgnd后发出的,为什么会出现这2种不同的效果图呢?高手可以帮忙分析一下吗啊,源码不长, 见链接:http://pan.baidu.com/share/link?shareid=2003914465&uk=1913319109

解决方案 »

  1.   

    默认的OnEraseBkgnd即 CButton::OnEraseBkgnd(pDC);是会擦除背景的。
    在Onpaint中是会调用OnEraseBkgnd的,如果你重载OnEraseBkgnd直接返回TRUE,就不会擦除背景了。
      

  2.   

    CButton::OnEraseBkgnd(pDC);
    把背景刷一下,默认是白色的
    也就是Button所在的矩形变成了白色
    DrawItem就是把按钮上面的有用内容画上,它只画了圆角矩形内的部分
    四角的白色没有变如果不刷背景
    也就是按钮的部分是空白
    那该显示什么呢?
    显示它后面的东西,按钮是放在窗体上,那就是显示窗体,也即是后面的小猫图
    这样就是个透明的圆角按钮想象一下
    你拿个白色的刷子在一幅画上画个矩形,
    然后再用彩笔在矩形中间画个图案如果不拿白色刷子画矩形
    直接画图案
    这两种效果是不是和你看到的程序里面的按钮是一样的效果?不是只有四个角变白了,是整个矩形变白了,因为中间的部分画上内容了,看起来只有四角是白色的
      

  3.   

    懂了, onerasebkgnd导致了白色,所以直接返回true即可多谢
      

  4.   

    1. 看看“play.bmp”那个按钮 是 用这个图 画上去的。
    2. 图里每个按钮是矩形的 , 必须通过 mask 把 4个 角 屏蔽掉
    见 void CKbcBmp::Draw
      

  5.   

    m_btnPlay.SetButtonImage("play.bmp",RGB(255,255,255));将play.bmp中的RGB(255,255,255)颜色设为透明下面是关键部分的代码
    void CKbcBmp::Draw(CDC *pDC,int nSeq,int nX,int nY,UINT nMask)
    ...
    // make maskDC
    // mask image made by black and white.
    // black region is we wanna draw , white region is we don't wanna draw.
    maskDC.CreateCompatibleDC(pDC);
    maskBmp.CreateBitmap(SLICEWIDTH,BMPHEIGHT,1,1,NULL);
    pOldmaskDC = maskDC.SelectObject(&maskBmp);
    srcDC.SetBkColor(MASK);
    maskDC.BitBlt(0,0,SLICEWIDTH,BMPHEIGHT,&srcDC,0,0,SRCCOPY);
    ////////////////////////////////////////////////////////////// // modify srcDC image.
    // at this point, mask color of srcDC change to black color.
    srcDC.SetBkColor(BLACK);
    srcDC.SetTextColor(WHITE);
    srcDC.BitBlt(0,0,SLICEWIDTH,BMPHEIGHT,&maskDC,0,0,SRCAND);
    //////////////////////////////////////////////////////////////
      

  6.   

    BOOL CKbcButton::OnEraseBkgnd(CDC* pDC) 
     {
     // do not draw back ground. just return here, so we can see the background.
     // if you have curiosity about this, then remove ON_WM_ERASEBKGND() and test..
     return TRUE; 
     // return CButton::OnEraseBkgnd(pDC);
      // 一般窗口,把它注释掉,是为了防闪;
      //这里把它注释掉,是为了,阻止他自动画背景。
      //MFC 这个函数,或者WINDOWS 的这个消息,确实有点多余,这个函数就不应该做什么。
     }