CBitmapSlider扩展

来源:互联网 发布:js中的date对象 编辑:程序博客网 时间:2024/05/21 17:51

http://www.codeproject.com/Articles/4850/CBitmapSlider
试用了很多slider 发现这个还是最稳定 最给力的

相对于作者给出的代码 做了如下修改:
1:添加滚轮事件
2:添加EnableWindow的函数:EnableEx

代码如下:

#ifndef _MEMDC_H_#define _MEMDC_H_//////////////////////////////////////////////////// CMemDC_flicker_free - memory DC//// Author: Keith Rule// Email:  keithr@europa.com// Copyright 1996-2002, Keith Rule//// You may freely use or modify this code provided this// Copyright is included in all derived versions.//// History - 10/3/97 Fixed scrolling bug.//                   Added print support. - KR////           11/3/99 Fixed most common complaint. Added//                   background color fill. - KR////           11/3/99 Added support for mapping modes other than//                   MM_TEXT as suggested by Lee Sang Hun. - KR////           02/11/02 Added support for CScrollView as supplied//                    by Gary Kirkham. - KR//// This class implements a memory Device Context which allows// flicker free drawing.////// I made a few changes to support transparency effect //// Line 44 : Added bBg parameter.// Line 83 ~ 87 : If bBg is TRUE, copy background.//class CMemDC_flicker_free : public CDC {private:        CBitmap     m_bitmap;       // Offscreen bitmap    CBitmap*    m_oldBitmap;    // bitmap originally found in CMemDC_flicker_free    CDC*        m_pDC;          // Saves CDC passed in constructor    CRect       m_rect;         // Rectangle of drawing area.    BOOL        m_bMemDC;       // TRUE if CDC really is a Memory DC.public:    CMemDC_flicker_free(CDC* pDC, const CRect* pRect = NULL, BOOL bBg = FALSE) : CDC()    {        ASSERT(pDC != NULL);         // Some initialization        m_pDC = pDC;        m_oldBitmap = NULL;        m_bMemDC = !pDC->IsPrinting();        // Get the rectangle to draw        if (pRect == NULL) {            pDC->GetClipBox(&m_rect);        } else {            m_rect = *pRect;        }        if (m_bMemDC) {            // Create a Memory DC            CreateCompatibleDC(pDC);            pDC->LPtoDP(&m_rect);            m_bitmap.CreateCompatibleBitmap(pDC, m_rect.Width(), m_rect.Height());            m_oldBitmap = SelectObject(&m_bitmap);            SetMapMode(pDC->GetMapMode());            SetWindowExt(pDC->GetWindowExt());            SetViewportExt(pDC->GetViewportExt());            pDC->DPtoLP(&m_rect);            SetWindowOrg(m_rect.left, m_rect.top);        } else {            // Make a copy of the relevent parts of the current DC for printing            m_bPrinting = pDC->m_bPrinting;            m_hDC       = pDC->m_hDC;            m_hAttribDC = pDC->m_hAttribDC;        }        // Fill background         if( bBg )            BitBlt(m_rect.left, m_rect.top, m_rect.Width(), m_rect.Height(),                m_pDC, m_rect.left, m_rect.top, SRCCOPY);        else            FillSolidRect(m_rect, pDC->GetBkColor());    }    ~CMemDC_flicker_free()     {        if (m_bMemDC) {            // Copy the offscreen bitmap onto the screen.            m_pDC->BitBlt(m_rect.left, m_rect.top, m_rect.Width(), m_rect.Height(),                this, m_rect.left, m_rect.top, SRCCOPY);                        //Swap back the original bitmap.            SelectObject(m_oldBitmap);              } else {            // All we need to do is replace the DC with an illegal value,            // this keeps us from accidently deleting the handles associated with            // the CDC that was passed to the constructor.                      m_hDC = m_hAttribDC = NULL;        }       }    // Allow usage as a pointer     CMemDC_flicker_free* operator->()     {        return this;    }       // Allow usage as a pointer     operator CMemDC_flicker_free*()     {        return this;    }};#endif
#if !defined(AFX_BITMAPSLIDER_H__BED36788_B60C_4C9E_AC56_FE430B93A0FD__INCLUDED_)#define AFX_BITMAPSLIDER_H__BED36788_B60C_4C9E_AC56_FE430B93A0FD__INCLUDED_#if _MSC_VER > 1000#pragma once#endif // _MSC_VER > 1000// BitmapSlider.h : header file/////////////////////////////////////////////////////////////////////////////////// CBitmapSlider v1.5//// It's free for everywhere - 16/September/2003 - Joon-ho Ryu///////////////////////////////////////////////////////////////////////////////#include "memdc.h" // "Flicker Free Drawing In MFC" by Keith Rule#define WM_BITMAPSLIDER_MOVING      WM_USER + 9425#define WM_BITMAPSLIDER_MOVED       WM_USER + 9426class CBitmapSlider : public CStatic{// Constructionpublic:    CBitmapSlider();// Attributespublic:// Operationspublic:// Overrides    // ClassWizard generated virtual function overrides    //{{AFX_VIRTUAL(CBitmapSlider)    //}}AFX_VIRTUAL// Implementationpublic:    void GetRange( int &nMin, int &nMax ) { nMin = m_nMin; nMax = m_nMax; };    int GetRangeMax() { return m_nMax; };    int GetRangeMin() { return m_nMin; };    int GetPos() { return m_nPos; };    void SetRange( int nMin, int nMax, BOOL bRedraw=FALSE );    void SetRangeMin(int nMin, BOOL bRedraw = FALSE);    void SetRangeMax( int nMax, BOOL bRedraw = FALSE );    void SetPos( int nPos );    int SetPageSize( int nSize );    BOOL SetBitmapChannel(        UINT nChannelID, UINT nActiveID=NULL, BOOL bTransparent=FALSE,        COLORREF clrpTransColor=0xFF000000, int iTransPixelX=0, int iTransPixelY=0 );    BOOL SetBitmapThumb(        UINT nThumbID, UINT nActiveID=NULL, BOOL bTransparent=FALSE,        COLORREF clrpTransColor=0xFF000000, int iTransPixelX=0, int iTransPixelY=0 );    void SetMargin( int nLeft, int nTop, int nRight, int nBottom );    void SetMarginTop( int nMargin ) { m_nMarginTop = nMargin; };    void SetMarginLeft( int nMargin ) { m_nMarginLeft = nMargin; };    void SetMarginRight( int nMargin ) { m_nMarginRight = nMargin; };    void SetMarginBottom( int nMargin ) { m_nMarginBottom = nMargin; };    void SetVertical( BOOL bVertical=TRUE ) { m_bVertical = bVertical; };  void Enable(BOOL bEnable = TRUE);  void EnableEx(BOOL bEnable = TRUE);    void DrawFocusRect( BOOL bDraw = TRUE, BOOL bRedraw = FALSE );    virtual ~CBitmapSlider();    // Generated message map functionsprotected:    void RestoreBackground(        CDC *pDC, int nXDst, int nYDst, int nWidth, int nHeight, CBitmap *pBmSrc);    void CopyBackground(        CDC *pDC, int nXSrc, int nYSrc, int nWidth, int nHeight, CBitmap *pBmDst );    void DrawBitmap(        CDC* pDC, int xStart, int yStart, int wWidth, int wHeight,        CDC* pTmpDC, int xSource, int ySource,        CBitmap *bmMask = NULL, BOOL bTransparent = FALSE );    void DrawTransparentBitmap(        CDC* pDC, int xStart, int yStart, int wWidth, int wHeight,        CDC* pTmpDC, int xSource, int ySource, CBitmap *bmMask );    void PrepareMask(        CBitmap* pBmpSource, CBitmap* pBmpMask,        COLORREF clrpTransColor=0xFF000000, int iTransPixelX=0, int iTransPixelY=0 );    int Pixel2Pos( int nPixel );    int Pos2Pixel( int nPos );    int m_nMax, m_nMin, m_nPos, m_nPage;    CRect m_rect;    int m_nWidth, m_nHeight;    int m_nThumbWidth, m_nThumbHeight;    int m_nMarginLeft, m_nMarginRight, m_nMarginTop, m_nMarginBottom;    int m_nThumbBgX, m_nThumbBgY;    int m_nMouseOffset;    BOOL m_bVertical;    BOOL m_bChannelActive, m_bThumbActive;    BOOL m_bTransparentChannel, m_bTransparentThumb, m_bThumb, m_bChannel;    BOOL m_bLButtonDown, m_bFocus, m_bFocusRect, m_bDrawFocusRect;    BOOL m_bEnable;  BOOL m_bEnableEx;    CBitmap m_bmChannel, m_bmChannelMask, m_bmChannelActive, m_bmChannelActiveMask;    CBitmap m_bmThumb, m_bmThumbMask, m_bmThumbActive, m_bmThumbActiveMask, m_bmThumbBg;    //{{AFX_MSG(CBitmapSlider)    afx_msg BOOL OnEraseBkgnd(CDC* pDC);    afx_msg void OnPaint();    afx_msg void OnLButtonDown(UINT nFlags, CPoint point);    afx_msg void OnMouseMove(UINT nFlags, CPoint point);  afx_msg BOOL OnMouseWheel(UINT nFlags, short zDelta, CPoint pt);    afx_msg void OnLButtonUp(UINT nFlags, CPoint point);    afx_msg UINT OnGetDlgCode();    afx_msg void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags);    afx_msg void OnKillFocus(CWnd* pNewWnd);    afx_msg void OnSetFocus(CWnd* pOldWnd);    afx_msg void OnDestroy();    //}}AFX_MSG    DECLARE_MESSAGE_MAP()private:    // This is CStatic method    void SetBitmap( HBITMAP /*hBitmap*/ ) {};};///////////////////////////////////////////////////////////////////////////////{{AFX_INSERT_LOCATION}}// Microsoft Visual C++ will insert additional declarations immediately before the previous line.#endif // !defined(AFX_BITMAPSLIDER_H__BED36788_B60C_4C9E_AC56_FE430B93A0FD__INCLUDED_)
// BitmapSlider.cpp : implementation file//#include "stdafx.h"#include "BitmapSlider.h"#ifdef _DEBUG#define new DEBUG_NEW#undef THIS_FILEstatic char THIS_FILE[] = __FILE__;#endif///////////////////////////////////////////////////////////////////////////////// CBitmapSlider v1.5//// It's free for everywhere - 16/September/2003 - Joon-ho Ryu///////////////////////////////////////////////////////////////////////////////CBitmapSlider::CBitmapSlider(){    m_nPos = m_nMin = 0;    m_nMax = 100;    m_nPage = 20;    m_nMarginLeft = m_nMarginRight = m_nMarginTop = m_nMarginBottom = 0;    m_nThumbWidth = m_nThumbHeight = 0;    m_bChannel = m_bVertical = m_bThumb = m_bLButtonDown = FALSE;    m_bFocusRect = m_bFocus = FALSE;    m_bDrawFocusRect = TRUE;    m_bEnable = TRUE;  m_bEnableEx = TRUE;    m_nThumbBgX = m_nThumbBgY = -1;}CBitmapSlider::~CBitmapSlider(){}BEGIN_MESSAGE_MAP(CBitmapSlider, CStatic)    //{{AFX_MSG_MAP(CBitmapSlider)    ON_WM_ERASEBKGND()    ON_WM_PAINT()    ON_WM_LBUTTONDOWN()    ON_WM_MOUSEMOVE()  ON_WM_MOUSEWHEEL()    ON_WM_LBUTTONUP()    ON_WM_GETDLGCODE()    ON_WM_KEYDOWN()    ON_WM_KILLFOCUS()    ON_WM_SETFOCUS()    ON_WM_CREATE()    ON_WM_DESTROY()    //}}AFX_MSG_MAP  END_MESSAGE_MAP()/////////////////////////////////////////////////////////////////////////////// CBitmapSlider message handlersBOOL CBitmapSlider::OnEraseBkgnd(CDC* /*pDC*/) {       // Do not erase background for the transparency effect    return TRUE;}// Draw channel and thumb//void CBitmapSlider::OnPaint() {    CPaintDC dcOrigin(this);    // "Flicker Free Drawing In MFC" by Keith Rule    CMemDC_flicker_free dc( &dcOrigin, &m_rect, m_bTransparentChannel );    CDC dcMem;    dcMem.CreateCompatibleDC( &dc );    CBitmap *pbmTmp;    // Delete focus rectangle for transparent channel    if( m_bFocusRect && ( m_bTransparentChannel || !m_bChannel ) ) {        dc.DrawFocusRect( m_rect );        m_bFocusRect = FALSE;    }    // Draw channel    if( m_bChannel ) {        pbmTmp = dcMem.SelectObject( &m_bmChannel );        // There is a bitmap for active channel        if( m_bChannelActive && m_bEnable ) {            // Vertical slider            if( m_bVertical ) {                // Lower part                DrawBitmap( &dc, 0, Pos2Pixel(m_nPos),                    m_nWidth, m_nHeight - Pos2Pixel(m_nPos),                    &dcMem, 0, Pos2Pixel(m_nPos),                    &m_bmChannelActiveMask, m_bTransparentChannel );                dcMem.SelectObject( &m_bmChannelActive );                // Upper part                DrawBitmap( &dc, 0, 0, m_nWidth, Pos2Pixel(m_nPos),                    &dcMem, 0, 0, &m_bmChannelMask, m_bTransparentChannel );            // Horizontal slider            } else {                // Right side                DrawBitmap( &dc, Pos2Pixel(m_nPos), 0,                    m_nWidth - Pos2Pixel(m_nPos), m_nHeight,                    &dcMem, Pos2Pixel(m_nPos), 0,                     &m_bmChannelActiveMask, m_bTransparentChannel );                dcMem.SelectObject( &m_bmChannelActive );                // Left side                DrawBitmap( &dc, 0, 0, Pos2Pixel(m_nPos), m_nHeight,                    &dcMem, 0, 0, &m_bmChannelMask, m_bTransparentChannel );            }        // Only one bitmap for channel        } else {            DrawBitmap( &dc, 0, 0, m_nWidth, m_nHeight,                &dcMem, 0, 0, &m_bmChannelMask, m_bTransparentChannel );        }        dcMem.SelectObject( pbmTmp );    }    // If there is a bitmap to restore background image of a thumb    if( m_nThumbBgX != -1 ) {        RestoreBackground(            &dc, m_nThumbBgX, m_nThumbBgY,            m_nThumbWidth, m_nThumbHeight, &m_bmThumbBg );        m_nThumbBgX = -1;    }    // Draw thumb    if( m_bThumb && m_bEnable ) {        if( m_bThumbActive && m_bLButtonDown )            pbmTmp = dcMem.SelectObject( &m_bmThumbActive ); // Active thumb        else            pbmTmp = dcMem.SelectObject( &m_bmThumb ); // Normal thumb        // Vertical slider        if( m_bVertical ) {            // Background image is need to be restored            if( m_bTransparentChannel || !m_bChannel ) {                m_nThumbBgX = m_nMarginLeft;                m_nThumbBgY = Pos2Pixel(m_nPos) - m_nThumbHeight/2;                CopyBackground(                    &dc, m_nThumbBgX, m_nThumbBgY,                    m_nThumbWidth, m_nThumbHeight, &m_bmThumbBg );            }            DrawBitmap(                &dc, m_nMarginLeft, Pos2Pixel(m_nPos) - m_nThumbHeight/2,                m_nThumbWidth, m_nThumbHeight,                &dcMem, 0, 0, &m_bmThumbMask, m_bTransparentThumb );        // Horizontal slider        } else {            // Background image is need to be restored            if( m_bTransparentChannel || !m_bChannel ) {                m_nThumbBgX = Pos2Pixel(m_nPos) - m_nThumbWidth/2;                m_nThumbBgY = m_nMarginTop;                CopyBackground(                    &dc, m_nThumbBgX, m_nThumbBgY,                    m_nThumbWidth, m_nThumbHeight, &m_bmThumbBg );            }            DrawBitmap(                &dc, Pos2Pixel(m_nPos) - m_nThumbWidth/2, m_nMarginTop,                m_nThumbWidth, m_nThumbHeight,                &dcMem, 0, 0, &m_bmThumbMask, m_bTransparentThumb );        } // if horizontal        dcMem.SelectObject( pbmTmp );    } // if draw thumb    // Draw focus rectangle    if( m_bDrawFocusRect && m_bFocus && m_bEnable ) {        dc.DrawFocusRect( m_rect );        m_bFocusRect = TRUE;    }    dcMem.DeleteDC();}// Sets the maximum range for the slider.//// Parameters://      [IN]    nMax//              Maximum position for the slider.//      [IN]    bRedraw//              TRUE to redraw after the range is set.//              FALSE to only change maximum position.//void CBitmapSlider::SetRangeMax(int nMax, BOOL bRedraw){    m_nMax = nMax;    if( bRedraw )        Invalidate();}// Sets the minimum range for the slider.//// Parameters://      [IN]    nMin//              Minimum position for the slider.//      [IN]    bRedraw//              TRUE to redraw after the range is set.//              FALSE to only change minimum position.//void CBitmapSlider::SetRangeMin(int nMin, BOOL bRedraw){    m_nMin = nMin;    if( bRedraw )        Invalidate();}// Sets the range (minimum and maximum positions) for the slider.//// Parameters://      [IN]    nMin//              Minimum position for the slider.//      [IN]    nMax//              Maximum position for the slider.//      [IN]    bRedraw//              TRUE to redraw after the range is set.//              FALSE to only change the range.//void CBitmapSlider::SetRange(int nMin, int nMax, BOOL bRedraw){    SetRangeMin( nMin, FALSE );    SetRangeMax( nMax, bRedraw );}// Sets the current position of the slider.//// Parameters://      [IN]    nPos//              Specifies the new slider position.//void CBitmapSlider::SetPos(int nPos){    m_nPos = nPos;    // Boundary check    if( m_nPos > m_nMax )        m_nPos = m_nMax;    if( m_nPos < m_nMin )        m_nPos = m_nMin;    Invalidate();}// Sets the size of the page for a control.//// Parameters://      [IN]    nSize//              The new page size of the control.//// Return value://      The previous page size.//int CBitmapSlider::SetPageSize(int nSize){    int nRet = m_nPage;    m_nPage = nSize;    return nRet;}// Sets the left, top, right, and bottom margins for a control//void CBitmapSlider::SetMargin(int nLeft, int nTop, int nRight, int nBottom ){    SetMarginLeft( nLeft );    SetMarginTop( nTop );    SetMarginRight( nRight );    SetMarginBottom( nBottom );}// Enables or disables control.////      [IN]    bEnable//              TRUE to enable control.//              FALSE to disable control.//void CBitmapSlider::Enable(BOOL bEnable){    m_bEnable = bEnable;    // If control is disabled during dragging    if( !m_bEnable && m_bLButtonDown ) {        m_bLButtonDown = FALSE;        ReleaseCapture();    }    Invalidate();}void CBitmapSlider::EnableEx(BOOL bEnable /* = TRUE */){  EnableWindow(bEnable);  m_bEnableEx = bEnable;  SetPos(m_nPos);}// Specify whether draw focus rectangle or not.////      [IN]    bDraw//              TRUE to draw focus rectangle.//              FALSE to hide focus rectangle.////      [IN]    bRedraw//              TRUE to redraw status is changed.//              FALSE to only change the status.//void CBitmapSlider::DrawFocusRect(BOOL bDraw, BOOL bRedraw){    m_bDrawFocusRect = bDraw;    if( bRedraw )        Invalidate();}// Load bitmaps for a channel//// Parameters://      [IN]    nChannelID//              ID number of the bitmap resource of the channel.//      [IN]    nActiveID//              ID number of the bitmap resource of the active channel.//      [IN]    bTransparent//              TRUE to apply transparency effect.//              FALSE to display normal bitmap.//      [IN]    clrpTransColor//              RGB color to treat as transparent.//      [IN]    iTransPixelX//              Logical x-coordinate of a point.//              It's color will be treated as transparent.//      [IN]    iTransPixelY//              Logical y-coordinate of a point.//              It's color will be treated as transparent.//// Return value://      TRUE//          Function succeedes.//      FALSE//          Function failes to load bitmaps.//BOOL CBitmapSlider::SetBitmapChannel(    UINT nChannelID, UINT nActiveID , BOOL bTransparent,    COLORREF clrpTransColor, int iTransPixelX, int iTransPixelY ){    // This control will not have any bitmap for channel    if( !nChannelID ) {        m_bChannel = FALSE;        m_bmChannel.DeleteObject();        m_bmChannelMask.DeleteObject();        m_bmChannelActive.DeleteObject();        m_bmChannelActiveMask.DeleteObject();        return TRUE;    }    // load a bitmap    m_bmChannel.DeleteObject();    if( !m_bmChannel.LoadBitmap( nChannelID ) )        return FALSE;    // Prepare mask for transparency effect.    if( bTransparent ) {        PrepareMask( &m_bmChannel, &m_bmChannelMask,            clrpTransColor, iTransPixelX, iTransPixelY );    }    // Load a bitmap for active state.    if( nActiveID ) {        m_bmChannelActive.DeleteObject();        if( !m_bmChannelActive.LoadBitmap( nActiveID ) ) {            m_bmChannel.DeleteObject();            if( bTransparent )                m_bmChannelMask.DeleteObject();            return FALSE;        }        if( bTransparent ) {            PrepareMask( &m_bmChannelActive, &m_bmChannelActiveMask,                clrpTransColor, iTransPixelX, iTransPixelY );        }        m_bChannelActive = TRUE;    // There is no bitmap for active state.    } else        m_bChannelActive = FALSE;    // Get size of bitmap.    BITMAP  bitmap;    m_bmChannel.GetBitmap( &bitmap );    m_nWidth = bitmap.bmWidth;    m_nHeight = bitmap.bmHeight;    // Compare size    if( m_bChannelActive ) {        BITMAP  bitmap;        m_bmChannelActive.GetBitmap( &bitmap );        ASSERT( m_nWidth == bitmap.bmWidth && m_nHeight == bitmap.bmHeight );    }    // Change size of control as same as the bitmap.    SetWindowPos(NULL, 0, 0, m_nWidth, m_nHeight, SWP_NOZORDER | SWP_NOMOVE);    GetClientRect( &m_rect );    m_bTransparentChannel = bTransparent;    m_bChannel = TRUE;    return TRUE;}// Load bitmaps for a thumb//// Parameters://      [IN]    nThumbID//              ID number of the bitmap resource of the thumb//      [IN]    nActiveID//              ID number of the bitmap resource of the active thumb//      [IN]    bTransparent//              TRUE to apply transparency effect//              FALSE to display normal bitmap//      [IN]    clrpTransColor//              RGB color to treat as transparent//      [IN]    iTransPixelX//              Logical x-coordinate of a point.//              It's color will be treated as transparent//      [IN]    iTransPixelY//              Logical y-coordinate of a point.//              It's color will be treated as transparent//// Return value://      TRUE//          Function succeedes.//      FALSE//          Function failes to load bitmaps.//BOOL CBitmapSlider::SetBitmapThumb(    UINT nThumbID, UINT nActiveID, BOOL bTransparent,    COLORREF clrpTransColor, int iTransPixelX, int iTransPixelY ){    // This control will not have bitmap    if( !nThumbID ) {        m_bThumb = FALSE;        m_bmThumb.DeleteObject();        m_bmThumbMask.DeleteObject();        m_bmThumbActive.DeleteObject();        m_bmThumbActiveMask.DeleteObject();        m_bmThumbBg.DeleteObject();        return TRUE;    }    // load a bitmap    m_bmThumb.DeleteObject();    if( !m_bmThumb.LoadBitmap( nThumbID ) )        return FALSE;    // Prepare mask for transparency effect.    if( bTransparent ) {        PrepareMask( &m_bmThumb, &m_bmThumbMask,            clrpTransColor, iTransPixelX, iTransPixelY );    }    // Load a bitmap for active state.    if( nActiveID ) {        m_bmThumbActive.DeleteObject();        if( !m_bmThumbActive.LoadBitmap( nActiveID ) ) {            m_bmThumb.DeleteObject();            if( bTransparent )                m_bmThumbMask.DeleteObject();            return FALSE;        }        if( bTransparent ) {            PrepareMask( &m_bmThumbActive, &m_bmThumbActiveMask,                clrpTransColor, iTransPixelX, iTransPixelY );        }        m_bThumbActive = TRUE;    // There is no bitmap for active state.    } else        m_bThumbActive = FALSE;    // Get size of the bitmap    BITMAP  bitmap;    m_bmThumb.GetBitmap( &bitmap );    m_nThumbWidth = bitmap.bmWidth;    m_nThumbHeight = bitmap.bmHeight;    // Get size of the control if there was no bitmap for channel.    if( !m_bChannel ) {        GetClientRect( &m_rect );        m_nHeight = m_rect.Height();        m_nWidth = m_rect.Width();    }    ASSERT( m_nThumbWidth <= m_nWidth && m_nThumbHeight <= m_nHeight );    // Compare size    if( m_bThumbActive ) {        BITMAP  bitmap;        m_bmThumbActive.GetBitmap( &bitmap );        ASSERT(            m_nThumbWidth == bitmap.bmWidth &&            m_nThumbHeight == bitmap.bmHeight );    }    // Set attributes    m_bTransparentThumb = bTransparent;    m_bThumb = TRUE;    return TRUE;}// OnLButtonDown//// Dragging is started//void CBitmapSlider::OnLButtonDown(UINT nFlags, CPoint point) {  if (!m_bEnable || !m_bEnableEx)        return;    SetCapture();    SetFocus();    m_bLButtonDown = TRUE;    // If mouse button is clicked on the thumb,    // capture the coordinates of mouse pointer and center of thumb    // and calculate distance between them.    if( m_bVertical ) {        if( abs( point.y - Pos2Pixel( m_nPos ) ) <= m_nThumbHeight / 2 )            m_nMouseOffset = point.y - Pos2Pixel( m_nPos );        else            m_nMouseOffset = 0;    } else {        if( abs( point.x - Pos2Pixel( m_nPos ) ) <= m_nThumbWidth / 2 )            m_nMouseOffset = point.x - Pos2Pixel( m_nPos );        else            m_nMouseOffset = 0;    }    OnMouseMove( nFlags, point );    Invalidate();    CStatic::OnLButtonDown(nFlags, point);}// OnMouseMove//// During dragging//void CBitmapSlider::OnMouseMove(UINT nFlags, CPoint point) {  if (!m_bLButtonDown || !m_bEnable || !m_bEnableEx)        return;    int nPixel;    // Boundary check    if( m_bVertical ) {        nPixel = point.y - m_nMouseOffset;        if( nPixel > m_nHeight - m_nMarginBottom - m_nThumbHeight/2 )            nPixel = m_nHeight - m_nMarginBottom - m_nThumbHeight/2;        if( nPixel < m_nMarginTop + m_nThumbHeight/2 )            nPixel = m_nMarginTop + m_nThumbHeight/2;    } else {        nPixel = point.x - m_nMouseOffset;        if( nPixel < m_nMarginLeft + m_nThumbWidth/2 )            nPixel = m_nMarginLeft + m_nThumbWidth/2;        if( nPixel > m_nWidth - m_nMarginRight - m_nThumbWidth/2 )            nPixel = m_nWidth - m_nMarginRight - m_nThumbWidth/2;    }    // Apply change    if( Pos2Pixel(m_nPos) != nPixel ) {        SetPos( Pixel2Pos( nPixel ) );        ::PostMessage(            GetParent()->GetSafeHwnd(), WM_BITMAPSLIDER_MOVING,            GetDlgCtrlID(), m_nPos );    }    CStatic::OnMouseMove(nFlags, point);}BOOL CBitmapSlider::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt){  m_nPos += (zDelta < 0 ? 1 : -1);  SetPos(m_nPos);  ::PostMessage(    GetParent()->GetSafeHwnd(), WM_BITMAPSLIDER_MOVED,    GetDlgCtrlID(), m_nPos);  return CStatic::OnMouseWheel(nFlags, zDelta, pt);}// OnLButtonUp//// Dragging is finished//void CBitmapSlider::OnLButtonUp(UINT nFlags, CPoint point) {  if (!m_bEnable || !m_bEnableEx)        return;    ReleaseCapture();    m_bLButtonDown = FALSE;    Invalidate();    ::PostMessage(        GetParent()->GetSafeHwnd(), WM_BITMAPSLIDER_MOVED,        GetDlgCtrlID(), m_nPos );    CStatic::OnLButtonUp(nFlags, point);}// Calculate point of thumb from position value//int CBitmapSlider::Pos2Pixel(int nPos){    if( m_bVertical ) {        return            m_nMarginTop + m_nThumbHeight/2 +            (int)(            ( m_nHeight - m_nMarginTop - m_nMarginBottom - m_nThumbHeight ) *            ((double) ( nPos - m_nMin ) / ( m_nMax - m_nMin ) )            );    } else {        return (int)(            ( m_nWidth - m_nMarginLeft - m_nMarginRight - m_nThumbWidth ) *            ((double) ( nPos - m_nMin ) / ( m_nMax - m_nMin ) )            ) + m_nMarginLeft + m_nThumbWidth/2;    }}// Calculate position value from point of mouse//int CBitmapSlider::Pixel2Pos(int nPixel){    if( m_bVertical ) {        return (int)(            m_nMin +            (double)( nPixel - m_nMarginTop - m_nThumbHeight/2) /            ( m_nHeight - m_nMarginBottom - m_nMarginTop - m_nThumbHeight ) *            ( m_nMax - m_nMin )            );    } else {        return (int)(            m_nMin +            (double)( nPixel - m_nMarginLeft - m_nThumbWidth/2 ) /            ( m_nWidth - m_nMarginLeft - m_nMarginRight - m_nThumbWidth ) *            ( m_nMax - m_nMin )            );    }}// Copy background image to bitmap//void CBitmapSlider::CopyBackground(    CDC *pDC, int nXSrc, int nYSrc, int nWidth, int nHeight, CBitmap *pBmDst){    pBmDst->DeleteObject();    pBmDst->CreateCompatibleBitmap( pDC, nWidth, nHeight );    CDC memDC;    memDC.CreateCompatibleDC( pDC );    CBitmap *pBmTmp = memDC.SelectObject( pBmDst );    memDC.BitBlt( 0, 0, nWidth, nHeight, pDC, nXSrc, nYSrc, SRCCOPY );    memDC.SelectObject( pBmTmp );    memDC.DeleteDC();}// Restore background image from bitmap//void CBitmapSlider::RestoreBackground(    CDC *pDC, int nXDst, int nYDst, int nWidth, int nHeight, CBitmap *pBmSrc){    CDC memDC;    memDC.CreateCompatibleDC( pDC );    CBitmap *pBmTmp = memDC.SelectObject( pBmSrc );    pDC->BitBlt( nXDst, nYDst, nWidth, nHeight, &memDC, 0, 0, SRCCOPY );    memDC.SelectObject( pBmTmp );    memDC.DeleteDC();}// DrawBitmap//// It's for code readability//void CBitmapSlider::DrawBitmap(    CDC *pDC, int xStart, int yStart, int wWidth, int wHeight,    CDC *pTmpDC, int xSource, int ySource, CBitmap *bmMask, BOOL bTransparent ){    if( bTransparent ) {        DrawTransparentBitmap(            pDC, xStart, yStart,            wWidth, wHeight,            pTmpDC, xSource, ySource, bmMask );    } else {        pDC->BitBlt( xStart, yStart,            wWidth, wHeight,            pTmpDC, xSource, ySource, SRCCOPY );    }}// PrepareMask//// "Drawing Transparent Bitmap with ease with on the fly masks in MFC"// By Raja Segar//// I changed default clrpTransColor value from NULL(black) to 0xFF000000(not RGB color)//void CBitmapSlider::PrepareMask(    CBitmap *pBmpSource, CBitmap *pBmpMask,    COLORREF clrpTransColor, int iTransPixelX, int iTransPixelY){    BITMAP bm;    // Get the dimensions of the source bitmap    pBmpSource->GetObject(sizeof(BITMAP), &bm);    // Create the mask bitmap    pBmpMask->DeleteObject();    pBmpMask->CreateBitmap( bm.bmWidth, bm.bmHeight, 1, 1, NULL);    // We will need two DCs to work with. One to hold the Image    // (the source), and one to hold the mask (destination).    // When blitting onto a monochrome bitmap from a color, pixels    // in the source color bitmap that are equal to the background    // color are blitted as white. All the remaining pixels are    // blitted as black.    CDC hdcSrc, hdcDst;    hdcSrc.CreateCompatibleDC(NULL);    hdcDst.CreateCompatibleDC(NULL);    // Load the bitmaps into memory DC    CBitmap* hbmSrcT = (CBitmap*) hdcSrc.SelectObject(pBmpSource);    CBitmap* hbmDstT = (CBitmap*) hdcDst.SelectObject(pBmpMask);    // Dynamically get the transparent color    COLORREF clrTrans;    if (clrpTransColor == 0xFF000000)    {        // User did not specify trans color so get it from bmp        clrTrans = hdcSrc.GetPixel(iTransPixelX, iTransPixelY);    }    else    {        clrTrans = clrpTransColor;    }    // Change the background to trans color    COLORREF clrSaveBk  = hdcSrc.SetBkColor(clrTrans);    // This call sets up the mask bitmap.    hdcDst.BitBlt(0,0,bm.bmWidth, bm.bmHeight, &hdcSrc,0,0,SRCCOPY);    // Now, we need to paint onto the original image, making    // sure that the "transparent" area is set to black. What    // we do is AND the monochrome image onto the color Image    // first. When blitting from mono to color, the monochrome    // pixel is first transformed as follows:    // if  1 (black) it is mapped to the color set by SetTextColor().    // if  0 (white) is is mapped to the color set by SetBkColor().    // Only then is the raster operation performed.    COLORREF clrSaveDstText = hdcSrc.SetTextColor(RGB(255,255,255));    hdcSrc.SetBkColor(RGB(0,0,0));    hdcSrc.BitBlt(0,0,bm.bmWidth, bm.bmHeight, &hdcDst,0,0,SRCAND);    // Clean up by deselecting any objects, and delete the    // DC's.    hdcDst.SetTextColor(clrSaveDstText);    hdcSrc.SetBkColor(clrSaveBk);    hdcSrc.SelectObject(hbmSrcT);    hdcDst.SelectObject(hbmDstT);    hdcSrc.DeleteDC();    hdcDst.DeleteDC();}// DrawTransparentBitmap//// "Drawing Transparent Bitmap with ease with on the fly masks in MFC"// By Raja Segar//void CBitmapSlider::DrawTransparentBitmap(    CDC *pDC, int xStart, int yStart, int wWidth, int wHeight,    CDC *pTmpDC, int xSource, int ySource, CBitmap *bmMask ){    // We are going to paint the two DDB's in sequence to the destination.    // 1st the monochrome bitmap will be blitted using an AND operation to    // cut a hole in the destination. The color image will then be ORed    // with the destination, filling it into the hole, but leaving the    // surrounding area untouched.    CDC hdcMem;    hdcMem.CreateCompatibleDC(NULL);    CBitmap* hbmT = hdcMem.SelectObject(bmMask);    pDC->BitBlt( xStart, yStart, wWidth, wHeight, &hdcMem,        xSource, ySource, SRCAND);    // Also note the use of SRCPAINT rather than SRCCOPY.    pDC->BitBlt(xStart, yStart, wWidth, wHeight, pTmpDC,        xSource, ySource,SRCPAINT);    // Now, clean up.    hdcMem.SelectObject(hbmT);    hdcMem.DeleteDC();}// To get keyboard input//UINT CBitmapSlider::OnGetDlgCode() {    if( GetKeyState(VK_TAB) >= 0 ) {        return  DLGC_WANTALLKEYS;    }    return CStatic::OnGetDlgCode();}// Handling keyboard input//void CBitmapSlider::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) {  if (!m_bEnable || !m_bEnableEx)        return;    switch( nChar ) {    // Left & up    case VK_LEFT :    case VK_UP :        SetPos( m_nPos-1 );        break;    // Right & down    case VK_RIGHT :    case VK_DOWN :        SetPos( m_nPos+1 );        break;    // Home    case VK_HOME :        SetPos( m_nMin );        break;    // End    case VK_END :        SetPos( m_nMax );        break;    // Page up    case VK_PRIOR :        SetPos( m_nPos - m_nPage );        break;    // Page down    case VK_NEXT :        SetPos( m_nPos + m_nPage );        break;    default :        CStatic::OnKeyDown(nChar, nRepCnt, nFlags);        return;    }    ::PostMessage(        GetParent()->GetSafeHwnd(), WM_BITMAPSLIDER_MOVED,        GetDlgCtrlID(), m_nPos );    CStatic::OnKeyDown(nChar, nRepCnt, nFlags);}// Control looses its focus//void CBitmapSlider::OnKillFocus(CWnd* pNewWnd) {    CStatic::OnKillFocus(pNewWnd);    m_bFocus = FALSE;    Invalidate();}// This control gains its focus//void CBitmapSlider::OnSetFocus(CWnd* pOldWnd) {    CStatic::OnSetFocus(pOldWnd);    m_bFocus = TRUE;    Invalidate();}// Release resources//void CBitmapSlider::OnDestroy() {    CStatic::OnDestroy();    m_bmThumb.DeleteObject();    m_bmThumbMask.DeleteObject();    m_bmThumbActive.DeleteObject();    m_bmThumbActiveMask.DeleteObject();    m_bmThumbBg.DeleteObject();    m_bmChannel.DeleteObject();    m_bmChannelMask.DeleteObject();    m_bmChannelActive.DeleteObject();    m_bmChannelActiveMask.DeleteObject();}

有点一点需要注意:
如果窗口是滑动显示 ,需要做一些特殊处理:
::AnimateWindow(wnd_.GetSafeHwnd(), 500, AW_ACTIVATE | AW_HOR_POSITIVE);

在滑动之后 调用一下
slider_.ShowWindow(SW_HIDE);slider_.ShowWindow(SW_SHOW);

0 0