珞珈山水BBS电脑网络程序人生 → 单文区文章阅读

单文区文章阅读 [返回]
发信人: pcj2008 (☆蓬草江☆), 信区: Programm
标  题: 求VC一问题解答,帮帮我吧,牛人们!
发信站: BBS 珞珈山水站 (Tue Jun  6 23:25:31 2006)

我自己扩展了一个CButton类,之后不停当鼠标移近时会按钮显得非常闪烁!问题好严重啊
!求牛人帮忙!
//PCJbirdButton.h
/************************************************************************/
/*****************************************************************************
******/
/******设计者:☆蓬草江☆    于2006年6月,武汉大学****************************
******/
/******飞思工作室   版权所有  武汉大学计算机学院03级计科1班*******************
******/
/*****************************************************************************
******/
#if !defined(AFX_PCJBIRDBUTTON_H__068B0DC5_909A_48B6_8019_BEE0B2D84B6A__INCLUD
ED_)
#define AFX_PCJBIRDBUTTON_H__068B0DC5_909A_48B6_8019_BEE0B2D84B6A__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
// PCJbirdButton.h : header file
//
//ico图标对齐方式
#define AL_LEFT     0//左对齐
#define AL_TOP      1//上对齐
//按钮类型
#define NormalBtn 0//普通按钮
#define BitmapBtn 1//bitmap位图按钮
#define IconBtn   2//icon按钮
// 鼠标状态
#define ST_MOVEIN    0//鼠标在按钮范围内
#define ST_MOVEOUT   1//鼠标在按钮范围外
#define ST_MOUSEUP   2//鼠标释放状态
#define ST_MOUSEDOWN 3//鼠标按下状态
/////////////////////////////////////////////////////////////////////////////

// PCJbirdButton window

class PCJbirdButton : public CButton
{
// Construction
public:
    PCJbirdButton();

// Attributes
public:       
       UINT m_NomalPic;//正常情况下显示的图片
       UINT m_FocusPic;//鼠标经过按钮时显示的图片
       UINT m_DownPic;//鼠标按下时显示的图片
       UINT m_EnablePic;//按钮实效时显示的图片
       //bool m_IsInRect;//是否在按钮范围内
       UINT CursorID;//焦点鼠标ID
       HCURSOR FocusCursor;//焦点鼠标图标
       UINT btnType;//按钮类型:0 普通按钮,1 bitmap按钮,2 icon按钮
       bool m_bDCStored;//按钮设备背景是否已经被保存
       int m_IconYPos;//ico图标y坐标
       int m_IconXPos;//ico图标x坐标
       int m_IconAlign;//ico图标对齐方式
       int m_DrawState;//鼠标与按钮的位置关系或鼠标的状态
       HICON m_hMouseInIcon;//鼠标经过按钮时的ico图标
       HICON m_hNormalIcon;//正常情况下的ico图标
       HICON m_hDownIcon;//按下时的ico图标
       bool m_bBkTransparent;//按钮背景是否透明
       COLORREF m_clText;//当前文本颜色
       COLORREF m_clMouseDownText;//鼠标按下时文本颜色
       COLORREF m_clActiveText;//按钮激活时的文本颜色
       COLORREF m_clNormalText;//按钮正常情况下的文本颜色
       bool m_bIsEnabled;//按钮是否可用状态
       bool m_bMove;//鼠标是否移动
       bool m_bUseIcon;//是否使用ico图标
       bool m_bIsCreated;//是否已经创建
       bool m_bCapture;//是否捕捉到按钮
       CDC baseDC;//基本设备,用于拷贝按钮背景部分
// Operations
public:

// Overrides
    // ClassWizard generated virtual function overrides
    //{{AFX_VIRTUAL(PCJbirdButton)
    public:
    virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct);
    protected:
    virtual void PreSubclassWindow();
    //}}AFX_VIRTUAL

// Implementation
public:
    void SetNormalTextColor(COLORREF color);
    void SetMouseDownTextColor(COLORREF color);
    void SetIconYPos(int y);
    void SetIconXPos(int x);
    void SetAlign(int nAlign);
    void SetActiveTextColor(COLORREF color);
    void SetIcon(HICON  hNormal,HICON hMouseIn);
    void SetIcon(UINT  nNormal,UINT nMouseIn);
    void DrawText();
    void DrawIcon(HICON hIcon,BOOL bDisabled=FALSE);
    void DrawIcon();
    BOOL SetCursor(UINT nCursorID);
    void SetBitmapIDS(UINT Normalbmp, UINT Focusbmp, UINT Downbmp,UINT Disable
dbmp);
    void DrawBitmap(UINT bmpID);
    void DrawBitmap();
    void SetButtonType(UINT btntype);
    void Draw();
    void Refresh();
    void SetBkMode(bool bTransparent);
    virtual ~PCJbirdButton();

    // Generated message map functions
protected:
    //{{AFX_MSG(PCJbirdButton)
    afx_msg BOOL OnEraseBkgnd(CDC* pDC);
    afx_msg void onMouseMove(UINT nFlags, CPoint point);
    afx_msg void OnTimer(UINT nIDEvent);
    afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
    afx_msg void OnLButtonUp(UINT nFlags, CPoint point);
    afx_msg BOOL OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message);
    afx_msg void OnKillFocus(CWnd* pNewWnd);
    //}}AFX_MSG

    DECLARE_MESSAGE_MAP()
};

/////////////////////////////////////////////////////////////////////////////


//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before
 the previous line.

#endif // !defined(AFX_PCJBIRDBUTTON_H__068B0DC5_909A_48B6_8019_BEE0B2D84B6A__
INCLUDED_)




//PCJbirdButton.cpp
/****************************************************************************/

// PCJbirdButton.cpp : implementation file
//

#include "stdafx.h"
#include "PCJbirdButton.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////

// PCJbirdButton

PCJbirdButton::PCJbirdButton()
{
    m_bIsCreated=false;
    btnType=NormalBtn;
    m_bBkTransparent=true;
    m_bIsEnabled=true;
    m_bDCStored=false;
    m_bMove=false;
    m_bUseIcon=false;
    m_bCapture = false;
    m_hMouseInIcon=NULL;
    m_hNormalIcon=NULL;
    m_IconAlign=AL_LEFT;
    m_DrawState=ST_MOVEOUT;
    m_IconYPos=5;
    m_IconXPos=5;
    m_clNormalText=::GetSysColor(COLOR_WINDOWTEXT);
    m_clActiveText=::GetSysColor(COLOR_HIGHLIGHT);
    m_clMouseDownText=::GetSysColor(COLOR_WINDOWTEXT);
    m_clText=m_clNormalText;
    m_NomalPic=-1;
    m_FocusPic=-1;
    m_DownPic=-1;
    m_EnablePic=-1;
}

PCJbirdButton::~PCJbirdButton()
{
}


BEGIN_MESSAGE_MAP(PCJbirdButton, CButton)
    //{{AFX_MSG_MAP(PCJbirdButton)
    ON_WM_ERASEBKGND()
    ON_WM_MOUSEMOVE()
    ON_WM_TIMER()
    ON_WM_LBUTTONDOWN()
    ON_WM_LBUTTONUP()
    ON_WM_SETCURSOR()
    ON_WM_KILLFOCUS()
    //}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////

// PCJbirdButton message handlers

BOOL PCJbirdButton::OnEraseBkgnd(CDC* pDC) //擦除按钮背景
{
    // TODO: Add your message handler code here and/or call default
    // 首先我们要保存设备 DC.
    if(!m_bDCStored)
    {
        CRect  clientRect;
        GetClientRect(&clientRect);
        int cx=clientRect.Width ();
        int cy=clientRect.Height ();
        // Store our orignal DC.
        CBitmap    bitmap;
        baseDC.CreateCompatibleDC (pDC);
        bitmap.CreateCompatibleBitmap (pDC,cx,cy);
        baseDC.SelectObject (&bitmap);
        baseDC.BitBlt (0,0,cx,cy,pDC,0,0,SRCCOPY);
        m_bDCStored=true;
    }
    return true;
}

void PCJbirdButton::onMouseMove(UINT nFlags, CPoint point) 
{
    // TODO: Add your message handler code here and/or call default
    
    CRect rc;
    GetClientRect(&rc);
    if (nFlags & MK_LBUTTON)
        return;
    if(!m_bMove && m_bIsEnabled && rc.PtInRect(point)&&m_bIsCreated==true)
    {    
        m_bMove=true;
        m_DrawState=ST_MOVEIN;
        if (!m_bCapture) 
        {
        SetCapture();
        m_bCapture = true;
        }
        //Draw();
        Invalidate();
        SetTimer(1,10,NULL);
    }
    else
    {
     if(!rc.PtInRect(point))
     {
        if (m_bCapture) 
        {
                ReleaseCapture();
                m_bCapture = false;
        }
     }
    }
    CButton::onMouseMove(nFlags, point);
}

void PCJbirdButton::OnTimer(UINT nIDEvent) 
{
    // TODO: Add your message handler code here and/or call default
    if(nIDEvent!=1)
        return;
    CPoint    point;
    CRect    rect;
    GetWindowRect(&rect);    
    GetCursorPos(&point);
    // 如果鼠标离开按钮且处于可用状态,则重画按钮。
    if (!rect.PtInRect(point) && m_bMove  && m_bIsEnabled)
    {
        KillTimer (1);
        m_DrawState=ST_MOVEOUT;
        m_bMove=false;
        //Draw();
        Invalidate();
        if (m_bCapture) 
        {
                ReleaseCapture();
                m_bCapture = false;
        }
    }
    CButton::OnTimer(nIDEvent);
}

void PCJbirdButton::OnLButtonDown(UINT nFlags, CPoint point) 
{
    // TODO: Add your message handler code here and/or call default
    CRect rc;
    GetClientRect(&rc);
    if (!m_bCapture) {
        SetCapture();
        m_bCapture = true;
    }
if(m_bIsEnabled && rc.PtInRect(point))
{
    //SetCapture();
    m_DrawState=ST_MOUSEDOWN;
    //Draw();
    Invalidate();
}
    CButton::OnLButtonDown(nFlags, point);
}

void PCJbirdButton::OnLButtonUp(UINT nFlags, CPoint point) 
{
    // TODO: Add your message handler code here and/or call default
    if (!m_bCapture) {
        SetCapture();
        m_bCapture = true;
    }
if(m_bIsEnabled)
{
    m_DrawState=ST_MOUSEUP;
    //Draw();
    Invalidate();
}
    CButton::OnLButtonUp(nFlags, point);
}

BOOL PCJbirdButton::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message) 
{
    // TODO: Add your message handler code here and/or call default
    if (FocusCursor != NULL)
    {
        ::SetCursor(FocusCursor);
        return TRUE;
    }    
    return CButton::OnSetCursor(pWnd, nHitTest, message);
}

void PCJbirdButton::SetBkMode(bool bTransparent)//设置按钮背景是否透明
{
      m_bBkTransparent=bTransparent;
}

void PCJbirdButton::Refresh()
{
    CRect    rect;
    GetClientRect(&rect);    
    CClientDC  dc(this);
    if(m_bBkTransparent==false)
        dc.FillRect(&rect,&CBrush(::GetSysColor(COLOR_BTNFACE)) );
    else
        dc.BitBlt (0,0,rect.Width (),rect.Height (),&baseDC,0,0,SRCCOPY);
}

void PCJbirdButton::Draw()
{
  m_bIsCreated=true;
    Refresh();
  switch(btnType)
   {    
   case NormalBtn:
       break;
   case BitmapBtn:
       DrawBitmap();
       break;
   case IconBtn:
         DrawIcon();
         DrawText();
       break;
   default:
       break;
   }
}

void PCJbirdButton::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct) 
{
    // TODO: Add your code to draw the specified item
    if(lpDrawItemStruct->itemState & ODS_DISABLED )
    {
        m_bIsEnabled=false;
        m_DrawState=ST_MOVEOUT;
    }
    if(lpDrawItemStruct->itemState & ODS_SELECTED )
    {
        m_DrawState=ST_MOUSEDOWN;
    }
    if(!(lpDrawItemStruct->itemState & ODS_DISABLED) )
    {
        m_bIsEnabled=true;
    }
    //if(m_bIsCreated==false)
    {        
        Draw();
    }
}

void PCJbirdButton::PreSubclassWindow() //设置按钮初始风格
{
    // TODO: Add your specialized code here and/or call the base class
    SetButtonStyle(GetButtonStyle() | BS_OWNERDRAW);
    CButton::PreSubclassWindow();
}

void PCJbirdButton::SetButtonType(UINT btntype)//设置按钮类型
{
   btnType=btntype;  
}

void PCJbirdButton::DrawBitmap()//选择画的Bitmap位图
{

  if(m_bIsEnabled)
    {
        switch(m_DrawState)
        {
            case ST_MOUSEDOWN:
                {
                    if(m_DownPic!=-1)
                    {
                        DrawBitmap(m_DownPic);
                    
                    }
                    else
                    {
                      if(m_NomalPic!=-1)
                        DrawBitmap(m_NomalPic);
                    }
                }
                break;
            case ST_MOVEIN:
            case ST_MOUSEUP:
                {
                    if(m_FocusPic!=-1)
                    {
                        DrawBitmap(m_FocusPic);
                    
                    }
                    else
                    {
                      if(m_NomalPic!=-1)
                        DrawBitmap(m_NomalPic);
                    }
                }
                break;
            case ST_MOVEOUT:
                {
                   if(m_NomalPic!=-1)    
                    DrawBitmap(m_NomalPic);
                }
                break;
            default:
                break;
        }
    }
    else
    {
        if(m_EnablePic!=-1)
        {
        DrawBitmap(m_EnablePic);
        }
        else
        {
          if(m_NomalPic!=-1)
            DrawBitmap(m_NomalPic);
        }
    }
}

void PCJbirdButton::DrawBitmap(UINT bmpID)//画Bitmap位图按钮
{    /*这段程序还有待改进,图片非常闪烁!*/
    int x,y;
    COLORREF TrancColor,color;
    CRect rcWnd;
 //    CRgn tmpRgn,WndRgn;
    CClientDC dc(this); // device context for painting
    CBitmap bitM;
    bitM.LoadBitmap(bmpID);
    BITMAP bitstruct;
    bitM.GetBitmap(&bitstruct);
    CDC memDC;
    CDC memDCdraw;
     CDC *pDC;
     pDC=this->GetDC();
     this->GetWindowRect(&rcWnd);
  //  CBitmap* pBitmap = new CBitmap;
   // pBitmap->CreateCompatibleBitmap(&baseDC, bitstruct.bmWidth, bitstruct.bm
Height);
    //WndRgn.CreateRectRgn(0,0,rcWnd.Width(),rcWnd.Height());
    memDC.CreateCompatibleDC(&dc);
    memDC.SelectObject(&bitM);
//    memDCdraw.CreateCompatibleDC(&dc);
//    memDCdraw.SelectObject(pBitmap);
//    memDCdraw.BitBlt(0,0,rcWnd.Width(),rcWnd.Height(),&baseDC,0,0,SRCCOPY);

    TrancColor=memDC.GetPixel(0,0);//取出透明色
    for(x=0;x<rcWnd.Width();x++)//bitstruct.bmWidthbitstruct.bmHeight
    {
       for(y=0;y<rcWnd.Height();y++)
       {
         color=memDC.GetPixel(x,y);
         if(color!=TrancColor)
         {
             //tmpRgn.CreateRectRgn(x,y,x+1,y+1);
             //WndRgn.CombineRgn(&WndRgn,&tmpRgn,RGN_XOR);
             //tmpRgn.DeleteObject();
             pDC->SetPixel(x,y,color);
         }
       }
    }
    //memDC.DeleteDC();
    //this->SetWindowRgn(WndRgn,true);
    //CRect rcClient;
    //GetClientRect(&rcClient);
    //dc.BitBlt(0,0,rcClient.Width(),rcClient.Height(),&memDCdraw,0,0,SRCCOPY)
;
}

void PCJbirdButton::SetBitmapIDS(UINT Normalbmp, UINT Focusbmp, UINT Downbmp, 
UINT Disabledbmp)//设置Bitmap
{
    m_NomalPic=Normalbmp;
    m_FocusPic=Focusbmp;
    m_DownPic=Downbmp;
    m_EnablePic=Disabledbmp;
}

BOOL PCJbirdButton::SetCursor(UINT nCursorID)//为按钮选择鼠标形状
{
  HINSTANCE hInstResource;
    // Destroy any previous cursor
    if (FocusCursor != NULL) ::DestroyCursor(FocusCursor);
    FocusCursor = NULL;

    // If we want a cursor
    if (nCursorID != -1)
    {
        hInstResource = AfxFindResourceHandle(MAKEINTRESOURCE(nCursorID),
                                            RT_GROUP_CURSOR);
        // Load icon resource
        FocusCursor = (HCURSOR)::LoadImage(hInstResource/*AfxGetApp()->m_hInst
ance*/, MAKEINTRESOURCE(nCursorID), IMAGE_CURSOR, 0, 0, 0);
        // If something wrong then return FALSE
        if (FocusCursor == NULL) return FALSE;
    }

    return TRUE;
}

void PCJbirdButton::DrawIcon()//选择ico图标
{
  if(m_bIsEnabled)
    {
        switch(m_DrawState)
        {
            case ST_MOVEIN:
            case ST_MOUSEDOWN:
            case ST_MOUSEUP:
                {
                    if(m_hMouseInIcon!=NULL)
                    {
                        DrawIcon(m_hMouseInIcon);
                    
                    }
                }
                break;
            case ST_MOVEOUT:
                {
                    if(m_hNormalIcon!=NULL)
                        DrawIcon(m_hNormalIcon);
                }
                break;
            default:
                break;
        }
    }
    else
    {
        DrawIcon(m_hNormalIcon,TRUE);
    }
}

void PCJbirdButton::DrawIcon(HICON hIcon, BOOL bDisabled)//画ico图标
{
     CRect    clientrect;
    CClientDC    dc(this);
    int cx=::GetSystemMetrics(SM_CXICON);
    int cy=::GetSystemMetrics(SM_CYICON);
    int x,y; // the icon's output position.
    int rectwidth,rectheight;
    GetClientRect(&clientrect);
    rectwidth=clientrect.Width ();
    rectheight=clientrect.Height ();

    CString        itemString;
    GetWindowText(itemString);

    if(itemString!="")
    {
        switch(m_IconAlign)
        {
            case AL_LEFT:
            // draw the icon left.
            {
                x=m_IconXPos;
                y=(rectheight-cy)/2;
                break;
            }
            case AL_TOP:
            {
                x=(rectwidth-cx)/2;
                y=m_IconYPos;
                break;
            }
            default:
                break;
        }
    }
    else
    // If there is not any text,we'll center the icon.
    {
        x=(rectwidth-cx)/2;
        y=(rectheight-cy)/2;
    }
    // Draw the icon,as if it is pressed
    if(m_DrawState==ST_MOUSEDOWN)
    {
        x++;
        y++;
    }
    // Draw the icon.
    if(!bDisabled)
    {
        dc.DrawIcon (x,y,hIcon);
    }
    else
    {
        dc.DrawState(CPoint(x,y),CSize(32,32),hIcon,DST_ICON | DSS_DISABLED,(H
BRUSH)NULL);
    }
}

void PCJbirdButton::DrawText()//画按钮文本
{
      CString        itemString;
    CRect  clientRect;
    CClientDC  dc(this);
    GetClientRect(&clientRect);
    GetWindowText(itemString);
    // Draw text depend on different state.
    if(itemString)
    {
        // First Get some necessary infomation.
        CSize size=dc.GetTextExtent (itemString);
        int rectwidth=clientRect.Width();
        int rectheight=clientRect.Height();
        int textwidth=size.cx ;
        int textheight=size.cy ;
        int iconwidth=::GetSystemMetrics(SM_CXICON);
        int iconheight=::GetSystemMetrics(SM_CYICON);
        int x,y; // the position of the text.
        // Next caculate the text output position.
        switch(m_IconAlign)
        {
            case AL_LEFT:
            {
                if(m_bUseIcon==true)
                {
                    x=m_IconXPos+iconwidth+
                        (rectwidth-textwidth-m_IconXPos-iconwidth)/2;
                }
                else
                {
                    x=(rectwidth-textwidth)/2;
                }
                y=(rectheight-textheight)/2;
                break;
            }
            case AL_TOP:
            {
                if(m_bUseIcon==true)
                {
                    y=m_IconYPos+iconheight+
                        (rectheight-textheight-m_IconYPos-iconheight)/2;
                }
                else
                {
                    y=(rectheight-textheight)/2;
                }
                x=(rectwidth-textwidth)/2;
                break;
            }
            default:
                break;
        }
        // Should we draw the text as if it is disabled?
        if(!m_bIsEnabled)
        {
            // .. Yes.Now draw the text disabled.
            dc.DrawState(CPoint(x,y),CSize(0,0),itemString,DST_TEXT | DSS_DISA
BLED,FALSE,0,(HBRUSH)NULL);
        }
        else
        {
            switch(m_DrawState)
            {
                case ST_MOVEIN:
                {
                    m_clText=m_clActiveText;
                }
                    break;
                case ST_MOVEOUT:
                {
                    m_clText=m_clNormalText;
                }
                    break;
                case ST_MOUSEUP:
                {
                    m_clText=m_clActiveText;
                }
                    break;
                case ST_MOUSEDOWN:
                {
                    m_clText=m_clNormalText;
                }
                    break;
                default:
                    break;
            }
            // Draw the text,as if it is pressed
            if(m_DrawState==ST_MOUSEDOWN)
            {
                x++;
                y++;
            }
            dc.SetTextColor(m_clText);
            dc.SetBkMode(TRANSPARENT);
            dc.TextOut (x,y,itemString);
        }
    }
}

void PCJbirdButton::SetIcon(UINT nNormal, UINT nMouseIn)
{
    m_hNormalIcon=AfxGetApp()->LoadIcon(nNormal);
    m_hMouseInIcon=AfxGetApp()->LoadIcon(nMouseIn);
    m_bUseIcon=true;
}

void PCJbirdButton::SetIcon(HICON hNormal, HICON hMouseIn)
{
    m_hNormalIcon=hNormal;
    m_hMouseInIcon=hMouseIn;
    m_bUseIcon=true;
}

void PCJbirdButton::SetActiveTextColor(COLORREF color)
{
    m_clActiveText=color;
    Draw();
}

void PCJbirdButton::SetAlign(int nAlign)
{
   m_IconAlign=nAlign;
   Draw();
}

void PCJbirdButton::SetIconXPos(int x)
{
  m_IconXPos=x;
  Draw();
}

void PCJbirdButton::SetIconYPos(int y)
{
  m_IconYPos=y;
  Draw();
}

void PCJbirdButton::SetMouseDownTextColor(COLORREF color)
{
  m_clMouseDownText=color;
  Draw();
}

void PCJbirdButton::SetNormalTextColor(COLORREF color)
{
    m_clNormalText=color;
    Draw(); 
}

void PCJbirdButton::OnKillFocus(CWnd* pNewWnd) 
{
    CButton::OnKillFocus(pNewWnd);
    m_DrawState=ST_MOVEOUT;
    //Invalidate();
    //ReleaseCapture();
    // TODO: Add your message handler code here    
}

--
我本是那漂泊在万里长江中的蓬草,随风远飘,万里独行,不知江月待何人,但见长江送流水。

※ 来源:·珞珈山水BBS站 http://bbs.whu.edu.cn·[FROM: 222.20.236.*]
[返回单文区目录]

武汉大学BBS 珞珈山水站 All rights reserved.
wForum , 页面执行时间:37.466毫秒