65.9K
CodeProject 正在变化。 阅读更多。
Home

旋钮滑块控件

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.83/5 (6投票s)

2003年10月4日

2分钟阅读

viewsIcon

74999

downloadIcon

1953

一个实现了旋钮滑块的自定义用户控件。

引言

本文的目的是展示如何实现一个用户控件。 此外,其示例对希望使用旋转旋钮滑块控件的程序员很有用,并提供了示例。

背景

对于任何想要理解此示例和/或实现新示例的开发人员,需要了解如何从标准 MFC 控件类派生新的 MFC 控件类。

使用代码

该代码可以通过将 KbutsliderCtrl 类插入到您自己的项目中来使用,也可以通过在资源中添加一个新的滑块控件来使用。 该类可以通过创建它的实例或创建从此类派生的新类来直接使用。 当程序员想要捕获 OnLButtonUpOnLButtonDown 事件时,派生很有用。

函数 SetKnobNumSetKnobPosi 用于设置在圆形通道上滑动的每个旋钮的数量和位置。 这些函数还将使用 %(模)运算符更新控件的窗口,以防止溢出错误。 当然,为了获得每个旋钮的当前位置,实现了函数 GetKnobPosi

KbutsliderCtrl 类有一些私有函数,用于一些数学和图形运算,如下所示

  • 函数 GetCurentAngle 计算由垂直轴、中心点和指定点(通常是鼠标的坐标)组成的角度。
  • 函数 DetectNearestKnob 扫描旋钮,以识别具有与指定值最接近的角度值的旋钮。 在大多数情况下,最后两个函数一起使用。
  • 函数 CalculateKnobPosi 用于计算必须停留在通道上并描述指定角度的旋钮的位置。
  • 函数 DrawCircleDrawBitmapDrawText 用于显示图形控件的各个部分。
  • 函数 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 的代码帮助,我用它来创建无闪烁绘图上下文对象。 还要感谢其他开发人员,他们在本网站上分享了有趣的源代码。

© . All rights reserved.