winform窗体、控件的简单封装,重做标题栏

1标题栏封装中使用了以下技术:

知识点:
1.父类、子类的继承;
2.窗体之间的继承;
3.自定义控件的绘制;
4.多线程在窗体间的应用;
5.窗体和控件的封装;
6.回调函数(委托);

效果展示

在这里插入图片描述

部分代码展示

	/// <summary>
    /// 标题栏
    /// </summary>
    public sealed partial class UcViewTitle : UserControl
    {

        /// <summary>
        /// 鼠标按下时子控件、父控件的位置
        /// </summary>
        private Point _mouseDownChildLocation, _mouseDownParentLocation;

        /// <summary>
        /// 标题栏文本字体
        /// </summary>
        public Font TitleFont { get; set; } = new Font("微软雅黑", 24.25F, FontStyle.Regular, GraphicsUnit.Point, 134);

        /// <summary>
        /// 标题栏文本内容
        /// </summary>
        public string Title { get; set; } = "科技未来,等你引领";

        /// <summary>
        /// 标题栏背景颜色
        /// </summary>
        public Color TitleBackColor { get; set; } = Color.FromArgb(0, 49, 71);

        /// <summary>
        /// 标题栏文本颜色
        /// </summary>
        public Color TitleTextBackColor { get; set; } = Color.White;

        /// <summary>
        /// 回调函数:关闭窗体时触发
        /// </summary>
        public Action CallbackCloseForm;

        /// <summary>
        /// 鼠标双击时设置窗体最大化、默认状态
        /// </summary>
        public Func<FormWindowState> FunGetFormState;

        /// <summary>
        /// 鼠标双击时设置窗体最大化、默认状态
        /// </summary>
        public Action<FormWindowState> ActionMouseDouble;

        /// <summary>
        /// 鼠标按下时窗体的位置
        /// </summary>
        public Func<Point> ActionMouseDownLocation;

        /// <summary>
        /// 鼠标移动后窗体的新位置
        /// </summary>
        public Action<Point> ActionMouseMoveLocation;

        /// <summary>
        /// 构造函数
        /// </summary>
        public UcViewTitle()
        {
            InitializeComponent();
            this.DoubleBuffered = true;
            SetToolTip();
        }

        private void UcViewTitle_Load(object sender, EventArgs e)
        {
            new Task(() =>
            {
                try
                {
                    while (true)
                    {
                        Thread.Sleep(1000);
                        Invoke(new EventHandler(delegate { this.Refresh(); }));
                    }
                }
                catch (Exception ex)
                {


                }
            }).Start();
        }


        [Description("跟随串口大小重新绘制标题栏")]
        private void UcTitle_SizeChanged(object sender, EventArgs e)
        {
            pic_Close.Location = new Point(this.Width - 5 - pic_Close.Width, this.Height / 2 - pic_Close.Height / 2);
            pic_Maximize.Location = new Point(pic_Close.Location.X - 5 - pic_Minimality.Width, this.Height / 2 - pic_Maximize.Height / 2);
            pic_Minimality.Location = new Point(pic_Maximize.Location.X - 5 - pic_Minimality.Width, this.Height / 2 - pic_Close.Height / 2);
            //pic_Logo.Location = new Point(10, this.Height / 2 - pic_Logo.Height / 2);
            SetPictureMaxIcon();
            Refresh();
        }

        [Description("绘制标题栏")]
        private void UcTitle_Paint(object sender, PaintEventArgs e)
        {
            e.Graphics.Clear(TitleBackColor);
            // e.Graphics.Clear(Color.FromArgb(14, 30, 63));
            e.Graphics.SmoothingMode = SmoothingMode.HighQuality;//指定抗锯齿的呈现

            var brush = new SolidBrush(TitleTextBackColor);

            #region [绘制日期时间]

            var textTimeStartX = pic_Logo.Location.X + pic_Logo.Width + 10;
            var textTimeFont = new Font(TitleFont.Name, 14f, FontStyle.Regular, GraphicsUnit.Point, 134);

            string text = GetDate();
            var textDateSize = e.Graphics.MeasureString(text, textTimeFont);
            PointF textLocation = new PointF(textTimeStartX, this.Height / 2);
            e.Graphics.DrawString(text, textTimeFont, brush, textLocation);

            text = GetTime();
            var textTimeSize = e.Graphics.MeasureString(text, textTimeFont);
            textLocation = new PointF(textTimeStartX + textDateSize.Width / 2 - textTimeSize.Width / 2, this.Height / 2 - textDateSize.Height);
            e.Graphics.DrawString(text, textTimeFont, brush, textLocation);
            #endregion [绘制日期时间]

            //绘制标题
            var textTitleSize = e.Graphics.MeasureString(Title, TitleFont);
            textLocation = new PointF(this.Width / 2.0f - textTitleSize.Width / 2.0f, this.Height / 2.0f - textTitleSize.Height / 2.0f);
            e.Graphics.DrawString(Title, TitleFont, brush, textLocation);

        }

        [Description("最小化窗口")]
        private void pic_Minimality_Click(object sender, EventArgs e) => ActionMouseDouble?.Invoke(FormWindowState.Minimized);

        [Description("最大化窗口")]
        private void pic_Maximize_Click(object sender, EventArgs e) => SwitchWindowState();

        [Description("关闭窗口")]
        private void pic_Close_Click(object sender, EventArgs e) => CallbackCloseForm?.Invoke();

        [Description("鼠标双击时设置窗体最大化、默认状态")]
        private void UcViewTitle_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            if (e.Button != MouseButtons.Left) return;
            SwitchWindowState();
        }

        [Description("鼠标按下记录位置信息用于计算移动窗口的初始值")]
        private void UcViewTitle_MouseDown(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                _mouseDownChildLocation = e.Location;
            }
        }

        [Description("鼠标按下并移动时设置窗口新的位置信息")]
        private void UcViewTitle_MouseMove(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                ActionMouseDouble?.Invoke(FormWindowState.Normal);
                if (ActionMouseDownLocation != null)
                {
                    _mouseDownParentLocation = ActionMouseDownLocation();
                }
                var addX = e.X - _mouseDownChildLocation.X;
                var addY = e.Y - _mouseDownChildLocation.Y;
                ActionMouseMoveLocation?.Invoke(new Point(_mouseDownParentLocation.X + addX, _mouseDownParentLocation.Y + addY));
            }
        }

        [Description("设置最小化、最大化、关闭的鼠标悬空提示信息")]
        private void SetToolTip()
        {
            new ToolTip().SetToolTip(pic_Minimality, "最小化");
            new ToolTip().SetToolTip(pic_Maximize, "最大化");
            new ToolTip().SetToolTip(pic_Close, "关闭");
        }

        [Description("鼠标双击时设置窗体最大化、默认状态")]
        private void SwitchWindowState()
        {
            if (FunGetFormState != null)
            {
                var state = FunGetFormState();
                state = state == FormWindowState.Maximized
                    ? FormWindowState.Normal
                    : FormWindowState.Maximized;
                ActionMouseDouble?.Invoke(state);
                SetPictureMaxIcon();
            }
        }

        [Description("设置最大化图标")]
        private void SetPictureMaxIcon()
        {
            if (FunGetFormState == null) return;

            var state = FunGetFormState();
            switch (state)
            {
                case FormWindowState.Normal:
                    pic_Maximize.BackgroundImage = Resources.FormTitle_最大化1;
                    break;
                default:
                    pic_Maximize.BackgroundImage = Resources.FormTitle_最大化;
                    break;
            }
        }

        /// <summary>
        /// 获取时间串(格式:2008年08月08日 10:20:06)
        /// </summary>
        /// <returns></returns>
        private string GetDate()
        {
            DateTime ts = DateTime.Now;
            var str = new StringBuilder();
            str.Append($"{ts.Year}年");
            str.Append($"{ts.Month.ToString().PadLeft(2, '0')}月");
            str.Append($"{ts.Day.ToString().PadLeft(2, '0')}日");
            return str.ToString();
        }
        /// <summary>
        /// 获取时间串(格式:10:20:06)
        /// </summary>
        /// <returns></returns>
        private string GetTime()
        {
            DateTime ts = DateTime.Now;
            var str = new StringBuilder();
            str.Append($"{ts.Hour.ToString().PadLeft(2, '0')}:");
            str.Append($"{ts.Minute.ToString().PadLeft(2, '0')}:");
            str.Append($"{ts.Second.ToString().PadLeft(2, '0')}");
            return str.ToString();
        }

        /// <summary>
        /// 设置LOGO
        /// </summary>
        /// <param name="bmp">LOGO图像</param>
        /// <param name="logoWidth">LOGO的宽度</param>
        public void SetLogo(Bitmap bmp, int logoWidth)
        {
            pic_Logo.Visible = true;
            pic_Logo.BackgroundImage = bmp;
            pic_Logo.Width = logoWidth;
        }
    }

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Redis快速入门(基础篇)

简介&#xff1a; 是一个高性能的 key-value数据库。 存在内存中 与其他 key-value 缓存产品有以下三个特点&#xff1a; Redis支持数据的持久化&#xff0c;可以将内存中的数据保持在磁盘中&#xff0c;重启的时候可以再次加载进行使用。 Redis不仅仅支持简单的key-value类…

自动备份pgsql数据库

bat文件中的内容&#xff1a; PATH D:\Program Files\PostgreSQL\13\bin;D:\Program Files\7-Zip set PGPASSWORD**** pg_dump -h 8.134.151.187 -p 5466 -U sky -d mip_db --schema-only -f D:\DB\backup\%TODAY%-schema-mip_db_ali.sql pg_dump -h 8.134.151.187 -p 5466…

BUUCTF 面具下的flag 1

BUUCTF:https://buuoj.cn/challenges 题目描述&#xff1a; 下载附件&#xff0c;得到一张.jpg图片。 密文&#xff1a; 解题思路&#xff1a; 1、将图片放到Kali中&#xff0c;使用binwalk检测出隐藏zip包。 使用foremost提取zip压缩包到output目录下 解压zip压缩包&…

python自动化第一篇—— 带图文的execl的自动化合并

简述 最近接到一个需求&#xff0c;需要为公司里的一个部门提供一个文件上传自动化合并的系统&#xff0c;以供用户稽核&#xff0c;谈到自动化&#xff0c;肯定是选择python&#xff0c;毕竟python的轮子多。比较了市面上几个用得多的python库&#xff0c;我最终选择了xlwings…

【自然语言处理(NLP)实战】LSTM网络实现中文文本情感分析(手把手与教学超详细)

目录 引言&#xff1a; 1.所有文件展示&#xff1a; 1.中文停用词数据&#xff08;hit_stopwords.txt)来源于&#xff1a; 2.其中data数据集为chinese_text_cnn-master.zip提取出的文件。点击链接进入github&#xff0c;点击Code、Download ZIP即可下载。 2.安装依赖库&am…

聊聊模糊测试,以及几种模糊测试工具的介绍!

以下为作者观点&#xff1a; 在当今的数字环境中&#xff0c;漏洞成为攻击者利用系统漏洞的通道&#xff0c;对网络安全构成重大威胁。这些漏洞可能存在于硬件、软件、协议实施或系统安全策略中&#xff0c;允许未经授权的访问并破坏系统的完整性。 根据 "常见漏洞与暴露…

在Linux中nacos集群模式部署

一、安装 配置nacos 在Linux中建立一个nacos文件夹 mkdir nacos 把下载的压缩包拉入刚才创建好的nacos文件中 解压 tar -zxvf nacos-server-1.4.1\.tar.gz 修改配置文件 进入nacos文件中的conf文件的cluster.conf.example 修改cluster.conf.example文件 vim cluster.conf.exa…

Django(六、模板层)

文章目录 模板传值模板语法传值特性 模板语法之过滤器常用的过滤器模板层之标签模板中的标签的格式为标签之if判断 标签之for循环模板的继承与导入模板导入导入格式 模板传值 """ 模板层三种语法 {{}}:主要与数据值相关 {%%}:主要与逻辑相关 {##}&#xff1a;模…

【开源】基于Vue和SpringBoot的快乐贩卖馆管理系统

项目编号&#xff1a; S 064 &#xff0c;文末获取源码。 \color{red}{项目编号&#xff1a;S064&#xff0c;文末获取源码。} 项目编号&#xff1a;S064&#xff0c;文末获取源码。 目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 数据中心模块2.2 搞笑视频模块2.3 视…

Linux常用的磁盘使用情况命令汇总

1、查看分区使用百分比 df -h 2、查看指定目录磁盘使用情况 du -hac --max-depth1 /opt 参数&#xff1a;-a 查看所有文件&#xff0c;-c 汇总统计&#xff0c;max-depth1 查看深度为1&#xff0c;2级目录不再统计。 3、常用统计命令汇总

一键帮您解决win11最新版画图工具难用问题!

&#x1f984;个人主页:修修修也 ⚙️操作环境:Windows 11 正文 自从win11更新后,新版的画图工具变得非常难用,如: 使用橡皮擦后露出背版马赛克 框住某部分拖动移动时背景露出马赛克剪贴板上图片信息无法直接插入到画图板 目前没有一个好一些的能够在软件内部解决这些问题的方…

参考意义大。4+巨噬细胞相关生信思路,简单易复现。

今天给同学们分享一篇生信文章“Angiogenesis regulators S100A4, SPARC and SPP1 correlate with macrophage infiltration and are prognostic biomarkers in colon and rectal cancers”&#xff0c;这篇文章发表在Front Oncol期刊上&#xff0c;影响因子为4.7。 结果解读&a…

软件测试个人求职简历该怎么写,模板在这里

1、个人资料 姓 名&#xff1a;xxx 性 别&#xff1a;x 手机号码&#xff1a;138888888xx 邮 箱&#xff1a; xxx 学 历&#xff1a;本科 专 业&#xff1a;电子商务 英 语&#xff1a;四级 当前工作&#xff1a;测试工程师 从业时间&#xff1a;4年 期望薪资&#xff1a;…

HDFS入门--学习笔记

1&#xff0c;大数据介绍 定义 数据指的是&#xff1a;一种可以被鉴别的、对客观事件进行记录的符号&#xff0c;除了可以是最简单的 数字外&#xff0c;也可以是各类符号、文字、图像、声音等。 通俗地说&#xff0c;数据就是对人类的行为及发生事件的一种记录。 存在的价值…

使用群晖虚拟机快速搭建黑群晖并在公网移动端环境下使用软件

文章目录 前言本教程解决的问题是&#xff1a;按照本教程方法操作后&#xff0c;达到的效果是前排提醒&#xff1a; 1. 搭建群晖虚拟机1.1 下载黑群晖文件vmvare虚拟机安装包1.2 安装VMware虚拟机&#xff1a;1.3 解压黑群晖虚拟机文件1.4 虚拟机初始化1.5 没有搜索到黑群晖的解…

Mysql中的索引与事务和B树的知识补充

索引与事务和B树的知识补充 一.索引1.概念2.作用3.使用场景4.使用 二.事务1.为什么使用事务2.事务的概念3.使用3.1脏读问题3.2不可重复读3.3 幻读问题3.4解决3.5 使用代码 三.B树的知识补充1.B树2.B树 一.索引 1.概念 索引是一种特殊的文件&#xff0c;包含着对数据表里所有记…

QGIS之二十栅格数据定义投影

效果 步骤 1、准备数据 2、定义投影 Qgis工具箱中搜索“投影” 指定投影坐标系&#xff0c;例如EPSG&#xff1a;4549 运行 3、结果 查看属性

【Qt-23】基于QCharts绘制曲线图

一、QChart简介 QChart是Qt中专门用于绘制图表的模块&#xff0c;支持折线图、柱状图、饼图等常见类型。其主要组成部分有&#xff1a; QChart&#xff1a;整个图表的容器&#xff0c;管理图表中的所有数据和图形属性QChartView&#xff1a;继承自QGraphicsView&#xff0c;用于…

day2324_jdbc

今日内容 零、 复习昨日 一、作业 二、SQL注入 三、PreparedStatement 四、事务 五、DBUtil 零、 复习昨日 一、引言 1.1 如何操作数据库 使用客户端工具访问数据库&#xff0c;需要手工建立连接&#xff0c;输入用户名和密码登录&#xff0c;编写 SQL 语句&#xff0c;点击执行…