请问如何用vc制作类似MediaPlayer的进度条?
有实例更佳!!!

解决方案 »

  1.   

    自己画呗,从CWnd派生,想画成啥样就画成啥样。
      

  2.   

    两点注意:
    1.mfc标准的进度条定位不准确,自己派生它,重写OnLButtonDown...
    2.外观,重写onpaint,全部自己画,或者借助换肤工具,如skinmagic(收费)之类ps.cronaldo是我偶像
      

  3.   


    这些我知道啊,我是想在播放位置前面加上图片,不知道怎样重绘,比如全长100,播放到50的位置,我想在0-50间加上彩色条,就像mediaplayer那样。在哪里响应好呢??找不到。我试过在OnNMCustomdraw里不行。求救中.................
      

  4.   

    重载CProgressCtrl// OwnerProgressCtrl.cpp : 实现文件
    //#include "stdafx.h"
    #include "OwnerProgress.h"
    #include "OwnerProgressCtrl.h"
    // COwnerProgressCtrlIMPLEMENT_DYNAMIC(COwnerProgressCtrl, CProgressCtrl)COwnerProgressCtrl::COwnerProgressCtrl()
    : m_strTitle(_T(""))
    , m_nCurSel(0)
    {
    m_pImage[0]=NULL;
    m_pImage[1]=NULL; ::GdiplusStartup(&m_pToken,&m_GdiInput,NULL);
    }COwnerProgressCtrl::~COwnerProgressCtrl()
    {
    if( m_pImage[0] )
    delete m_pImage[0];
    if( m_pImage[1] )
    delete m_pImage[1]; ::GdiplusShutdown(m_pToken);
    }
    BEGIN_MESSAGE_MAP(COwnerProgressCtrl, CProgressCtrl)
    ON_WM_PAINT()
    END_MESSAGE_MAP()// COwnerProgressCtrl 消息处理程序void COwnerProgressCtrl::OnPaint()
    {
    CPaintDC dc(this); // device context for painting
    // TODO: 在此处添加消息处理程序代码
    // 不为绘图消息调用 CProgressCtrl::OnPaint() CDC memDC;
    memDC.CreateCompatibleDC(&dc); CRect rc;
    GetClientRect(&rc); // 得到当前绘图区域
    int nLow=0,nHigh=0;
    GetRange(nLow,nHigh); int nPos=GetPos();
    float fPersent=(float)nPos/(nHigh-nLow);
    rc.right=rc.left+fPersent*rc.Width(); CBitmap memBmp;
    memBmp.CreateCompatibleBitmap(&dc,rc.Width(),rc.Height());
    CBitmap *pOldBmp=memDC.SelectObject(&memBmp); Graphics graphics(memDC.m_hDC); Rect rect(rc.left,rc.top,rc.right,rc.bottom);
    LinearGradientBrush lBrush(rect,Color(100,0,255,0),Color(150,0,0,255),LinearGradientModeHorizontal);
    graphics.FillRectangle(&lBrush,rect); if( m_pImage==NULL )
    return; graphics.DrawImage(m_pImage[m_nCurSel],rc.right-m_pImage[m_nCurSel]->GetWidth(),0,
    m_pImage[m_nCurSel]->GetWidth(),m_pImage[m_nCurSel]->GetHeight()); if( !m_strTitle.IsEmpty() )
    {
    //Pen pen(Color(100,0,0,0),2);
    FontFamily fontFamily(_T("宋体"));
    Font font(&fontFamily,10); SolidBrush sBrush(Color(200,255,255,255));
    StringFormat stringFormat;
    stringFormat.SetAlignment(StringAlignmentCenter); PointF point(rect.Width/2,rect.Height/2);
    graphics.DrawString(m_strTitle,-1,&font,point,&sBrush);
    } dc.BitBlt(0,0,rc.Width(),rc.Height(),&memDC,0,0,SRCCOPY); memDC.SelectObject(pOldBmp);
    memDC.DeleteDC();
    }void COwnerProgressCtrl::PreSubclassWindow()
    {
    // TODO: 在此添加专用代码和/或调用基类
    if( m_pImage[0] )
    delete m_pImage[0];
    if( m_pImage[1] )
    delete m_pImage[1];
    m_pImage[0]=new Image(_T("1.bmp"));
    m_pImage[1]=new Image(_T("2.bmp"));
    CProgressCtrl::PreSubclassWindow();
    }
    void COwnerProgressCtrl::SetBitmap(int nCurSel)
    {
    m_nCurSel=nCurSel; Invalidate();
    }void COwnerProgressCtrl::SetTitle(CString strTitle)
    {
    m_strTitle=strTitle;
    //Invalidate();
    }
      

  5.   

    这个要写很多鼠标响应的吧?应该有从CSliderCtrl继承的吧,怎么都没人做过吗?
      

  6.   

    直接用CSliderCtrl就可以了,把控件的宽度改小些,看上去就和播放进度条差不多了,而且CSliderCtrl的拖动特性也符合播放进度的拖动,只不过你要时刻自己计算播放进度,并更新滑动条的位置
      

  7.   


    那自绘就是了,会响应相关消息,会用GDI贴图就行
      

  8.   

    可看看这个显示文本的进度条控件类CTextProgressCtrl,或许能从中获取灵感:
    http://topic.csdn.net/t/20030106/10/1330183.html
      

  9.   

    我正在做CMySlider  从CSliderCtrl派生
    OnPanit函数下 自绘的部分 我还没弄
    为了实现 MediaPlayer中 鼠标悬停在进度条上 拇指按钮才出现 所以要给该类添加
    对OnMouseLeave  OnMouseMove函数的处理
    这里给你些代码参考一下吧 希望对你有帮助void CMySlider::OnMouseMove(UINT nFlags, CPoint point) 
    {
    TRACKMOUSEEVENT event ;
    event.cbSize = sizeof( event );
    event.dwFlags = TME_LEAVE ;
    event.dwHoverTime = 0 ;
    event.hwndTrack = GetSafeHwnd() ;
    VERIFY (_TrackMouseEvent( &event )) ;
    CSliderCtrl::OnMouseMove(nFlags, point);
    }
    LRESULT CMySlider::OnMouseLeave( WPARAM wParam , LPARAM lParam )
    {
    return 0 ;
    }
    OnMouseLeave 函数要自己添加  afx_msg LRESULT OnMouseLeave( WPARAM wParam , LPARAM lParam ) ;ON_MESSAGE( WM_MOUSELEAVE , OnMouseLeave )
      

  10.   

    找一个可以贴图的CSliderCtrl子类:
    比喻CBitmapSlider就可以,我用的就是这个作的
    #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
    {
    // Construction
    public:
    CBitmapSlider();// Attributes
    public:// Operations
    public:// Overrides
    // ClassWizard generated virtual function overrides
    //{{AFX_VIRTUAL(CBitmapSlider)
    //}}AFX_VIRTUAL// Implementation
    public: 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 DrawFocusRect( BOOL bDraw = TRUE, BOOL bRedraw = FALSE ); virtual ~CBitmapSlider(); // Generated message map functions
    protected:
    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; 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 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_)
      

  11.   

    // BitmapSlider.cpp : implementation file
    //#include "stdafx.h"
    #include "BitmapSlider.h"#ifdef _DEBUG
    #define new DEBUG_NEW
    #undef THIS_FILE
    static 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 = 1; 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_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_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 dc( &dcOrigin, &m_rect, m_bTransparentChannel ); CDC dcMem;
    BOOL bReturn =  dcMem.CreateCompatibleDC( &dc ); if (!bReturn)
    {
    dcMem.DeleteDC();
    TRACE("1 CBitmapSlider::OnPaint() CreateCompatibleDC error");
    return ;
    } 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;
    } bReturn =dcMem.DeleteDC();
    if (!bReturn)
    {
    TRACE("CBitmapSlider::OnPaint() dcMem.DeleteDC error");
    }
    }// 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();
    }// 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.
    //
      

  12.   

    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 )
    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 )
    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);
    }