本文将详细介绍如何使用C#和GDI+技术实现一个自定义的温度计控件。这个控件具有以下特点:
首先,创建一个继承自Control
的自定义控件类:
C#using System;
using System.Collections.Generic;
using System.Drawing.Drawing2D;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace AppControls
{
public class ThermometerControl : Control
{
// 温度相关属性
private float _currentTemperature = 0;
private float _minTemperature = -20;
private float _maxTemperature = 50;
// 尺寸相关属性
private int _bulbRadius = 20;
// 颜色设置
private Color _mercuryColor = Color.Red;
private Color _backgroundColor = Color.White;
private Color _borderColor = Color.Black;
// 控件尺寸常量
private const int TUBE_WIDTH = 10;
private const int SCALE_LENGTH = 5;
private const int LEFT_MARGIN = 15;
private const int BOTTOM_MARGIN = 25;
// 球形底部半径属性
public int BulbRadius
{
get => _bulbRadius;
set
{
if (value != _bulbRadius && value >= 10 && value <= 50) // 设置合理的范围限制
{
_bulbRadius = value;
UpdateControlSize();
Invalidate();
}
}
}
// 温度相关属性
public float CurrentTemperature
{
get => _currentTemperature;
set
{
if (value != _currentTemperature)
{
_currentTemperature = Math.Max(_minTemperature, Math.Min(_maxTemperature, value));
Invalidate();
}
}
}
public float MinTemperature
{
get => _minTemperature;
set
{
if (value != _minTemperature)
{
_minTemperature = value;
Invalidate();
}
}
}
public float MaxTemperature
{
get => _maxTemperature;
set
{
if (value != _maxTemperature)
{
_maxTemperature = value;
Invalidate();
}
}
}
// 颜色属性
public Color MercuryColor
{
get => _mercuryColor;
set
{
if (value != _mercuryColor)
{
_mercuryColor = value;
Invalidate();
}
}
}
public Color BackgroundColor
{
get => _backgroundColor;
set
{
if (value != _backgroundColor)
{
_backgroundColor = value;
Invalidate();
}
}
}
public Color BorderColor
{
get => _borderColor;
set
{
if (value != _borderColor)
{
_borderColor = value;
Invalidate();
}
}
}
public ThermometerControl()
{
SetStyle(ControlStyles.DoubleBuffer |
ControlStyles.AllPaintingInWmPaint |
ControlStyles.UserPaint |
ControlStyles.ResizeRedraw, true);
UpdateControlSize();
}
// 更新控件尺寸
private void UpdateControlSize()
{
// 根据球形底部半径计算合适的控件尺寸
int minWidth = LEFT_MARGIN + _bulbRadius * 2 + SCALE_LENGTH + 35; // 35为刻度文本预留空间
int minHeight = _bulbRadius * 4 + BOTTOM_MARGIN; // 确保有足够空间显示温度计管体
MinimumSize = new Size(minWidth, minHeight);
if (Width < minWidth) Width = minWidth;
if (Height < minHeight) Height = minHeight;
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
Graphics g = e.Graphics;
g.SmoothingMode = SmoothingMode.AntiAlias;
// 计算关键尺寸
int bulbCenterX = LEFT_MARGIN + _bulbRadius;
int bulbCenterY = Height - BOTTOM_MARGIN - _bulbRadius;
int tubeHeight = Height - 2 * _bulbRadius - BOTTOM_MARGIN;
int tubeTop = _bulbRadius;
// 绘制温度计外壳
DrawThermometerBody(g, bulbCenterX, bulbCenterY, tubeHeight);
// 绘制水银柱
DrawMercury(g, bulbCenterX, bulbCenterY, tubeHeight);
// 绘制刻度
DrawScale(g, bulbCenterX, tubeTop, tubeHeight);
}
private void DrawThermometerBody(Graphics g, int bulbCenterX, int bulbCenterY, int tubeHeight)
{
using (Pen borderPen = new Pen(_borderColor, 2))
{
// 绘制管子
g.DrawLine(borderPen,
bulbCenterX - TUBE_WIDTH / 2, _bulbRadius,
bulbCenterX - TUBE_WIDTH / 2, bulbCenterY);
g.DrawLine(borderPen,
bulbCenterX + TUBE_WIDTH / 2, _bulbRadius,
bulbCenterX + TUBE_WIDTH / 2, bulbCenterY);
// 绘制球形底部
g.DrawEllipse(borderPen,
bulbCenterX - _bulbRadius,
bulbCenterY - _bulbRadius,
_bulbRadius * 2,
_bulbRadius * 2);
}
// 填充球形底部背景
using (SolidBrush bulbBrush = new SolidBrush(_backgroundColor))
{
g.FillEllipse(bulbBrush,
bulbCenterX - _bulbRadius + 1,
bulbCenterY - _bulbRadius + 1,
(_bulbRadius - 1) * 2,
(_bulbRadius - 1) * 2);
}
}
private void DrawMercury(Graphics g, int bulbCenterX, int bulbCenterY, int tubeHeight)
{
float temperatureRange = _maxTemperature - _minTemperature;
float temperatureHeight = (_currentTemperature - _minTemperature) / temperatureRange;
int mercuryHeight = (int)(tubeHeight * temperatureHeight);
using (SolidBrush mercuryBrush = new SolidBrush(_mercuryColor))
{
// 填充管中的水银
g.FillRectangle(mercuryBrush,
bulbCenterX - TUBE_WIDTH / 2 + 2,
bulbCenterY - mercuryHeight,
TUBE_WIDTH - 3,
mercuryHeight);
// 填充球部的水银
g.FillEllipse(mercuryBrush,
bulbCenterX - _bulbRadius + 2,
bulbCenterY - _bulbRadius + 2,
(_bulbRadius - 2) * 2,
(_bulbRadius - 2) * 2);
}
}
private void DrawScale(Graphics g, int centerX, int topY, int height)
{
using (Pen scalePen = new Pen(_borderColor, 1))
using (Font scaleFont = new Font("Arial", 8))
using (StringFormat sf = new StringFormat { Alignment = StringAlignment.Near })
{
int scaleCount = 10;
float temperatureStep = (_maxTemperature - _minTemperature) / scaleCount;
float pixelStep = height / (float)scaleCount;
for (int i = 0; i <= scaleCount; i++)
{
int y = topY + (int)(i * pixelStep);
// 绘制刻度线
g.DrawLine(scalePen,
centerX + TUBE_WIDTH / 2,
y,
centerX + TUBE_WIDTH / 2 + SCALE_LENGTH,
y);
// 绘制温度值
float temperature = _maxTemperature - i * temperatureStep;
g.DrawString(
temperature.ToString("F0") + "°",
scaleFont,
Brushes.Black,
new RectangleF(
centerX + TUBE_WIDTH / 2 + SCALE_LENGTH + 2,
y - 6,
30,
12),
sf);
}
}
}
}
}
C#DrawThermometerBody() // 绘制温度计外壳
DrawMercury() // 绘制水银柱
DrawScale() // 绘制刻度
这个温度计控件实现了基本的温度显示功能,具有良好的可扩展性和自定义性。通过GDI+绘图技术,我们实现了平滑的显示效果和专业的外观。该控件可以用于各种需要温度显示的应用场景,如天气站、工业控制等领域。
本文作者:rick
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!