如何在按钮上显示位图,并且按钮的大小是否要与位图的大小一致?

解决方案 »

  1.   

    我们可以可由CButton派生出新的基类,并对此进行改造。重载DRAWITEM函数,将位图贴在按钮上,可形成自己风格的按钮。
    如有兴趣我们共同研究一下。
    void CFlatButton::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct) 
    {
    // TODO: Add your code to draw the specified item
    CDC *pDC = CDC::FromHandle(lpDrawItemStruct->hDC);
    CRect m_rcItem;
    m_rcItem.CopyRect(&lpDrawItemStruct->rcItem);
    m_nState =  lpDrawItemStruct->itemState; BOOL bIsPressed = (lpDrawItemStruct->itemState & ODS_SELECTED);
    BOOL bIsFocused = (lpDrawItemStruct->itemState & ODS_FOCUS);
    BOOL bIsDisabled = (lpDrawItemStruct->itemState & ODS_DISABLED);

    pDC->SetBkMode(TRANSPARENT);
    if(bIsPressed)
    pDC->DrawEdge(m_rcItem,EDGE_SUNKEN,BF_RECT);
    else
    if(m_bMouseOnButton)
    pDC->DrawEdge(m_rcItem,EDGE_RAISED,BF_RECT); m_rcItem.DeflateRect(1,1); CBrush br(m_bMouseOnButton?m_crHoveBack:m_crBack);
    pDC->FillRect(&m_rcItem,&br);
    DeleteObject(br); if(m_bShowCaption)
    {
    if(m_bMouseOnButton)
    pDC->SetTextColor(m_crActFore);
    else
    pDC->SetTextColor(m_crFont);

    if(bIsDisabled)
    pDC->SetTextColor(m_crGray);
    else
    pDC->SetTextColor(m_crFont);
    if(bIsPressed)
    m_rcItem.OffsetRect(1,1); GetWindowText(m_strCaption);
    CRect rcToSubtract;
    rcToSubtract.CopyRect(CRect(m_rcItem.left,
    m_rcItem.top,
    m_rcItem.left+2*IconLeftMargin+m_sizeIcon.cx,
    m_rcItem.bottom));
    m_rcItem.SubtractRect(m_rcItem,rcToSubtract); pDC->DrawText(m_strCaption,m_rcItem,DT_CENTER|DT_SINGLELINE|DT_VCENTER);
    }
    DrawIcon(pDC); ReleaseDC(pDC); // How make the code has been executed when Mouse Cursor move in ;
    // exclouding Mouse button up;}
      

  2.   

    给你提高一个扩展类,功能很强大!
    // SXButton.cpp : implementation file
    // Michael Santoro - [email protected]
    //
    // Revision History
    // ================
    // 08-30-97 msantoro Origional Code
    // 11-09-97 msantoro Added bitmap support
    //
    /////////////////////////////////////////////////////////////////////////////// CSXButton window#ifndef _SXBUTTON_H
    #define _SXBUTTON_H#define SXBUTTON_CENTER -1class CSXButton : public CButton
    {
    // Construction
    public:
    CSXButton();// Attributes
    private:
    // Positioning
    BOOL m_bUseOffset;
    CPoint m_pointImage;
    CPoint m_pointText;
    int m_nImageOffsetFromBorder;
    int m_nTextOffsetFromImage; // Image
    HICON m_hIcon;
    HBITMAP m_hBitmap;
    HBITMAP m_hBitmapDisabled;
    int m_nImageWidth, m_nImageHeight; // Color Tab
    char m_bColorTab;
    COLORREF m_crColorTab; // State
    BOOL m_bDefault;
    UINT m_nOldAction;
    UINT m_nOldState;
    // Operations
    public:
    // Positioning
    int SetImageOffset( int nPixels ); 
    int SetTextOffset( int nPixels );
    CPoint SetImagePos( CPoint p );
    CPoint SetTextPos( CPoint p ); // Image
    BOOL SetIcon( UINT nID, int nWidth, int nHeight );
    BOOL SetBitmap( UINT nID, int nWidth, int nHeight );
    BOOL SetMaskedBitmap( UINT nID, int nWidth, int nHeight, COLORREF crTransparentMask );
    BOOL HasImage() { return (BOOL)(( m_hIcon != 0)  | (m_hBitmap != 0 )); } // Color Tab
    void SetColorTab(COLORREF crTab); // State
    BOOL SetDefaultButton( BOOL bState = TRUE );private:
    BOOL SetBitmapCommon( UINT nID, int nWidth, int nHeight, COLORREF crTransparentMask, BOOL bUseMask );
    void CheckPointForCentering( CPoint &p, int nWidth, int nHeight );
    void Redraw();// Overrides
    // ClassWizard generated virtual function overrides
    //{{AFX_VIRTUAL(CSXButton)
    public:
    virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct);
    //}}AFX_VIRTUAL// Implementation
    public:
    virtual ~CSXButton(); // Generated message map functions
    protected:
    //{{AFX_MSG(CSXButton)
    afx_msg LRESULT OnGetText(WPARAM wParam, LPARAM lParam);
    //}}AFX_MSG DECLARE_MESSAGE_MAP()
    };#endif
    /////////////////////////////////////////////////////////////////////////////
      

  3.   

    // SXButton.cpp : implementation file
    // Michael Santoro - [email protected]
    //
    ///////////////////////////////////////////////////////////////#include "stdafx.h"
    #include "SXButton.h" // Access local header#ifdef _DEBUG
    #define new DEBUG_NEW
    #undef THIS_FILE
    static char THIS_FILE[] = __FILE__;
    #endif/////////////////////////////////////////////////////////////////////////////
    // CSXButtonCSXButton::CSXButton()
    {
    m_bColorTab = FALSE; m_hIcon = 0;
    m_hBitmap = 0; m_bDefault = FALSE;
    m_nOldState = 0;
    m_nOldAction = 0; m_nImageOffsetFromBorder = 4;
    m_nTextOffsetFromImage = 8;
    m_bUseOffset = TRUE;
    }CSXButton::~CSXButton()
    {
    }
    BEGIN_MESSAGE_MAP(CSXButton, CButton)
    //{{AFX_MSG_MAP(CSXButton)
    //}}AFX_MSG_MAP
    END_MESSAGE_MAP()
    inline void CSXButton::Redraw()
    {
    if( m_hWnd != NULL )
    Invalidate();
    }//
    // Various Attribute setting functions
    //// Image functions
    BOOL CSXButton::SetIcon( UINT nID, int nWidth, int nHeight )
    {
    m_hIcon = (HICON)::LoadImage(AfxGetApp()->m_hInstance, MAKEINTRESOURCE(nID), IMAGE_ICON, nWidth, nHeight, 0); if( m_hIcon == 0 )
    return FALSE; m_nImageWidth = nWidth;
    m_nImageHeight = nHeight; m_hBitmap = 0; Redraw(); return TRUE;
    }BOOL CSXButton::SetBitmap( UINT nID, int nWidth, int nHeight )
    {
    return SetBitmapCommon( nID, nWidth, nHeight, 0, FALSE /* no mask */ );
    }BOOL CSXButton::SetMaskedBitmap( UINT nID, int nWidth, int nHeight, COLORREF crTransparentMask )
    {
    return SetBitmapCommon( nID, nWidth, nHeight, crTransparentMask, TRUE /* mask */ );
    }BOOL CSXButton::SetBitmapCommon( UINT nID, int nWidth, int nHeight, COLORREF crTransparentMask, BOOL bUseMask )
    {
    // If it is not a masked bitmap, just go through the
    // motions as if it was, but set then number of color mappings to 0
    COLORMAP mapColor;
    mapColor.from = crTransparentMask;
    mapColor.to  = ::GetSysColor( COLOR_BTNFACE );
    HBITMAP bmTemp = (HBITMAP)::CreateMappedBitmap(AfxGetApp()->m_hInstance, nID, IMAGE_BITMAP, &mapColor, bUseMask ? 1 : 0 );
    m_hBitmap = (HBITMAP)::CopyImage( bmTemp, IMAGE_BITMAP, nWidth, nHeight, 0 ); // Create disabled bitmap.  We need to make the masked area white so
    // it will appear transparent when the bitmap is rendered as an
    // 'embossed' (disabled) image in DrawItem() below.  Since DrawState 
    // converts the image to monochrome, white is transparent, black is 
    // graphics data.
    mapColor.to  = RGB( 255, 255, 255 );
    bmTemp = (HBITMAP)::CreateMappedBitmap(AfxGetApp()->m_hInstance, nID, IMAGE_BITMAP, &mapColor, bUseMask ? 1 : 0 );
    m_hBitmapDisabled = (HBITMAP)::CopyImage( bmTemp, IMAGE_BITMAP, nWidth, nHeight, 0 );
      
    if( m_hBitmap == 0 || m_hBitmapDisabled == 0 )
    return FALSE;  m_nImageWidth = nWidth;
    m_nImageHeight = nHeight; m_hIcon = 0; Redraw(); return TRUE;
    }void CSXButton::SetColorTab(COLORREF crTab)
    {
    m_bColorTab = TRUE;
    m_crColorTab = crTab; Redraw();
    }BOOL CSXButton::SetDefaultButton( BOOL bState )
    {
    CDialog *pDialog = (CDialog *)GetOwner();
    ASSERT( pDialog->IsKindOf( RUNTIME_CLASS( CDialog ) ) ); pDialog->SetDefID( GetDlgCtrlID() ); BOOL bPrevious = m_bDefault;
    m_bDefault = bState; Redraw(); // Return previous state
    return bPrevious;
    }// Positioning Functions
    int CSXButton::SetImageOffset( int nPixels )
    {
    int nPrevious = m_nImageOffsetFromBorder; m_bUseOffset = TRUE; 
    m_nImageOffsetFromBorder = nPixels;  Redraw(); return nPrevious;
    }int CSXButton::SetTextOffset( int nPixels ) 

    int nPrevious = m_nTextOffsetFromImage; m_bUseOffset = TRUE; 
    m_nTextOffsetFromImage = nPixels;  Redraw(); return nPrevious;
    }CPoint CSXButton::SetImagePos( CPoint p ) 

    CPoint pointPrevious = m_pointImage; m_bUseOffset = FALSE; 
    m_pointImage = p;  Redraw(); return pointPrevious;
    }
    CPoint CSXButton::SetTextPos( CPoint p ) 

    CPoint pointPrevious = m_pointText; m_bUseOffset = FALSE; 
    m_pointText = p;  Redraw(); return pointPrevious;
    }
      

  4.   

    解上贴!
    // Centering a point helper function
    void CSXButton::CheckPointForCentering( CPoint &p, int nWidth, int nHeight )
    {
    CRect rectControl;
    GetClientRect( rectControl ); if( p.x == SXBUTTON_CENTER )
    p.x = ( ( rectControl.Width() - nWidth ) >> 1 );
    if( p.y == SXBUTTON_CENTER )
    p.y = ( ( rectControl.Height() - nHeight ) >> 1 );
    }
    //
    // Owner Draw function, the grand-daddy
    //
    void CSXButton::DrawItem(LPDRAWITEMSTRUCT lpDIS) 
    {
    CDC* pDC = CDC::FromHandle(lpDIS->hDC); CRect rectControl( lpDIS->rcItem );

    UINT nOffset = 0; // For position adjustment of a pushed button
    UINT nFrameStyle=0;
    BOOL bDRAWFOCUSONLY = FALSE; // Optimize a bit
    int nStateFlag; // Normal or Disabled
    HBITMAP hBitmapToDraw; // Normal or Disabled bitmap (not used if uses icon)

    UINT nNewState = lpDIS->itemState;
    UINT nNewAction = lpDIS->itemAction;

    // Find out what state the control and set some drawing flags 
    // according to the state.
    if ( nNewState & ODS_SELECTED)
    {
    nFrameStyle = DFCS_PUSHED;
    nOffset += 1;
    } if( nNewState & ODS_DISABLED )
    {
    nStateFlag = DSS_DISABLED;
    hBitmapToDraw = m_hBitmapDisabled;
    }
    else
    {
    nStateFlag = DSS_NORMAL;
    hBitmapToDraw = m_hBitmap;
    } // If only the focus is changing, don't redraw the whole control
    if (nNewAction == ODA_FOCUS )
    bDRAWFOCUSONLY = TRUE; // If this is the defualt button, deflate the control so everything 
    // we do below (icon, text, focus ) is adjusted properly
    if( m_bDefault )
    rectControl.DeflateRect( 1, 1 ); if( !bDRAWFOCUSONLY )
    {
    //
    // Draw 'default button' rectangle
    //
    if( m_bDefault ) // Can't use ODS_DEFAULT w/owner draw!!
    {
    CPen *pOldPen = (CPen*)pDC->SelectStockObject(BLACK_PEN);

    pDC->Rectangle( &lpDIS->rcItem ); // don't use deflated rectangle
    pDC->SelectObject( pOldPen );
    } //
    // Draw button frame
    //
    pDC->DrawFrameControl(&rectControl, DFC_BUTTON, DFCS_BUTTONPUSH | nFrameStyle); //
    // Draw color tab
    //
    if (m_bColorTab)
    {
    CPen penTab; 

    #define COLORTABSIZE 8
    if( penTab.CreatePen( PS_SOLID, 1, m_crColorTab) )
    {
    CPen* pOldPen = pDC->SelectObject( &penTab );

    int nXOffset = rectControl.left+1 + nOffset;
    int nYOffset = rectControl.top+1 + nOffset;
    for (UINT nStep = 0; nStep < COLORTABSIZE; nStep++)
    {
    pDC->MoveTo( nXOffset, nYOffset + nStep );
    pDC->LineTo( nXOffset + (COLORTABSIZE-nStep)-1, nYOffset + nStep );
    }
            
    pDC->SelectObject( pOldPen );
    }
    } // Get control text
    CString strTitle;
    this->GetWindowText(strTitle); //
    // Draw Image
    //
    if( HasImage() )
    {
    CPoint pt; if( m_bUseOffset )
    {
    pt.x = strTitle.IsEmpty() ? SXBUTTON_CENTER : rectControl.left + m_nImageOffsetFromBorder;
    pt.y = SXBUTTON_CENTER;
    }
    else
    pt = m_pointImage; CheckPointForCentering( pt, m_nImageWidth, m_nImageHeight );

    pt.Offset( nOffset, nOffset ); if( m_hIcon )
    pDC->DrawState( pt, CSize(m_nImageWidth, m_nImageHeight), (HICON)m_hIcon, DST_ICON | nStateFlag, (CBrush *)NULL );
    else if( m_hBitmap )
    pDC->DrawState( pt, CSize(m_nImageWidth, m_nImageHeight), (HBITMAP)hBitmapToDraw, DST_BITMAP | nStateFlag );
    } //
    // Draw Text
    //
    if ( !strTitle.IsEmpty() )
    {
    CPoint pt;
    CSize sizeText = pDC->GetTextExtent(strTitle); if( m_bUseOffset )
    {
    pt.x = !HasImage() ? SXBUTTON_CENTER : m_nImageWidth + m_nTextOffsetFromImage + m_nImageOffsetFromBorder;
    pt.y = SXBUTTON_CENTER; 
    }
    else
    pt = m_pointText; // If we are centering the text vertically, it looks best of we
    // center based on the height of the text, then move it up 1 more pixel
    int nOffsetFixY = pt.y == SXBUTTON_CENTER ? -1 : 0; CheckPointForCentering( pt, sizeText.cx, sizeText.cy ); pt.Offset( nOffset, nOffset + nOffsetFixY ); pDC->DrawState( pt, CSize(0,0), strTitle, DST_PREFIXTEXT|nStateFlag, TRUE, 0, (CBrush*)NULL );
    } } // End !focus only //
    // Draw focus rectange
    //
    if( !( nNewState & ODS_DISABLED ) ) // Make sure it's not disabled
    {
    // Redraw the focus if:
    // 1. There is a change in focus state 
    // OR 2. The entire control was just redrawn and Focus is set
    if( ( nNewState && ODS_FOCUS ) ^ ( m_nOldState && ODS_FOCUS ) ||
    ( !bDRAWFOCUSONLY && ( nNewState & ODS_FOCUS ) ) )
    {
    #define FOCUSOFFSET 3
    CRect rect( rectControl ); // As control gets smaller, decrease focus size
    int nDeflate = min( FOCUSOFFSET,
    min( rect.Width(), rect.Height() ) >> 2 );
    rect.DeflateRect( nDeflate, nDeflate);
    pDC->DrawFocusRect(&rect);
    }
    } m_nOldAction = nNewAction;
    m_nOldState = nNewState;
    }