C# Winform中制作精美控件(2)

news2024/10/5 18:34:08

仓库温度监控系统重有个控件,就是温度监控,还是比较精美的,那么我们来看看制作的要点有哪些。

前面我们讨论过布局和圆角按钮。这节主要关注温度计控件

1. 布局: 两个Panel将界面分位上下两个部分,Dock.Top  Dock.Fill分别设置给他们。

2.  温度按钮采用的有自定义的圆角按钮

3. 温度计控件

从设置部分,我们可以看到最重要的几个属性是:

Value=10

MaxValue=50    

MercuryColor 水银颜色

GlassTubeColor 玻璃管颜色

// 
// uTemperValue
// 
this.uTemperValue.BMaxValue = new decimal(new int[] {
30,
0,
0,
0});
this.uTemperValue.BMinValue = new decimal(new int[] {
0,
0,
0,
0});
this.uTemperValue.Font = new System.Drawing.Font("宋体", 6.6F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.uTemperValue.ForeColor = System.Drawing.Color.White;
this.uTemperValue.GlassTubeColor = System.Drawing.Color.FromArgb(((int)(((byte)(211)))), ((int)(((byte)(211)))), ((int)(((byte)(211)))));
this.uTemperValue.LeftTemperatureUnit = STMS.STMSApp.UControls.UThermometer.TemperatureUnit.C;
this.uTemperValue.Location = new System.Drawing.Point(254, 6);
this.uTemperValue.MaxValue = new decimal(new int[] {
50,
0,
0,
0});
this.uTemperValue.MercuryColor = System.Drawing.Color.FromArgb(((int)(((byte)(255)))), ((int)(((byte)(77)))), ((int)(((byte)(59)))));
this.uTemperValue.MinValue = new decimal(new int[] {
0,
0,
0,
0});
this.uTemperValue.Name = "uTemperValue";
this.uTemperValue.Size = new System.Drawing.Size(79, 150);
this.uTemperValue.SpCount = 5;
this.uTemperValue.TabIndex = 3;
this.uTemperValue.Value = new decimal(new int[] {
10,
0,
0,
0});
this.uTemperValue.ValueColor = System.Drawing.Color.White;
this.uTemperValue.ValueFont = new System.Drawing.Font("宋体", 7.8F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
// 
// SRTemperLight
// 
this.SRTemperLight.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(137)))), ((int)(((byte)(201)))), ((int)(((byte)(151)))));
this.SRTemperLight.Location = new System.Drawing.Point(110, 117);
this.SRTemperLight.Name = "SRTemperLight";
this.SRTemperLight.Size = new System.Drawing.Size(20, 20);
this.SRTemperLight.TabIndex = 2;

4. 温度计控件源码

public partial class UThermometer : UserControl
{
    public UThermometer()
    {
        InitializeComponent();
        this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
        this.SetStyle(ControlStyles.DoubleBuffer, true);
        this.SetStyle(ControlStyles.ResizeRedraw, true);
        this.SetStyle(ControlStyles.Selectable, true);
        this.SetStyle(ControlStyles.SupportsTransparentBackColor, true);
        this.SetStyle(ControlStyles.UserPaint, true);
        this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.None;
        this.Size = new Size(60, 200);
    }

    private Color glassTubeColor = Color.FromArgb(211, 211, 211);
    [Description("玻璃管颜色"), Category("自定义")]
    public Color GlassTubeColor
    {
        get { return glassTubeColor; }
        set
        {
            glassTubeColor = value;
            Refresh();
        }
    }

    private Color mercuryColor = Color.FromArgb(255, 77, 59);
    [Description("水银颜色"), Category("自定义")]
    public Color MercuryColor
    {
        get { return mercuryColor; }
        set
        {
            mercuryColor = value;
            Refresh();
        }
    }

    private decimal minValue = 0;
    [Description("最小值"), Category("自定义")]
    public decimal MinValue
    {
        get { return minValue; }
        set
        {
            minValue = value;
            Refresh();
        }
    }

    private decimal maxValue = 50;
    [Description("最大值"), Category("自定义")]
    public decimal MaxValue
    {
        get { return maxValue; }
        set
        {
            maxValue = value;
            Refresh();
        }
    }

    private decimal mValue = 10;
    [Description("刻度值"), Category("自定义")]
    public decimal Value
    {
        get { return mValue; }
        set
        {
            mValue = value;
            Refresh();
        }
    }

    private int spCount = 6;
    [Description("分隔份数"), Category("自定义")]
    public int SpCount
    {
        get { return spCount; }
        set
        {
            if (value <= 0)
                return;
            spCount = value;
            Refresh();
        }
    }
    [Description("获取或设置控件显示的文字的字体"), Category("自定义")]
    public override Font Font
    {
        get
        {
            return base.Font;
        }
        set
        {
            base.Font = value;
            Refresh();
        }
    }

    [Description("获取或设置控件的文字及刻度颜色"), Category("自定义")]
    public override System.Drawing.Color ForeColor
    {
        get
        {
            return base.ForeColor;
        }
        set
        {
            base.ForeColor = value;
            Refresh();
        }
    }

    private Color valueColor = Color.White;
    [Description("温度值的文本颜色"), Category("自定义")]
    public Color ValueColor
    {
        get
        {
            return valueColor;
        }
        set
        {
            valueColor = value;
            Refresh();
        }
    }

    private Font valueFont = new Font("宋体", 10);
    public Font ValueFont
    {
        get
        {
            return valueFont;
        }
        set
        {
            valueFont = value;
            Refresh();
        }
    }




    private TemperatureUnit leftTemperatureUnit = TemperatureUnit.C;
    [Description("左侧刻度单位,不可为none"), Category("自定义")]
    public TemperatureUnit LeftTemperatureUnit
    {
        get { return leftTemperatureUnit; }
        set
        {
            if (value == TemperatureUnit.None)
                return;
            leftTemperatureUnit = value;
            Refresh();
        }
    }

    /// <summary>
    /// 高温线的温度值
    /// </summary>
    public decimal bMaxValue;
    public decimal BMaxValue
    {
        get { return bMaxValue; }
        set
        {
            bMaxValue = value;
            Refresh();
        }
    }

    /// <summary>
    ///低温线的温度值
    /// </summary>
    public decimal bMinValue;
    public decimal BMinValue
    {
        get { return bMinValue; }
        set
        {
            bMinValue = value;
            Refresh();
        }
    }

    Rectangle m_rectWorking; //工作区
    Rectangle m_rectLeft;//刻度区域

    /// <summary>
    /// 温度计单位
    /// </summary>
    public enum TemperatureUnit
    {
        /// <summary>
        /// 不显示
        /// </summary>
        None,
        /// <summary>
        /// 摄氏度
        /// </summary>
        C,
        /// <summary>
        /// 华氏度
        /// </summary>
        F,
        /// <summary>
        /// 开氏度
        /// </summary>
        K,
        /// <summary>
        /// 兰氏度
        /// </summary>
        R,
        /// <summary>
        /// 列氏度
        /// </summary>
        Re
    }

    private void UThermometer_SizeChanged(object sender, EventArgs e)
    {
        m_rectWorking = new Rectangle(this.Width / 2 - this.Width / 8, this.Width / 4, this.Width / 4, this.Height - this.Width / 2);
        m_rectLeft = new Rectangle(this.Width / 2 - this.Width / 8, m_rectWorking.Top + m_rectWorking.Width / 2, (this.Width - this.Width / 4) / 2 - 2, m_rectWorking.Height - m_rectWorking.Width * 2);
    }

    /// <summary>
    /// 画温度计
    /// </summary>
    /// <param name="e"></param>
    protected override void OnPaint(PaintEventArgs e)
    {
        base.OnPaint(e);
        var g = e.Graphics;
        g.SmoothingMode = SmoothingMode.HighQuality;
        //玻璃管
        GraphicsPath path = new GraphicsPath();
        path.AddLine(m_rectWorking.Left, m_rectWorking.Bottom, m_rectWorking.Left, m_rectWorking.Top + m_rectWorking.Width / 2);
        path.AddArc(new Rectangle(m_rectWorking.Left, m_rectWorking.Top, m_rectWorking.Width, m_rectWorking.Width), 180, 180);
        path.AddLine(m_rectWorking.Right, m_rectWorking.Top + m_rectWorking.Width / 2, m_rectWorking.Right, m_rectWorking.Bottom);
        path.CloseAllFigures();
        g.FillPath(new SolidBrush(glassTubeColor), path);
        //底部
        var rectDi = new Rectangle(this.Width / 2 - m_rectWorking.Width, m_rectWorking.Bottom - m_rectWorking.Width - 2, m_rectWorking.Width * 2, m_rectWorking.Width * 2);
        g.FillEllipse(new SolidBrush(glassTubeColor), rectDi);
        g.FillEllipse(new SolidBrush(mercuryColor), new Rectangle(rectDi.Left + 4, rectDi.Top + 4, rectDi.Width - 8, rectDi.Height - 8));

        //值
        float fltHeightValue = (float)(Value / (maxValue - minValue) * m_rectLeft.Height);
        RectangleF rectValue = new RectangleF(m_rectWorking.Left + 4, m_rectLeft.Top + (m_rectLeft.Height - fltHeightValue), m_rectWorking.Width - 8, fltHeightValue + (m_rectWorking.Height - m_rectWorking.Width / 2 - m_rectLeft.Height));
        g.FillRectangle(new SolidBrush(mercuryColor), rectValue);
        //
        //刻度
        decimal decSplit = (maxValue - minValue) / spCount;
        decimal decSplitHeight = m_rectLeft.Height / spCount;
        for (int i = 0; i <= spCount; i++)
        {
            g.DrawLine(new Pen(new SolidBrush(ForeColor), 1), new PointF(m_rectLeft.Left + 1, (float)(m_rectLeft.Bottom - decSplitHeight * i)), new PointF(m_rectLeft.Left + 8, (float)(m_rectLeft.Bottom - decSplitHeight * i)));

            var valueLeft = (minValue + decSplit * i).ToString("0.#");
            var sizeLeft = g.MeasureString(valueLeft, Font);
            g.DrawString(valueLeft, Font, new SolidBrush(ForeColor), new PointF(m_rectLeft.Left - sizeLeft.Width-2, m_rectLeft.Bottom - (float)decSplitHeight * i - 5));
            if (i != spCount)
            {
                if (decSplitHeight > 40)
                {
                    var decSp1 = decSplitHeight / 10;
                    for (int j = 1; j < 10; j++)
                    {
                        if (j == 5)
                        {
                            g.DrawLine(new Pen(new SolidBrush(ForeColor), 1), new PointF(m_rectLeft.Left + 1, (m_rectLeft.Bottom - (float)decSplitHeight * i - ((float)decSp1 * j))), new PointF(m_rectLeft.Left + 8, (m_rectLeft.Bottom - (float)decSplitHeight * i - ((float)decSp1 * j))));

                        }
                        else
                        {
                            g.DrawLine(new Pen(new SolidBrush(ForeColor), 1), new PointF(m_rectLeft.Left + 1, (m_rectLeft.Bottom - (float)decSplitHeight * i - ((float)decSp1 * j))), new PointF(m_rectLeft.Left + 5, (m_rectLeft.Bottom - (float)decSplitHeight * i - ((float)decSp1 * j))));

                        }
                    }
                }
                else if (decSplitHeight > 10)
                {
                    g.DrawLine(new Pen(new SolidBrush(ForeColor), 1), new PointF(m_rectLeft.Left + 1, (m_rectLeft.Bottom - (float)decSplitHeight * i - (float)decSplitHeight / 2)), new PointF(m_rectLeft.Left + 5, (m_rectLeft.Bottom - (float)decSplitHeight * i - (float)decSplitHeight / 2)));

                }
            }
        }

        //单位
        string strLeftUnit = GetUnitChar(leftTemperatureUnit);
        g.DrawString(strLeftUnit, Font, new SolidBrush(ForeColor), new PointF(m_rectLeft.Left + 2, 5));

        float bmaxValue = (float)(BMaxValue / (maxValue - minValue) * m_rectLeft.Height);
        float bminValue = (float)(BMinValue / (maxValue - minValue) * m_rectLeft.Height);

        //低温线
        g.DrawLine(new Pen(new SolidBrush(Color.Blue), 1), m_rectWorking.Left + 2, m_rectLeft.Top + (m_rectLeft.Height - bminValue), m_rectWorking.Left + m_rectWorking.Width, m_rectLeft.Top + (m_rectLeft.Height - bminValue));
        //高温线
        g.DrawLine(new Pen(new SolidBrush(Color.Orange), 1), m_rectWorking.Left + 2, m_rectLeft.Top + (m_rectLeft.Height - bmaxValue), m_rectWorking.Left + m_rectWorking.Width, m_rectLeft.Top + (m_rectLeft.Height - bmaxValue));

        var sizeValue = g.MeasureString(mValue.ToString("0.##"), ValueFont);

        g.DrawString(mValue.ToString("0.##"), ValueFont, new SolidBrush(ValueColor), new PointF(rectDi.Left + (rectDi.Width - sizeValue.Width) / 2, rectDi.Top + (rectDi.Height - sizeValue.Height) / 2 + 1));

    }

    private string GetUnitChar(TemperatureUnit unit)
    {
        string strUnit = "℃";
        switch (unit)
        {
            case TemperatureUnit.C:
                strUnit = "℃";
                break;
            case TemperatureUnit.F:
                strUnit = "℉";
                break;
            case TemperatureUnit.K:
                strUnit = "K";
                break;
            case TemperatureUnit.R:
                strUnit = "°R";
                break;
            case TemperatureUnit.Re:
                strUnit = "°Re";
                break;
        }
        return strUnit;
    }
}

partial class UThermometer
{
    /// <summary> 
    /// 必需的设计器变量。
    /// </summary>
    private System.ComponentModel.IContainer components = null;

    /// <summary> 
    /// 清理所有正在使用的资源。
    /// </summary>
    /// <param name="disposing">如果应释放托管资源,为 true;否则为 false。</param>
    protected override void Dispose(bool disposing)
    {
        if (disposing && (components != null))
        {
            components.Dispose();
        }
        base.Dispose(disposing);
    }

    #region 组件设计器生成的代码

    /// <summary> 
    /// 设计器支持所需的方法 - 不要修改
    /// 使用代码编辑器修改此方法的内容。
    /// </summary>
    private void InitializeComponent()
    {
        this.SuspendLayout();
        // 
        // UThermometer
        // 
        this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 15F);
        this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
        this.Name = "UThermometer";
        this.Size = new System.Drawing.Size(67, 230);
        this.SizeChanged += new System.EventHandler(this.UThermometer_SizeChanged);
        this.ResumeLayout(false);

    }

    #endregion
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1865228.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Web3 ETF 的软件开发框架

Web3 ETF 的软件开发框架主要包含以下几个方面&#xff0c;需要说明的是&#xff0c;Web3 ETF 仍处于早期发展阶段&#xff0c;相关技术和标准尚未成熟。在开发 Web3 ETF 时&#xff0c;需要谨慎评估风险&#xff0c;并做好安全防范措施。北京木奇移动技术有限公司&#xff0c;…

【博士每天一篇文献-算法】Fearnet Brain-inspired model for incremental learning

阅读时间&#xff1a;2023-12-16 1 介绍 年份&#xff1a;2017 作者&#xff1a;Ronald Kemker&#xff0c;美国太空部队&#xff1b;Christopher Kanan&#xff0c;罗切斯特大学 期刊&#xff1a; arXiv preprint 引用量&#xff1a;520 Kemker R, Kanan C. Fearnet: Brain-…

手机恢复已删除的照片,2个实用方法,有效避免数据丢失

手机相册&#xff0c;简直就是我们生活中的宝藏库&#xff0c;里面储存着我们拍摄的每一张照片。但是&#xff0c;有时候我们会因为手残或者意外情况&#xff0c;不小心把手机照片给删了&#xff0c;这简直是让我们的生活留下了无法弥补的遗憾啊&#xff01; 为了帮助大家避免…

如何封装自动化测试框架?

封装自动化测试框架&#xff0c;测试人员不用关注框架的底层实现&#xff0c;根据指定的规则进行测试用例的创建、执行即可&#xff0c;这样就降低了自动化测试门槛&#xff0c;能解放出更多的人力去做更深入的测试工作。 本篇文章就来介绍下&#xff0c;如何封装自动化测试框…

“天下第一痛”到底有多疼?三叉神经痛有哪些症状

三叉神经是负责脸部、口腔、鼻腔和舌前的感觉和咀嚼肌的运动的颅脑最粗大的神经。当三叉神经被干扰后&#xff0c;它所支配的面部区域内就会出现一种反复发作的短暂性剧烈疼痛&#xff0c;每次痛持续数秒至数十秒&#xff0c;可严重影响患者生活质量。 三叉神经痛的主要特征是在…

云渲染平台千千万,哪个平台更划算!?

渲染100 以高性价比著称&#xff0c;是预算有限的小伙伴首选。 15分钟0.2,60分钟内0.8;注册填邀请码【7788】可领30元礼包和免费渲染券) 提供了多种机器配置选择(可以自行匹配环境)最高256G大内存机器&#xff0c;满足不同用户需求。支持3dmax&#xff0c;cr&#xff0c;vr所…

他们说:优秀的程序员应该对代码保持追求

在当今技术飞速发展的时代&#xff0c;快速开发成为了企业竞争的关键。为了满足市场需求&#xff0c;降低开发成本&#xff0c;越来越多的企业开始关注低代码开发平台。 传统的应用开发流程通常需要大量的人力资源和时间投入&#xff0c;使得企业在产品迭代的速度上受限。而低…

筑梦未来:高考后,专业与学校的天秤两端

前言 2024 年高考落幕&#xff0c;几人欢喜几人愁&#xff0c;作为一个过来人&#xff0c;希望每一个努力的悻悻学子都能得偿所愿&#xff0c;不负年华&#xff0c;报的心仪的志愿。 接下来我将从三个方向进行一些分析建议&#xff0c;在专业与大学排名间做出适当的权衡。 专…

AI办公自动化:多音频轨电影视频抽取出英语音频

很多电影视频是有中、英、粤语等多个音频轨的&#xff0c;如果直接转换成音频&#xff0c;很有可能不是自己想要的那种语音。 可以先查看音频流信息&#xff0c;确定属于哪个音频轨&#xff1a; Reading video file: E:\1-7\比得兔1.mp4 输出音频流信息 Available audio str…

Flask无法Debug

问题描述 Flask Debug的时候&#xff0c;可能会无法进入断点。我使用的是pycharm CE版本。 解决方案 确保pycharm安装路径不带空格。&#xff08;带空格路径导致debug程序启动报错&#xff09;Gevent compatible&#xff0c;这个东西老的pycharm版本必须勾选它&#xff0c;新…

郑州大学人工智能简答

第一章 1. 什么是人工智能&#xff1f; 人工智能又称机器智能&#xff0c;主要研究人工的方法和技术开发智能机器或智能系统&#xff0c;以模仿、延伸和扩展人的智能、生物智能、自然智能&#xff0c;实现机器的智能行为。 人工智能的定义分四类&#xff1a; &#xff08;1&am…

如何用Vue3构建一个功能齐全的投资组合管理仪表盘?

本文由ScriptEcho平台提供技术支持 项目地址&#xff1a;传送门 使用 Vue 构建一个功能齐全的投资组合仪表板 应用场景介绍 本代码展示了一个使用 Vue 构建的投资组合仪表板&#xff0c;它允许用户查看和管理他们的投资组合。仪表板提供了以下功能&#xff1a; 实时显示投…

EWM学习之旅-1-EWM100

系统学习一个业务模块已经变得越来越重要&#xff0c;开始吧&#xff0c;EWM&#xff01; EWM的Learning Journey中包括7本 ebook,100/110/115/120/125/130/140&#xff0c;一本一本的啃吧&#xff0c;相信很多内容是重复的。 EWM100很适合初学者&#xff0c;了解概念术语&…

健身房管理系统

摘 要 随着人们健康意识的增强&#xff0c;健身房作为一种提供健身服务的场所&#xff0c;受到越来越多人的关注和喜爱。然而&#xff0c;传统的健身房管理方式存在诸多问题&#xff0c;如信息管理不便捷、会员管理不规范等。为了解决这些问题&#xff0c;本文设计并实现了一款…

螺丝扭断力试验机SJ-12

一、设备简介&#xff1a; 螺丝扭断力试验机用于测试螺丝的耐扭断力。本机将螺丝产品所受到轴向扭转力与反作用力&#xff0c;常用扭力扳手来计量。本机可对产品进行转力测、锁动测试、锁动扭力测试等多种测试方式。 二、设备使用&#xff1a; 1、将螺丝强度扭力试验机底座锁于…

【数据结构】——链表经典OJ(leetcode)

文章目录 一、 相交链表二、 反转链表三、 回文链表四、 环形链表五、 环形链表 II六、 合并两个有序链表七、 两数相加八、 删除链表的倒数第N个节点九、 随机链表的复制 一、 相交链表 双指针法 struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListN…

makefile中的用户自定义变量

makefile: CC gcc CFLAGS -Isub -Isub -O2 OBJS add_int.o add_float.o sub_int.o sub_float.o main.o TARGET ccb RM rm -f $(TARGET):$(OBJS)$(CC) -o $(TARGET) $(OBJS) $(CFLAGS) $(OBJS):%.o:%.c$(CC) -c $(CFLAGS) $< -o $ clean:-$(RM) $(TARGET) $(OBJS)编译运…

电脑硬盘数据恢复,4个方法,轻松恢复数据

在数字化时代的浪潮中&#xff0c;电脑硬盘不仅是存储数据的仓库&#xff0c;更是我们生活、工作、学习的记忆宫殿。然而&#xff0c;当这个宫殿中的一部分珍贵记忆突然消失&#xff0c;仿佛历史的片段被无情地抹去&#xff0c;我们不禁会感到焦虑和恐慌。此时&#xff0c;电脑…

苹果电脑安装双系统步骤 教你苹果电脑如何装双系统

许多人刚买来苹果电脑时&#xff0c;对苹果的IOS操作系统比较陌生&#xff0c;显得非常不适应&#xff0c;都会去想吧苹果电脑去安装一个自己熟悉的Windows系统&#xff0c;方便自己办公娱乐&#xff0c;那么苹果电脑安装双系统的步骤怎么样呢 小编给大家介绍下吧。 许多人刚买…

探究电子电路中的电压与电平转换

1. 引言 昨天跟好朋友讨论一个项目的时候,我朋友就给我画了一个简化版的电路图&#xff0c;如下图所示&#xff1a; 总觉得这个电路怪怪的&#xff0c;clk信号怎么直接接稳压电路呢。就产生了一个疑问&#xff0c;电平转换和电压转换的区别是啥&#xff1f;稳压电路还有升降压…