// 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 = 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_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 handlers BOOL 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_Slider 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(); } // 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 ) 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); } // OnLButtonUp // // Dragging is finished // void CBitmapSlider::OnLButtonUp(UINT nFlags, CPoint point) { if( !m_bEnable ) 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 ) 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(); }