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

温度计控件

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.85/5 (59投票s)

2007年6月11日

CPOL

2分钟阅读

viewsIcon

250584

downloadIcon

6657

创建模拟风格的温度计

Screenshot - Thermometer_demo.jpg

引言

本文演示了一个用 C# 编写的复杂的模拟风格温度计控件。 该控件使用纯托管代码。 大多数视觉元素都可以通过控件的属性进行调整。

布局

由于该控件的灵活性,它不仅可以用于显示度数,还可以用于显示各种数据。

Screenshot - Layouts.jpg

架构

该控件由 2 个类组成:ManometerBaseThermometer

Screenshot - architecture.jpg

实现是在 Thermometer 类中完成的。

代码

所有绘制都在 Thermometer 类的 OnPaint 方法中完成。 每个元素都有自己的 Paint 方法,这些方法被标记为 protected virtual

protected override void OnPaint(PaintEventArgs e)
{
    // Set smoothingmode to AntiAlias
    e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
    // Shadow
    PaintShadow(e.Graphics);
    // Background
    PaintBackground(e.Graphics);
    // Border
    PaintBorder(e.Graphics);
    // Inner shadow
    PaintInnerShadow(e.Graphics);
    // Bars
    PaintBars(e.Graphics);
    // Numbers
    PaintNumbers(e.Graphics);
    // Paint the text(s)
    PaintText(e.Graphics);
    // Paint the Arrows
    PaintArrows(e.Graphics);
    // Reflex
    PaintReflex(e.Graphics);
    // Reset smoothingmode
    e.Graphics.SmoothingMode = SmoothingMode.Default;
}

绘制数字

大多数方法都很简单,但将数字对齐在椭圆中有点棘手。

protected virtual void PaintNumbers(Graphics g)
{
    double tmpAngle = StartAngle;
    for (double d = Min; d<= Max; d+= Interval)
    {
        String text = Math.Round(d, Decimals).ToString();
        PointF p = 
            CalcTextPosition(
            tmpAngle, MeasureText(g, text, Font, (int)numberRect.Width));
        if (ClockWise)
            tmpAngle -= NumberSpacing;
        else
            tmpAngle += NumberSpacing;
            g.DrawString(text, Font, new SolidBrush(ForeColor), p);
    }
}

解决方案是找到文本的中心点,然后根据文本在椭圆中的位置及其尺寸来计算偏移量。

private PointF CalcTextPosition(double a, SizeF size)
{
    PointF p = PointInEllipse(numberRect, a);
    p.X -= (float)((size.Width/2)*(1 + Math.Cos(Convert.ToRadians(a))));
    p.Y -= (float)((size.Height/2)*(1 - Math.Sin(Convert.ToRadians(a))));
    return p;
}

私有方法 CalcTextPosition 调用 PointInEllipse。 此方法根据角度和椭圆的大小计算椭圆中的一个点,这是一个简单的数学运算。

private static PointF PointInEllipse(RectangleF rect , double angle)
{
    double r1 = rect.Width/2;
    double r2 = rect.Height/2;
    double x = 
        (float)(r1 * Math.Cos(Convert.ToRadians(angle))) + r1 + rect.X;
    double y = 
        -(float)(r2 * Math.Sin(Convert.ToRadians(angle))) + r2 + rect.Y;
    return new PointF((float)x, (float)y);
}

使用代码

要测试该控件,请下载演示项目,然后构建并运行它。 要更改控件的外观,请使用属性

  • Interval - 控件上每个数字之间的间隔;这是一个浮点数。
  • Max - 量程上的最大值。
  • Min - 量程上的最小值。
  • StartAngle - 起始角度(以度为单位)。
  • StoreMax - 显示存储的最大值(红色箭头)。
  • StoredMax - 存储的最大值。
  • TextDescription - 设置在控件上显示的下方文本。
  • TextUnit - 设置文本以描述所使用的单位。
  • Value - 箭头的值和点。
  • ArrowColor - 箭头的颜色。
  • BackColor - 控件的内部颜色。
  • BarsBetweenNumbers - 两个显示的数字之间的线条数。 请注意,线条的对齐取决于属性 NumberSpacingInterval
  • BorderWidth - 外边框的宽度。
  • ClockWise - 按顺时针或逆时针方向排列数字。
  • Decimals - 显示的小数位数;默认为 0。
  • NumberSpacing - 数字之间的间距(以度为单位)。

历史

  • 2007 年 6 月 9 日:初始发布。
  • 2007 年 7 月 8 日
    • 修复了某些对象上缺少 dispose 的问题。
    • 修复了一个 bug,当从工具栏添加控件时,设计器会挂起。
    • 更改了 Unit 和 Description 属性上的默认文本。
    • 在此文档中添加了布局部分。
    • 添加了演示下载。
    • 从源代码管理中移除了解决方案。
© . All rights reserved.