众所周知,CBitmapButton类提供了一定的自绘Button的能力,即LoadBitmaps()函数,但没有鼠标进入而改变状态的机制.以下是我的代码(不多),有错误,希望有人能COPY进VC后给予指正.*****一些数据定义未说明*****
***这是一个接口类,用于对按钮控制变量中来设置自绘的功能***
void CMyButton::GetResId(UINT id1,UINT id2,UINT id3)
{//类似LoadBitmaps()得到资源
m_Id1=id1;
m_Id2=id2;
m_Id3=id3;
}
void CMyButton::OnPaint() 
{//DC重绘
CPaintDC dc(this); // device context for painting
//经过分析 鼠标未进入前state为0,进入state为1,按下为2,起来为0,离开为0
//所以需要3个资源
if(state==0)
DrawBmp(&dc,m_Id1);
else if(state==1)
DrawBmp(&dc,m_Id2);
else if(state==2)
DrawBmp(&dc,m_Id3);
}
void CMyButton::OnMouseMove(UINT nFlags, CPoint point) 
{//对鼠标消息处理
if(!b_InRect||GetCapture()!=this){//进入
b_InRect=true;//进入标志
SetCapture();//捕获
state=1; //修改状态
Invalidate();//重绘
}
else{
if(!m_ButRect.PtInRect(point)){//离开
b_InRect=false; //清除进入标志
ReleaseCapture();//释放
state=0; //修改状态
Invalidate(); //重绘
}
}
CButton::OnMouseMove(nFlags, point);
}
void CMyButton::OnDrawItem(int nIDCtl, LPDRAWITEMSTRUCT lpDrawItemStruct) 
{//得到按钮尺寸
m_ButRect = lpDrawItemStruct->rcItem; //获取按钮尺寸
CButton::OnDrawItem(nIDCtl, lpDrawItemStruct);
}
void CMyButton::DrawBmpState(CPaintDC *pDC, HBITMAP hBitmap)
//PDC双缓存绘图,代码略
void CMyButton::DrawBmp(CPaintDC *dc, UINT id)
{//绘图,以ID为参数
CBitmap pb;
HBITMAP hbmp;
pb.LoadBitmap(id);//加载资源
hbmp=(HBITMAP)pb;//转换
DrawBmpState(dc,hbmp);//绘图
}
void CMyButton::OnLButtonDown(UINT nFlags, CPoint point) 
{//处理鼠标按下
SetCapture();
state=2;
Invalidate();
// CButton::OnLButtonDown(nFlags, point);
}
void CMyButton::OnLButtonUp(UINT nFlags, CPoint point) 
{//处理鼠标放开
state=0;
Invalidate();
CButton::OnLButtonUp(nFlags, point);
}
其中在OnLButtonDown注释掉了基类的OnLButtonDown,测试过,如果不去掉,则当按下时会出错.
但如果注释掉的话...则鼠标失去了按下发送的消息作用,从而失去了按钮该有的功能.
所以,这2者不知道如何处理.也不知道是否一些界面中的响应MOUSEMOVE是不是这样处理的.
第一次提问,请大家赐教,谢谢!

解决方案 »

  1.   

    忘记了,如果有人愿意COPY进VC的话,我还是把双缓绘图贴出来
    void CMyButton::DrawBmpState(CPaintDC *pDC, HBITMAP hBitmap)
    {
        CRect rect;
        GetClientRect(&rect);
        CDC MemDC,mdc;
        mdc.CreateCompatibleDC(NULL);
        MemDC.CreateCompatibleDC(NULL);
        CBitmap MemBitmap;
        MemBitmap.CreateCompatibleBitmap(pDC,rect.Width(),rect.Height());
        MemDC.SelectObject(&MemBitmap);
        MemDC.FillSolidRect(0,0,rect.Width(),rect.Height(),RGB(0,0,0));  
        mdc.SelectObject(hBitmap);
        MemDC.BitBlt(0,0,rect.Width(),rect.Height(),&mdc,0,0,SRCCOPY);  
        pDC->BitBlt(0,0,rect.Width(),rect.Height(),&MemDC,0,0,SRCCOPY);
        MemBitmap.DeleteObject();
        MemDC.DeleteDC();
    }
      

  2.   

    不缺啊,这个类中只差定义一些成员变量.自己也另外建立一个测试的DLG类就可以了.其他的都是WIZARD自己生成的
    不过,这里可以直接看出问题吗?
      

  3.   

    既然在OnLButtonDown里面要SetCapture,为何还要在OnMouseMove里面也SetCapture呢?只切换一个状态标志不行吗?这个用法很奇怪,不知要实现什么效果。
      

  4.   

    ls,这个,我最初觉得有问题的时候感觉是捕获鼠标哪出了问题,一时懒得去认真细想各个状态.于是改了几个捕获..
    那个应该不要SetCapture().谢谢你耐心看完.帮找到问题分都给你
      

  5.   

    补:是在OnLButtonDown不要SetCapture
      

  6.   

    要达到的效果比CBitmapButton多一个当鼠标进入时会重绘.至于禁用,输入焦点没考虑
      

  7.   

    就把OnMouseMove里面的SetCapture和ReleaseCapture两个语句注释掉就可以了
      

  8.   

    哦,不对,应该使用WM_MOUSELEAVE消息,这个消息不会主动发生,要在OnMouseMove里面用TrackMouseEvent来告诉窗口你需要这个消息。
      

  9.   

    不好意思,我不是开发人员,掌握的不多,对TrackMouseEvent不会用.
    不知道究竟怎么改~请详细点说明~
      

  10.   

    不是开发人员怎么跟你解释,我的解释跟MSDN一样。
      

  11.   

    网上有自绘按钮的代码,太长了这里贴不下,你搜一下CSkinBtn
      

  12.   

    jameshooo还要说什么吗?没的话结贴了~只能给你30分
      

  13.   

    CSkinBtn:
    http://blog.chinaunix.net/u/32550/showart.php?id=331078