home *** CD-ROM | disk | FTP | other *** search
/ Large Pack of OldSkool DOS MOD Trackers / beaversweeper_v101.zip / src / RoundSliderCtrl.cpp < prev    next >
C/C++ Source or Header  |  2005-10-07  |  17KB  |  665 lines

  1. // RoundSliderCtrl.cpp : implementation file
  2. //
  3.  
  4. #include "stdafx.h"
  5. #include "tracker.h"
  6. #include "RoundSliderCtrl.h"
  7.  
  8. #include <math.h>
  9.  
  10. #ifdef _DEBUG
  11. #define new DEBUG_NEW
  12. #undef THIS_FILE
  13. static char THIS_FILE[] = __FILE__;
  14. #endif
  15.  
  16.  
  17. static const double pi = 3.141592653589793238462643383279;
  18.  
  19. // The following 3 functions were taken from 'CRoundButton.cpp', written and
  20. // copyright (c) 1997,1998 by Chris Maunder (chrismaunder@codeguru.com).
  21. // To be honest, I never had a look at their implementation, I just use them.
  22. // This is cut-and-paste-programming at its best... if it works... :)
  23.  
  24. // prototypes
  25. COLORREF GetColour(double dAngle, COLORREF crBright, COLORREF crDark);
  26. void DrawCircle(CDC* pDC, CPoint p, LONG lRadius, COLORREF crColour, BOOL bDashed = FALSE);
  27. void DrawCircle(CDC* pDC, CPoint p, LONG lRadius, COLORREF crBright, COLORREF crDark);
  28.  
  29.  
  30. // Calculate colour for a point at the given angle by performing a linear
  31. // interpolation between the colours crBright and crDark based on the cosine
  32. // of the angle between the light source and the point.
  33. //
  34. // Angles are measured from the +ve x-axis (i.e. (1,0) = 0 degrees, (0,1) = 90 degrees )
  35. // But remember: +y points down!
  36.  
  37. COLORREF GetColour(double dAngle, COLORREF crBright, COLORREF crDark)
  38. {
  39. #define Rad2Deg    180.0/3.1415 
  40. #define LIGHT_SOURCE_ANGLE    -2.356        // -2.356 radians = -135 degrees, i.e. From top left
  41.  
  42.     ASSERT(dAngle > -3.1416 && dAngle < 3.1416);
  43.     double dAngleDifference = LIGHT_SOURCE_ANGLE - dAngle;
  44.  
  45.     if (dAngleDifference < -3.1415) dAngleDifference = 6.293 + dAngleDifference;
  46.     else if (dAngleDifference > 3.1415) dAngleDifference = 6.293 - dAngleDifference;
  47.  
  48.     double Weight = 0.5*(cos(dAngleDifference)+1.0);
  49.  
  50.     BYTE Red   = (BYTE) (Weight*GetRValue(crBright) + (1.0-Weight)*GetRValue(crDark));
  51.     BYTE Green = (BYTE) (Weight*GetGValue(crBright) + (1.0-Weight)*GetGValue(crDark));
  52.     BYTE Blue  = (BYTE) (Weight*GetBValue(crBright) + (1.0-Weight)*GetBValue(crDark));
  53.  
  54.     //TRACE("LightAngle = %0.0f, Angle = %3.0f, Diff = %3.0f, Weight = %0.2f, RGB%3d,%3d,%3d\n", 
  55.     //      LIGHT_SOURCE_ANGLE*Rad2Deg, dAngle*Rad2Deg, dAngleDifference*Rad2Deg,Weight,Red,Green,Blue);
  56.  
  57.     return RGB(Red, Green, Blue);
  58. }
  59.  
  60. void DrawCircle(CDC* pDC, CPoint p, LONG lRadius, COLORREF crColour, BOOL bDashed)
  61. {
  62.     const int nDashLength = 1;
  63.     LONG lError, lXoffset, lYoffset;
  64.     int  nDash = 0;
  65.     BOOL bDashOn = TRUE;
  66.  
  67.     //Check to see that the coordinates are valid
  68.     ASSERT( (p.x + lRadius <= LONG_MAX) && (p.y + lRadius <= LONG_MAX) );
  69.     ASSERT( (p.x - lRadius >= LONG_MIN) && (p.y - lRadius >= LONG_MIN) );
  70.  
  71.     //Set starting values
  72.     lXoffset = lRadius;
  73.     lYoffset = 0;
  74.     lError     = -lRadius;
  75.  
  76.     do {
  77.         if (bDashOn) {
  78.             pDC->SetPixelV(p.x + lXoffset, p.y + lYoffset, crColour);
  79.             pDC->SetPixelV(p.x + lXoffset, p.y - lYoffset, crColour);
  80.             pDC->SetPixelV(p.x + lYoffset, p.y + lXoffset, crColour);
  81.             pDC->SetPixelV(p.x + lYoffset, p.y - lXoffset, crColour);
  82.             pDC->SetPixelV(p.x - lYoffset, p.y + lXoffset, crColour);
  83.             pDC->SetPixelV(p.x - lYoffset, p.y - lXoffset, crColour);
  84.             pDC->SetPixelV(p.x - lXoffset, p.y + lYoffset, crColour);
  85.             pDC->SetPixelV(p.x - lXoffset, p.y - lYoffset, crColour);
  86.         }
  87.  
  88.         //Advance the error term and the constant X axis step
  89.         lError += lYoffset++;
  90.  
  91.         //Check to see if error term has overflowed
  92.         if ((lError += lYoffset) >= 0)
  93.             lError -= --lXoffset * 2;
  94.  
  95.         if (bDashed && (++nDash == nDashLength)) {
  96.             nDash = 0;
  97.             bDashOn = !bDashOn;
  98.         }
  99.  
  100.     } while (lYoffset <= lXoffset);    //Continue until halfway point
  101.  
  102. void DrawCircle(CDC* pDC, CPoint p, LONG lRadius, COLORREF crBright, COLORREF crDark)
  103. {
  104.     LONG lError, lXoffset, lYoffset;
  105.  
  106.     //Check to see that the coordinates are valid
  107.     ASSERT( (p.x + lRadius <= LONG_MAX) && (p.y + lRadius <= LONG_MAX) );
  108.     ASSERT( (p.x - lRadius >= LONG_MIN) && (p.y - lRadius >= LONG_MIN) );
  109.  
  110.     //Set starting values
  111.     lXoffset = lRadius;
  112.     lYoffset = 0;
  113.     lError     = -lRadius;
  114.  
  115.     do {
  116.         const double Pi = 3.141592654, 
  117.                      Pi_on_2 = Pi * 0.5,
  118.                      Three_Pi_on_2 = Pi * 1.5;
  119.         COLORREF crColour;
  120.         double     dAngle = atan2((float)lYoffset, (float)lXoffset);
  121.  
  122.         //Draw the current pixel, reflected across all eight arcs
  123.         crColour = GetColour(dAngle, crBright, crDark);
  124.         pDC->SetPixelV(p.x + lXoffset, p.y + lYoffset, crColour);
  125.  
  126.         crColour = GetColour(Pi_on_2 - dAngle, crBright, crDark);
  127.         pDC->SetPixelV(p.x + lYoffset, p.y + lXoffset, crColour);
  128.  
  129.         crColour = GetColour(Pi_on_2 + dAngle, crBright, crDark);
  130.         pDC->SetPixelV(p.x - lYoffset, p.y + lXoffset, crColour);
  131.  
  132.         crColour = GetColour(Pi - dAngle, crBright, crDark);
  133.         pDC->SetPixelV(p.x - lXoffset, p.y + lYoffset, crColour);
  134.  
  135.         crColour = GetColour(-Pi + dAngle, crBright, crDark);
  136.         pDC->SetPixelV(p.x - lXoffset, p.y - lYoffset, crColour);
  137.  
  138.         crColour = GetColour(-Pi_on_2 - dAngle, crBright, crDark);
  139.         pDC->SetPixelV(p.x - lYoffset, p.y - lXoffset, crColour);
  140.  
  141.         crColour = GetColour(-Pi_on_2 + dAngle, crBright, crDark);
  142.         pDC->SetPixelV(p.x + lYoffset, p.y - lXoffset, crColour);
  143.  
  144.         crColour = GetColour(-dAngle, crBright, crDark);
  145.         pDC->SetPixelV(p.x + lXoffset, p.y - lYoffset, crColour);
  146.  
  147.         //Advance the error term and the constant X axis step
  148.         lError += lYoffset++;
  149.  
  150.         //Check to see if error term has overflowed
  151.         if ((lError += lYoffset) >= 0)
  152.             lError -= --lXoffset * 2;
  153.  
  154.     } while (lYoffset <= lXoffset);    //Continue until halfway point
  155.  
  156. /////////////////////////////////////////////////////////////////////////////
  157. // CRoundSliderCtrl
  158.  
  159. IMPLEMENT_DYNAMIC(CRoundSliderCtrl, CSliderCtrl)
  160.  
  161. CRoundSliderCtrl::CRoundSliderCtrl()
  162. {
  163. //    m_strText = "%ld░";
  164.     m_strText = "%f";
  165.     m_nKnobRadius = 7;
  166.     m_nZero = 0;
  167.     m_bInverted = false;
  168.     m_bDragging = false;
  169.     m_bDrawRadioButton = true;
  170. }
  171.  
  172. CRoundSliderCtrl::~CRoundSliderCtrl()
  173. {
  174. }
  175.  
  176. BEGIN_MESSAGE_MAP(CRoundSliderCtrl, CSliderCtrl)
  177.     //{{AFX_MSG_MAP(CRoundSliderCtrl)
  178.     ON_WM_SIZE()
  179.     ON_WM_ERASEBKGND()
  180.     ON_WM_PAINT()
  181.     ON_WM_LBUTTONDOWN()
  182.     ON_WM_MOUSEMOVE()
  183.     ON_WM_LBUTTONUP()
  184.     ON_WM_KEYDOWN()
  185.     ON_WM_KEYUP()
  186.     //}}AFX_MSG_MAP
  187. END_MESSAGE_MAP()
  188.  
  189. void CRoundSliderCtrl::PreSubclassWindow() 
  190. {
  191.     CSliderCtrl::PreSubclassWindow();
  192.  
  193.     SetRange(0, 359, FALSE);
  194.     SetLineSize(1);
  195.     SetPageSize(10);
  196.  
  197.     Init();
  198. }
  199.  
  200. BOOL CRoundSliderCtrl::PreCreateWindow(CREATESTRUCT& cs) 
  201. {
  202.     if(!CSliderCtrl::PreCreateWindow(cs)) return FALSE;
  203.  
  204.     SetRange(0, 359, FALSE);
  205.     SetLineSize(1);
  206.     SetPageSize(10);
  207.  
  208.     Init();
  209.  
  210.     return TRUE;
  211. }
  212.  
  213. void CRoundSliderCtrl::OnSize(UINT nType, int cx, int cy) 
  214. {
  215.     CSliderCtrl::OnSize(nType, cx, cy);
  216.     
  217.     Init();
  218. }
  219.  
  220. void CRoundSliderCtrl::Init()
  221. {
  222.     CRect rc;
  223.     GetClientRect(rc);
  224.  
  225.     // Resize the window to make it square
  226.     rc.bottom = rc.right = max(rc.bottom, rc.right);
  227.  
  228.     // Get the vital statistics of the window
  229.     m_ptCenter = rc.CenterPoint();
  230.     m_ptCenter.y-=8;
  231.     m_nRadius = rc.bottom/2-(m_nKnobRadius+1)-5;
  232.  
  233.     // Set the window region so mouse clicks only activate the round section 
  234.     // of the slider
  235. /*
  236.  
  237.     m_rgn.DeleteObject(); 
  238.     SetWindowRgn(NULL, FALSE);
  239.     m_rgn.CreateEllipticRgnIndirect(rc);
  240.     SetWindowRgn(m_rgn, TRUE);
  241. */
  242.     // VerifyPos();
  243. }
  244.  
  245. #pragma warning(disable:4100) // Unreferenced formal parameter
  246. BOOL CRoundSliderCtrl::OnEraseBkgnd(CDC* pDC) 
  247. {
  248.     return TRUE;
  249. }
  250. #pragma warning(default:4100)
  251.  
  252. void CRoundSliderCtrl::OnPaint() 
  253. {
  254.     const int nMin = GetRangeMin();
  255.     const int nMax = GetRangeMax()+1;
  256.  
  257.     int nRadius = m_nRadius;
  258.  
  259.     // Draw (clear) the background
  260.     CRect rc;
  261.     GetClientRect(rc);
  262.  
  263.     CPaintDC dc_(this); // device context for painting
  264.  
  265. #ifdef USE_MEM_DC
  266.     CMemDC pDC(&dc);
  267. #else
  268.     CDC dcc;
  269.     dcc.CreateCompatibleDC(0);
  270.     CBitmap bmp;
  271.     bmp.CreateCompatibleBitmap( &dc_, rc.right, rc.bottom );
  272.     dcc.SelectObject( &bmp );
  273.     CDC* pDC = &dcc;
  274. #endif
  275.  
  276.     pDC->SelectStockObject(NULL_BRUSH);
  277.     pDC->FillSolidRect(rc, ::GetSysColor(COLOR_BTNFACE));
  278.  
  279.  
  280. //  pDC->FillSolidRect(rc, ::GetSysColor(COLOR_BACKGROUND));
  281.   // Draw the sliders channel
  282.     if (!m_bDrawRadioButton)
  283.     {
  284.         DrawCircle(pDC, m_ptCenter, nRadius--, ::GetSysColor(COLOR_3DDKSHADOW),::GetSysColor(COLOR_3DHIGHLIGHT));
  285.         DrawCircle(pDC, m_ptCenter, nRadius, ::GetSysColor(COLOR_3DSHADOW),::GetSysColor(COLOR_3DLIGHT));
  286.     }
  287.     int nPos = (((GetPos()-nMin)*360/(nMax-nMin)) + m_nZero + 360) % 360;
  288.     if(m_bInverted) nPos = 360-nPos;
  289.  
  290.     const double dPos = ((double)(nPos))*pi/180.0;
  291.  
  292. #pragma warning(disable:4244) // Disable warning "Converting 'double' to 'int', possible loss of data"
  293.     CPoint    ptKnobCenter;
  294.     
  295.     if (m_bDrawRadioButton)
  296.     {
  297.         ptKnobCenter = CPoint(    m_ptCenter.x + (nRadius-m_nKnobRadius) * sin(dPos), 
  298.                                 m_ptCenter.y - (nRadius-m_nKnobRadius) *
  299. cos(dPos));
  300.     }
  301.     else
  302.     {
  303.         ptKnobCenter = CPoint(    m_ptCenter.x + (nRadius) * sin(dPos), 
  304.                                 m_ptCenter.y - (nRadius) * cos(dPos));
  305.     }
  306. #pragma warning(default:4244)
  307.     nRadius+=2;
  308.  
  309.     DrawCircle(pDC, m_ptCenter, nRadius--, ::GetSysColor(COLOR_3DHIGHLIGHT),::GetSysColor(COLOR_3DDKSHADOW));
  310.     DrawCircle(pDC, m_ptCenter, nRadius--, ::GetSysColor(COLOR_3DLIGHT), ::GetSysColor(COLOR_3DSHADOW));
  311.     
  312.     // Draw the knob
  313.     int nKnobRadius;
  314.     if (m_bDrawRadioButton)
  315.     {
  316. #pragma warning(disable:4244) // Disable warning "Converting 'double' to 'int', possible loss of data"
  317.         nKnobRadius= m_nKnobRadius*0.8;
  318. #pragma warning(default:4244)
  319.     }
  320.     else
  321.     {
  322.         nKnobRadius= m_nKnobRadius;
  323.     }
  324.     const CRect rcKnob(    ptKnobCenter.x - nKnobRadius, ptKnobCenter.y - nKnobRadius, 
  325.                         ptKnobCenter.x + nKnobRadius, ptKnobCenter.y + nKnobRadius);
  326.  
  327.     CRgn rgnKnob;
  328.     rgnKnob.CreateEllipticRgnIndirect(rcKnob);
  329.     CBrush brKnob(::GetSysColor(COLOR_BTNFACE));
  330.     pDC->FillRgn(&rgnKnob, &brKnob);
  331.     rgnKnob.DeleteObject();
  332.  
  333.     if (!m_bDrawRadioButton)
  334.     {
  335.         if(m_bDragging)
  336.         {
  337.             DrawCircle(pDC, ptKnobCenter, --nKnobRadius, ::GetSysColor(COLOR_3DDKSHADOW),::GetSysColor(COLOR_3DHIGHLIGHT));
  338.             DrawCircle(pDC, ptKnobCenter, --nKnobRadius, ::GetSysColor(COLOR_3DSHADOW),::GetSysColor(COLOR_3DLIGHT));
  339.         }
  340.         else
  341.         {
  342.             DrawCircle(pDC, ptKnobCenter, --nKnobRadius, ::GetSysColor(COLOR_3DHIGHLIGHT), ::GetSysColor(COLOR_3DDKSHADOW));
  343.             DrawCircle(pDC, ptKnobCenter, --nKnobRadius, ::GetSysColor(COLOR_3DLIGHT), ::GetSysColor(COLOR_3DSHADOW));
  344.         }
  345.     }
  346.     else
  347.     {
  348.             DrawCircle(pDC, ptKnobCenter, --nKnobRadius, ::GetSysColor(COLOR_3DDKSHADOW),::GetSysColor(COLOR_3DHIGHLIGHT));
  349.             DrawCircle(pDC, ptKnobCenter, --nKnobRadius, ::GetSysColor(COLOR_3DSHADOW),::GetSysColor(COLOR_3DLIGHT));
  350.     }
  351.  
  352.     // Draw the focus circle on the inside of the knob
  353.     if (!m_bDrawRadioButton)
  354.         if(GetFocus() == this)
  355.         {
  356.             DrawCircle(pDC, ptKnobCenter, nKnobRadius-2, RGB(0, 0, 0), TRUE);
  357.         }
  358.  
  359.     // Draw the text
  360.     const CString strFormattedText = OnFormatText();
  361.  
  362.     if(!strFormattedText.IsEmpty())
  363.     {
  364.         CWnd* pOwner = GetParentOwner();
  365.         if(pOwner)
  366.         {
  367.             CFont* pFont = pOwner->GetFont();
  368.             pDC->SelectObject(pFont);
  369.         }
  370.  
  371.         const CSize szExtent = pDC->GetTextExtent(strFormattedText);
  372.         const CPoint ptText = CPoint(m_ptCenter.x - szExtent.cx/2, m_nRadius+m_ptCenter.y/* + szExtent.cy*/);
  373.  
  374.         pDC->SetBkMode(TRANSPARENT);
  375.         if(!IsWindowEnabled())
  376.         {
  377.             pDC->DrawState(ptText, szExtent, strFormattedText, DSS_DISABLED, TRUE, 0,(HBRUSH)NULL);
  378.         }
  379.         else
  380.         {
  381.             pDC->TextOut(ptText.x, ptText.y, strFormattedText);
  382.         }
  383.     }
  384.  
  385.     #ifdef USE_MEM_DC
  386.         CMemDC pDC(&dc);
  387.     #else
  388.         dc_.BitBlt( 0, 0, rc.right, rc.bottom, pDC, 0, 0, SRCCOPY );
  389.     #endif
  390.  
  391.     // Don't call CSliderCtrl::OnPaint()
  392. }
  393.  
  394. void CRoundSliderCtrl::OnLButtonDown(UINT nFlags, CPoint point) 
  395. {
  396.     if(!m_bDragging)
  397.     {
  398.         m_bDragging = true;
  399.         m_bDragChanged = false;
  400.         SetCapture();
  401.         SetFocus();
  402.         if(SetKnob(point))
  403.         {
  404.             m_bDragChanged = true;
  405.             PostMessageToParent(TB_THUMBTRACK);
  406.         }
  407.         RedrawWindow();
  408.     }
  409.     else
  410.     {
  411.         CSliderCtrl::OnLButtonDown(nFlags, point);
  412.     }
  413. }
  414.  
  415. void CRoundSliderCtrl::OnMouseMove(UINT nFlags, CPoint point) 
  416. {
  417.     if(m_bDragging)
  418.     {
  419.         if(SetKnob(point))
  420.         {
  421.             m_bDragChanged = true;
  422.             PostMessageToParent(TB_THUMBTRACK);
  423.             RedrawWindow();
  424.         }
  425.     }
  426.     else
  427.     {
  428.         CSliderCtrl::OnMouseMove(nFlags, point);
  429.     }
  430. }
  431.  
  432. void CRoundSliderCtrl::OnLButtonUp(UINT nFlags, CPoint point) 
  433. {
  434.     if(m_bDragging)
  435.     {
  436.         m_bDragging = false;
  437.         ::ReleaseCapture();
  438.         if(SetKnob(point))
  439.         {
  440.             PostMessageToParent(TB_THUMBTRACK);
  441.             m_bDragChanged = true;
  442.         }
  443.         if(m_bDragChanged)
  444.         {
  445.             PostMessageToParent(TB_THUMBPOSITION);
  446.             m_bDragChanged = false;
  447.         }
  448.         RedrawWindow();
  449.     }
  450.     else
  451.     {
  452.         CSliderCtrl::OnLButtonUp(nFlags, point);
  453.     }
  454. }
  455.  
  456. bool CRoundSliderCtrl::SetKnob(const CPoint& pt)
  457. {
  458.     const int nMin = GetRangeMin();
  459.     const int nMax = GetRangeMax()+1;
  460.  
  461.     CSize szDelta = pt - m_ptCenter;
  462.     if(m_bInverted) szDelta.cx *= -1;
  463.  
  464.     double dNewPos = 0.0;
  465.  
  466.     if(szDelta.cx != 0)
  467.     {
  468.         dNewPos = 90.0 - atan(-(double)szDelta.cy / (double)szDelta.cx) * 180.0 / pi;
  469.     }
  470.  
  471.     if(((szDelta.cx == 0) && (szDelta.cy >= 0)) || (szDelta.cx < 0))
  472.     {
  473.         dNewPos += 180.0;
  474.     }
  475.  
  476.     dNewPos -= m_nZero;
  477.  
  478.     while(dNewPos < 0.0) dNewPos += 360.0;
  479.     while(dNewPos >= 360.0) dNewPos -= 360.0;
  480.  
  481.     const int nNewPos = nMin + (int)(dNewPos*(nMax-nMin)/360.0);
  482.     const bool bChanged = (nNewPos != GetPos());
  483.  
  484.     if(bChanged)
  485.     {
  486.         SetPos(nNewPos);
  487.     }
  488.  
  489.     return bChanged;
  490. }
  491.  
  492. void CRoundSliderCtrl::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) 
  493. {
  494.     const int nMin = GetRangeMin();
  495.     const int nMax = GetRangeMax()+1;
  496.  
  497.     switch(nChar)
  498.     {
  499.     case VK_LEFT:
  500.     case VK_UP:
  501.         {
  502.             int nNewPos = GetPos()-GetLineSize();
  503.             while(nNewPos < nMin) nNewPos += (nMax - nMin);
  504.             SetPos(nNewPos);
  505.             RedrawWindow();
  506.             PostMessageToParent(TB_LINEUP);
  507.         }
  508.         break;
  509.     
  510.     case VK_RIGHT:
  511.     case VK_DOWN:
  512.         {
  513.             int nNewPos = GetPos()+GetLineSize();
  514.             while(nNewPos >= nMax) nNewPos -= (nMax - nMin);
  515.             SetPos(nNewPos);
  516.             RedrawWindow();
  517.             PostMessageToParent(TB_LINEDOWN);
  518.         }
  519.         break;
  520.  
  521.     case VK_PRIOR:
  522.         {
  523.             int nNewPos = GetPos()-GetPageSize();
  524.             while(nNewPos < nMin) nNewPos += (nMax - nMin);
  525.             SetPos(nNewPos);
  526.             RedrawWindow();
  527.             PostMessageToParent(TB_PAGEUP);
  528.         }
  529.         break;
  530.  
  531.     case VK_NEXT:
  532.         {
  533.             int nNewPos = GetPos()+GetPageSize();
  534.             while(nNewPos >= nMax) nNewPos -= (nMax - nMin);
  535.             SetPos(nNewPos);
  536.             RedrawWindow();
  537.             PostMessageToParent(TB_PAGEDOWN);
  538.         }
  539.         break;
  540.  
  541.     case VK_HOME:
  542.     case VK_END:
  543.         // Do nothing (ignore keystroke)
  544.         break;
  545.  
  546.     default:
  547.         CSliderCtrl::OnKeyDown(nChar, nRepCnt, nFlags);
  548.     }
  549. }
  550.  
  551. void CRoundSliderCtrl::OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags) 
  552. {
  553.     switch(nChar)
  554.     {
  555.     case VK_LEFT:
  556.     case VK_UP:
  557.     case VK_RIGHT:
  558.     case VK_DOWN:
  559.     case VK_PRIOR:
  560.     case VK_NEXT:
  561.         PostMessageToParent(TB_ENDTRACK);
  562.         break;
  563.  
  564.     case VK_HOME:
  565.     case VK_END:
  566.         // Do nothing
  567.         break;
  568.  
  569.     default:
  570.         CSliderCtrl::OnKeyUp(nChar, nRepCnt, nFlags);
  571.     }
  572. }
  573.  
  574. void CRoundSliderCtrl::PostMessageToParent(const int nTBCode) const
  575. {
  576.     CWnd* pWnd = GetParent();
  577.     if(pWnd) pWnd->PostMessage(WM_HSCROLL, (WPARAM)((GetPos() << 16) | nTBCode),(LPARAM)GetSafeHwnd());
  578. }
  579.  
  580. void CRoundSliderCtrl::SetScale (const float scale)
  581. {
  582.   m_scale = scale;
  583. }
  584. float CRoundSliderCtrl::GetScale (void) const
  585. {
  586.   return m_scale;
  587. }
  588. void CRoundSliderCtrl::SetText(const CString& strNewText)
  589. {
  590.     m_strText = strNewText;
  591. }
  592.  
  593. CString CRoundSliderCtrl::GetText() const
  594. {
  595.     return m_strText;
  596. }
  597.  
  598. void CRoundSliderCtrl::SetKnobRadius(const int nNewKnobRadius)
  599. {
  600.     ASSERT(nNewKnobRadius > 4);
  601.  
  602.     m_nKnobRadius = nNewKnobRadius;
  603. }
  604.  
  605. void CRoundSliderCtrl::SetDrawRadioButton(const bool nDrawRadioButton)
  606. {
  607.     m_bDrawRadioButton = nDrawRadioButton;
  608. }
  609.  
  610. int CRoundSliderCtrl::GetKnobRadius() const
  611. {
  612.     return m_nKnobRadius;
  613. }
  614.  
  615. void CRoundSliderCtrl::SetZero(const int nZero)
  616. {
  617.     ASSERT(nZero >= 0 && nZero < 360);
  618.  
  619.     m_nZero = nZero;
  620. }
  621.  
  622. int CRoundSliderCtrl::GetZero() const
  623. {
  624.     return m_nZero;
  625. }
  626.  
  627. void CRoundSliderCtrl::SetInverted(const bool bNewInverted)
  628. {
  629.     m_bInverted = bNewInverted;
  630. }
  631.  
  632. bool CRoundSliderCtrl::GetInverted()
  633. {
  634.     return m_bInverted;
  635. }
  636.  
  637. // Overrideables
  638. CString CRoundSliderCtrl::OnFormatText()
  639. {
  640.     CString strFormattedText;
  641.     strFormattedText.Format(GetText(), GetPos()*m_scale);
  642.     return strFormattedText;
  643. }
  644.  
  645. #ifdef _DEBUG
  646. void CRoundSliderCtrl::AssertValid() const
  647. {
  648.     CSliderCtrl::AssertValid();
  649.  
  650.     ASSERT(m_nZero >= 0 && m_nZero < 360);
  651.     ASSERT(m_nKnobRadius > 4);
  652. }
  653.  
  654. void CRoundSliderCtrl::Dump(CDumpContext& dc) const
  655. {
  656.     CSliderCtrl::Dump(dc);
  657.  
  658.     dc    << "m_strText = '" << m_strText << "'\n"
  659.         << "m_nKnobRadius = " << m_nKnobRadius << "\n"
  660.         << "m_nZero = " << m_nZero;
  661. }
  662. #endif // _DEBUG
  663.