上位机学习记录组合控件的应用(控件堆叠+重置)与UI导航栏的编写

Posted 聆听微风

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了上位机学习记录组合控件的应用(控件堆叠+重置)与UI导航栏的编写相关的知识,希望对你有一定的参考价值。

上位机学习记录(4)组合控件的应用(控件堆叠+重置)与UI导航栏的编写

(一)组合控件

组合控件效果:

  1. 鼠标悬浮上去,会有颜色的渐变
  2. 点击第一个控件后会在控件出现下端会有白色矩形块。点击第二个控件以后,第一个控件的白色矩形块会消失

设计思想:

  1. 主体上:label 和Picturebox 控件的组合
  2. 粗略来看需要设计的属性:鼠标移入的颜色变深,鼠标点击时产生的小方块,鼠标点击的激活状态
  3. 考虑到这个方块可能与用户授权有关,所以需要考虑权限属性

设计如下:

第一步 先把label 与Picturebox 控件粘贴到一起。进行适当的位置调整。注意,控件字体一般设置“微软雅黑”,而非宋体

红框字体为需要配置的属性信息

第二步 编写当前控件需要实现的属性

代码如下:

       public NaviButton()
        
            InitializeComponent();
            SavedBackColor = this.BackColor;
        

        private Color SavedBackColor;


        private Image naviImage = Properties.Resources.RealData;

        [Browsable(true)]
        [Category("自定义属性")]
        [Description("导航按钮图片设置")]
        public Image NaviImage
        
            get  return naviImage; 
            set
            
                naviImage = value;

                this.pic_Main.Image = naviImage;
            
        

        private string naviName = "实时监控";
        [Browsable(true)]
        [Category("自定义属性")]
        [Description("导航按钮名称设置")]
        public string NaviName
        
            get  return naviName; 
            set
            
                naviName = value;

                this.lbl_NaviName.Text = naviName;
            
        


        private bool isActive = false;
        [Browsable(true)]
        [Category("自定义属性")]
        [Description("是否激活")]
        public bool IsActive
        
            get  return isActive; 
            set
            
                isActive = value;
                this.Invalidate();
            
        



        private int activeGap = 0;
        [Browsable(true)]
        [Category("自定义属性")]
        [Description("激活方块边距")]
        public int ActiveGap
        
            get  return activeGap; 
            set
            
                activeGap = value;
                this.Invalidate();
            
        


        private int activeHeight = 4;
        [Browsable(true)]
        [Category("自定义属性")]
        [Description("激活方块高度")]
        public int ActiveHeight
        
            get  return activeHeight; 
            set
            
                activeHeight = value;
                this.Invalidate();
            
        

        private Color activeColor = Color.FromArgb(236, 240, 243);
        [Browsable(true)]
        [Category("自定义属性")]
        [Description("激活方块颜色")]
        public Color ActiveColor
        
            get  return activeColor; 
            set
            
                activeColor = value;
                this.Invalidate();
            
        

        [Browsable(true)]
        [Category("自定义属性")]
        [Description("悬浮渐变色系数")]
        public float ColorDepth  get; set;  = -0.2f;

        [Browsable(true)]
        [Category("自定义属性")]
        [Description("权限登记")]
        public int Role  get; set;  = 0;

        [Browsable(true)]
        [Category("自定义事件")]
        [Description("单击事件")]
        public event EventHandler ClientEvent;

        private void lbl_NaviName_Click(object sender, EventArgs e)
        
            if (ClientEvent != null)
            
                ClientEvent.Invoke(this, e);
            
        

        private void pic_Main_Click(object sender, EventArgs e)
        
            if (ClientEvent != null)
            
                ClientEvent.Invoke(this, e);
            
        

        private void lbl_NaviName_MouseEnter(object sender, EventArgs e)
        
            this.BackColor = ChangeColor(this.BackColor, ColorDepth);
        

        private void lbl_NaviName_MouseLeave(object sender, EventArgs e)
        
            this.BackColor = this.SavedBackColor;
        

        protected override void OnPaint(PaintEventArgs e)
        
            base.OnPaint(e);

            Graphics graphics = e.Graphics;
            Rectangle rectangle = new Rectangle(activeGap, this.Height - activeHeight, this.Width - 2 * activeGap, activeHeight);
            graphics.FillRectangle(isActive ? new SolidBrush(this.activeColor) : new SolidBrush(this.BackColor), rectangle);

        

        private Color ChangeColor(Color color, float correctionFactor)
        
            if (correctionFactor > 1.0f) correctionFactor = 1.0f;
            if (correctionFactor < -1.0f) correctionFactor = -1.0f;

            float red = (float)color.R;
            float green = (float)color.G;
            float blue = (float)color.B;

            if (correctionFactor < 0)
            
                correctionFactor = 1 + correctionFactor;
                red *= correctionFactor;
                green *= correctionFactor;
                blue *= correctionFactor;
            
            else
            
                red = (255 - red) * correctionFactor + red;
                green = (255 - green) * correctionFactor + green;
                blue = (255 - blue) * correctionFactor + blue;
            

            if (red < 0) red = 0;

            if (red > 255) red = 255;

            if (green < 0) green = 0;

            if (green > 255) green = 255;

            if (blue < 0) blue = 0;

            if (blue > 255) blue = 255;

            return Color.FromArgb(color.A, (int)red, (int)green, (int)blue);
        
    

解释如下:

  1. 引入了一个自定义事件,绑定了当前图片或者标签被点击后,会跳转到单击事件上面。
  2. ChangeColor()这个方法相对固定,直接粘贴使用即可
  3. 鼠标进入时,颜色变深;鼠标离开的时候,颜色恢复
  4. 页面在浏览的时候,触发本控件IsActive时,绘制小方块。点击其他控件的时候,原先的控件IsActive为False,小方块消失

(二)UI导航栏的编写

需求:

实时监控这个界面不能关闭(关闭以后,页面信息会被清空)。其他的界面可以被关闭。考虑情况,如果出现上一个窗口是监控窗口,那么要把监控窗口给SendToBack。如果上一个是监控窗口,下一个还是监控窗口。那么要把监控窗口直接BringToFront。

原项目的写法太过于复杂。而且根本没有把窗口关闭的需求。

我觉得可以这样考虑:首先,每个窗口都不能关闭。没调用之前都处于隐藏状态。

调用以后,当前的窗口打开,放到前面。实时监控窗口放到后面。

当调用实时监控窗口的时候,监控窗口放到前面。

可能基于我的理解只要同一个窗口不能开两个,当前窗口处于最前端就行(我就做了个list存储窗口名,当没有的时候新建,把新建的BringToFront;有的时候,找到直接BringToFront)

原来例程中的代码:

        private void OpenWindow(FormNames formNames)
        
            bool isFind = false;

            int total = this.MainPanel.Controls.Count;

            int closeCount = 0;

            for (int i = 0; i < total; i++)
            
                Control ct = this.MainPanel.Controls[i - closeCount];

                if (ct is Form frm)
                
                    //如果是我们需要的,应该怎么处理
                    if (frm.Text == formNames.ToString())
                    
                        frm.BringToFront();
                        isFind = true;
                    
                    //如果不是我们需要的,但是不能的关闭,应该怎么处理?
                    else if (IsFixedForm(frm.Text))
                    
                        frm.SendToBack();
                    
                    // 其他的,应该怎么处理?
                    else
                    
                        frm.Close();
                        closeCount++;
                    
                
            

            if (isFind == false)
            
                Form frm = null;

                switch (formNames)
                
                    case FormNames.实时监控:
                        frm = new FrmMonitor();
                        this.AddLog = ((FrmMonitor)frm).AddLog;
                        this.AddAlarm = ((FrmMonitor)frm).AddAlarm;
                        this.SetRowState = ((FrmMonitor)frm).SetRowState;
                        this.SetSNCode = ((FrmMonitor)frm).SetSNCode;
                        this.SetCode = ((FrmMonitor)frm).SetCode;
                        this.SetWeight = ((FrmMonitor)frm).SetWeight;
                        this.SetPos = ((FrmMonitor)frm).SetPos;
                        // this.SystemReset= ((FrmMonitor)frm).SystemReset;

                        Program.SysRst = ((FrmMonitor)frm).SystemReset;


                        break;
                    case FormNames.手动操作:
                        frm = new FrmHand();
                        // ((FrmHand)frm).SystemReset = this.SysReset;
                        break;
                    case FormNames.报警记录:
                        frm = new FrmSysLog();
                        break;
                    case FormNames.历史数据:
                        frm = new FrmHistory();
                        break;
                    case FormNames.参数设置:
                        frm = new FrmParamSet();
                        break;
                    case FormNames.用户管理:
                        frm = new FrmUserManage();
                        break;
                    default:
                        break;
                


                frm.TopLevel = false;
                frm.FormBorderStyle = FormBorderStyle.None;
                frm.Dock = DockStyle.Fill;
                frm.Parent = this.MainPanel;
                frm.BringToFront();
                frm.Show();
            
        
        private bool IsFixedForm(string formNames)
        
            //获取所有的固定窗体
            var list = Enum.GetNames(typeof(FormNames)).Where(c => (int)Enum.Parse(typeof(FormNames), c, true) < 10).ToList();

            return list.Contains(formNames);
        
                    OpenWindow(formNames);

                    foreach (var item in this.TopPanel.Controls)
                    
                        if (item is NaviButton navi1)
                        
                            navi1.IsActive = false;
                        
                    

                    navi.IsActive = true;
    /// <summary>
    /// 所有窗体的枚举
    /// </summary>
    /// <remarks>
    /// 预留十个数值为固定窗体
    /// 固定窗体为不会关闭的窗体
    /// 本例中,只有实时监控是固定窗体
    /// 如果整个项目都没有固定窗体,那么需要把实时监控的值改成10
    /// </remarks>
    public enum FormNames
    
        实时监控,
        手动操作 = 10,
        报警记录,
        历史数据,
        参数设置,
        用户管理,
        退出系统
    

以上是关于上位机学习记录组合控件的应用(控件堆叠+重置)与UI导航栏的编写的主要内容,如果未能解决你的问题,请参考以下文章

上位机学习日记系统运行日志功能的编写与日志查看功能

上位机开发(canvas使用)

2021-09-12 WPF上位机 07-控件模板

C#上位机开发—— 表格控件的使用

C#上位机开发—— 表格控件的使用

2021-10-14 WPF上位机 67-自定义控件