Visual C++ 7.1Visual Studio 6Visual C++ 7.0Windows 2003Windows 2000Visual C++ 6.0Windows XPMFC中级开发Visual StudioWindowsC++
旋钮滑块控件






3.83/5 (6投票s)
2003年10月4日
2分钟阅读

74999

1953
一个实现了旋钮滑块的自定义用户控件。
引言
本文的目的是展示如何实现一个用户控件。 此外,其示例对希望使用旋转旋钮滑块控件的程序员很有用,并提供了示例。
背景
对于任何想要理解此示例和/或实现新示例的开发人员,需要了解如何从标准 MFC 控件类派生新的 MFC 控件类。
使用代码
该代码可以通过将 KbutsliderCtrl
类插入到您自己的项目中来使用,也可以通过在资源中添加一个新的滑块控件来使用。 该类可以通过创建它的实例或创建从此类派生的新类来直接使用。 当程序员想要捕获 OnLButtonUp
和 OnLButtonDown
事件时,派生很有用。
函数 SetKnobNum
和 SetKnobPosi
用于设置在圆形通道上滑动的每个旋钮的数量和位置。 这些函数还将使用 %
(模)运算符更新控件的窗口,以防止溢出错误。 当然,为了获得每个旋钮的当前位置,实现了函数 GetKnobPosi
。
KbutsliderCtrl
类有一些私有函数,用于一些数学和图形运算,如下所示
- 函数
GetCurentAngle
计算由垂直轴、中心点和指定点(通常是鼠标的坐标)组成的角度。 - 函数
DetectNearestKnob
扫描旋钮,以识别具有与指定值最接近的角度值的旋钮。 在大多数情况下,最后两个函数一起使用。 - 函数
CalculateKnobPosi
用于计算必须停留在通道上并描述指定角度的旋钮的位置。 - 函数
DrawCircle
、DrawBitmap
和DrawText
用于显示图形控件的各个部分。 - 函数
DrawLine
用于替代函数SetPixelV
,它是可选的。
展示了 OnPaint
例程
void KbutsliderCtrl::OnPaint() { int j; CPaintDC dc(this); // device context for painting CMemDC memDC(&dc); // derived memory context CMemDC *pDC = &memDC; // pointer to it int nRadius = m_nRadius; CRect rc; GetClientRect(rc); pDC->SelectStockObject(NULL_BRUSH); pDC->FillSolidRect(rc, ::GetSysColor(COLOR_BTNFACE)); DrawCircle(pDC, m_ptCenter, nRadius--, ::GetSysColor(COLOR_3DDKSHADOW), ::GetSysColor(COLOR_3DHIGHLIGHT)); DrawCircle(pDC, m_ptCenter, nRadius, ::GetSysColor(COLOR_3DSHADOW), ::GetSysColor(COLOR_3DLIGHT)); nRadius-=2; DrawCircle(pDC, m_ptCenter, nRadius--, ::GetSysColor(COLOR_3DHIGHLIGHT), ::GetSysColor(COLOR_3DDKSHADOW)); DrawCircle(pDC, m_ptCenter, nRadius--, ::GetSysColor(COLOR_3DLIGHT), ::GetSysColor(COLOR_3DSHADOW)); DrawBitmap(pDC,s_ButStateNew); for ( j=0; j<m_nKnobNum; j++ ) { const CPoint ptKnobCenter = CalculateKnobPosi(m_nKnobPosi[j]); int nKnobRadius = m_nKnobRadius; const CRect rcKnob(ptKnobCenter.x - nKnobRadius, ptKnobCenter.y - nKnobRadius, ptKnobCenter.x + nKnobRadius, ptKnobCenter.y + nKnobRadius); CRgn rgnKnob; rgnKnob.CreateEllipticRgnIndirect(rcKnob); CBrush brKnob(::GetSysColor(COLOR_BTNFACE)); pDC->FillRgn(&rgnKnob, &brKnob); rgnKnob.DeleteObject(); if(m_bDragging) { DrawCircle(pDC, ptKnobCenter, --nKnobRadius, ::GetSysColor(COLOR_3DDKSHADOW), ::GetSysColor(COLOR_3DHIGHLIGHT)); DrawCircle(pDC, ptKnobCenter, --nKnobRadius, ::GetSysColor(COLOR_3DSHADOW), ::GetSysColor(COLOR_3DLIGHT)); } else { DrawCircle(pDC, ptKnobCenter, --nKnobRadius, ::GetSysColor(COLOR_3DHIGHLIGHT), ::GetSysColor(COLOR_3DDKSHADOW)); DrawCircle(pDC, ptKnobCenter, --nKnobRadius, ::GetSysColor(COLOR_3DLIGHT), ::GetSysColor(COLOR_3DSHADOW)); } if(GetFocus() == this) { DrawCircle(pDC, ptKnobCenter, nKnobRadius-2, RGB(0, 0, 0), TRUE); if ( j == m_nKnobCrt ) { DrawCircle(pDC, ptKnobCenter, nKnobRadius-4, RGB(0, 0, 0), TRUE); } } } DrawText(pDC); }
关注点
我从这个项目中了解到的是,一些内部状态变量需要与窗口事件一起使用,以定义控件的所需行为。
历史
这是开发的第一个混合控件版本,它看起来像一个旋钮滑块。
致谢
我要感谢 Kyle Rule 的代码帮助,我用它来创建无闪烁绘图上下文对象。 还要感谢其他开发人员,他们在本网站上分享了有趣的源代码。