日常开发记录分享——C#控件ToolTip实现分栏显示内容

文章目录

需求来源

需要在鼠标浮动到指定位置后提示出详细的信息,一开始使用的tooltip实现,但是里面的内容效果并不理想,需要有条理性,于是就想到能不能将展示的东西分列。

实现思路

使用两个字符串数据接收通过字符串切割后的内容,然后通过在tooltip的draw事件绘制时将内容分为两次绘制。

实施

自定封装一个ToolTip控件,继承ToolTIp然后添加两个事件,分别时Draw Popup
DrawPopup 这两个事件在 ToolTip 类中扮演着重要的角色,用于自定义工具提示的显示和绘制。

Draw 事件在工具提示需要绘制时触发。通过处理这个事件,可以自定义工具提示的外观和内容。

  • 作用

    • 自定义绘制工具提示 :在处理 Draw 事件时,可以完全控制工具提示的绘制,包括背景颜色、边框、文本内容和文本样式等。
    • 实现高级图形效果 :可以使用 Graphics 对象来实现复杂的绘制效果,比如渐变色、图片、各种形状等。
  • 使用场景

    • 当默认的工具提示外观不能满足需求时,可以通过 Draw 事件自定义绘制工具提示。
    • 需要在工具提示中显示非文本内容(如图像、图表)时,可以在 Draw 事件中实现。

Popup 事件在工具提示显示之前触发。通过处理这个事件,可以动态调整工具提示的大小和内容。

  • 作用

    • 动态调整工具提示大小 :在处理 Popup 事件时,可以根据内容的大小动态设置工具提示的尺寸,以确保内容完全显示。
    • 准备绘制环境 :可以在 Popup 事件中进行一些准备工作,比如计算文本的最大宽度和高度,为后续的 Draw 事件做准备。
  • 使用场景

    • 需要根据内容动态调整工具提示的大小时,可以在 Popup 事件中进行计算和设置。
    • 需要在工具提示显示前进行一些准备工作,比如加载图片、计算文本尺寸等,可以在 Popup 事件中处理。
csharp 复制代码
using System;
using System.Drawing;
using System.Windows.Forms;

namespace Test1
{
    // 自定义工具提示类,继承自 ToolTip
    public class CustomToolTip : ToolTip
    {
        private string[] Column1; // 用于存储第一列的文本数组
        private string[] Column2; // 用于存储第二列的文本数组
        private Font TextFont; // 工具提示文本的字体
        // 记录第一列的宽度
        private int Column1MaxWidth = 0;
		
        // 构造函数,初始化自定义工具提示
        public CustomToolTip()
        {
            TextFont = new Font("微软雅黑", 15.0f); // 设置字体为"微软雅黑",大小为15
            this.OwnerDraw = true; // 启用自定义绘制工具提示
            this.Draw += new DrawToolTipEventHandler(OnDraw); // 订阅 Draw 事件
            this.Popup += new PopupEventHandler(OnPopup); // 订阅 Popup 事件
        }

        // 设置工具提示的内容,将其拆分为两列
        public void SetContent(string content)
        {
            var parts = content.Split(new string[] { "," }, StringSplitOptions.None); // 按逗号拆分内容
            int midPoint = (parts.Length + 1) / 2; // 计算拆分成两列的中间点

            Column1 = new string[midPoint]; // 初始化第一列数组
            Column2 = new string[parts.Length - midPoint]; // 初始化第二列数组

            // 填充列数组
            for (int i = 0; i < parts.Length; i++)
            {
                if (i < midPoint)
                {
                    Column1[i] = parts[i];
                }
                else
                {
                    Column2[i - midPoint] = parts[i];
                }
            }
        }

        // 自定义工具提示的绘制事件处理程序
        private void OnDraw(object sender, DrawToolTipEventArgs e)
        {
            e.DrawBackground(); // 绘制工具提示的背景
            e.DrawBorder(); // 绘制工具提示的边框

            Brush brush = Brushes.Black; // 用于绘制文本的画笔
            Rectangle rct2 = e.Bounds; // 工具提示的边界
            e.Graphics.FillRectangle(Brushes.Bisque, rct2); // 用浅橙色填充背景
            e.Graphics.DrawRectangle(Pens.DarkGray, new Rectangle(0, 0, rct2.Width - 1, rct2.Height - 1)); // 绘制边框

            // 绘制第一列文本
            for (int i = 0; i < Column1.Length; i++)
            {
                e.Graphics.DrawString(Column1[i], TextFont, brush, new PointF(5, i * 25));
            }

            // 绘制第二列文本
            for (int i = 0; i < Column2.Length; i++)
            {
                e.Graphics.DrawString(Column2[i], TextFont, brush, new PointF(Column1MaxWidth, i * 25));
            }
        }

        // 在工具提示显示之前计算其大小的事件处理程序
        private void OnPopup(object sender, PopupEventArgs e)
        {
            int Column2MaxWidth = 0; // 用于存储第二列的最大宽度
            int maxHeight = 0; // 用于存储工具提示的最大高度

            // 计算第一列的最大宽度和高度
            foreach (var text in Column1)
            {
                var sz = TextRenderer.MeasureText(text, TextFont);
                if (sz.Width > Column1MaxWidth)
                    Column1MaxWidth = sz.Width;
                maxHeight += sz.Height;
            }

            // 计算第二列的最大宽度
            foreach (var text in Column2)
            {
                var sz = TextRenderer.MeasureText(text, TextFont);
                if (sz.Width > Column2MaxWidth)
                    Column2MaxWidth = sz.Width;
            }

            // 确保高度适应两列中较高的一列
            maxHeight = Math.Max(maxHeight, Column2.Length * TextRenderer.MeasureText("A", TextFont).Height);
            e.ToolTipSize = new Size(Column1MaxWidth + Column2MaxWidth + 20, maxHeight + 30); // 设置工具提示大小,并添加一些间距
        }
    }
}

这里对字符串的分割是根据,来的,根据个人需要修改SetContent方法中切割字符,当然也可以封装一下,这里本人偷懒了。

下面是使用的方式,先在我们窗体中创建一个自定义的Tooltip对象,具体使用就是先设置SetContent方法将要显示的内容传递进去。最后将要tooltip关联的控件对象绑定就行了

csharp 复制代码
  private CustomToolTip custom = new CustomToolTip();
        private void Form1_Load(object sender, EventArgs e)
        {

            string aa = $"工作人员姓名:aaa,出勤地点:aaa333344445555555555," +
               $"工号:aaa,出勤时间:aaa," +
               $"手机:aaaaaaaa,本站时间:aaa," +
               $"站名:aaa,工作班制:aaa," +
               $"当前已工作时间:aaa,班制时长:aaa1111," +
               $"工作人员所属部门:aaa";
            custom.SetContent(aa);
             custom.SetToolTip(button1,aa);//这里传递第二个参数只要是字符串就行,因为在SetContent方法时已经设置好要显示的内容了。
        }

请看VCR

等等别走,有优化

鉴于上面我们使用的在From_Load方法中去使用自定义tip时调用SetToolTip时第二个参数传递有些冗余,这里把自定义的tip控件给优化了一下,优化虽小也是进步

csharp 复制代码
using System;
using System.Drawing;
using System.Windows.Forms;

namespace Test1
{
    // 自定义工具提示类,继承自 ToolTip
    public class CustomToolTip : ToolTip
    {
        private string[] Column1; // 用于存储第一列的文本数组
        private string[] Column2; // 用于存储第二列的文本数组
        private Font TextFont; // 工具提示文本的字体
        priavte Control ParentCtrl;//父窗体控件
        // 记录第一列的宽度
        private int Column1MaxWidth = 0;

        // 构造函数,初始化自定义工具提示
        public CustomToolTip()
        {
            TextFont = new Font("微软雅黑", 15.0f); // 设置字体为"微软雅黑",大小为15
            this.OwnerDraw = true; // 启用自定义绘制工具提示
            this.Draw += new DrawToolTipEventHandler(OnDraw); // 订阅 Draw 事件
            this.Popup += new PopupEventHandler(OnPopup); // 订阅 Popup 事件
        }

        // 设置工具提示的内容,将其拆分为两列
        private void SetContent(string content)
        {
            var parts = content.Split(new string[] { "," }, StringSplitOptions.None); // 按逗号拆分内容
            int midPoint = (parts.Length + 1) / 2; // 计算拆分成两列的中间点

            Column1 = new string[midPoint]; // 初始化第一列数组
            Column2 = new string[parts.Length - midPoint]; // 初始化第二列数组

            // 填充列数组
            for (int i = 0; i < parts.Length; i++)
            {
                if (i < midPoint)
                {
                    Column1[i] = parts[i];
                }
                else
                {
                    Column2[i - midPoint] = parts[i];
                }
            }
        }

        // 自定义工具提示的绘制事件处理程序
        private void OnDraw(object sender, DrawToolTipEventArgs e)
        {
            e.DrawBackground(); // 绘制工具提示的背景
            e.DrawBorder(); // 绘制工具提示的边框

            Brush brush = Brushes.Black; // 用于绘制文本的画笔
            Rectangle rct2 = e.Bounds; // 工具提示的边界
            e.Graphics.FillRectangle(Brushes.Bisque, rct2); // 用浅橙色填充背景
            e.Graphics.DrawRectangle(Pens.DarkGray, new Rectangle(0, 0, rct2.Width - 1, rct2.Height - 1)); // 绘制边框

            // 绘制第一列文本
            for (int i = 0; i < Column1.Length; i++)
            {
                e.Graphics.DrawString(Column1[i], TextFont, brush, new PointF(5, i * 25));
            }

            // 绘制第二列文本
            for (int i = 0; i < Column2.Length; i++)
            {
                e.Graphics.DrawString(Column2[i], TextFont, brush, new PointF(Column1MaxWidth, i * 25));
            }
        }

        // 在工具提示显示之前计算其大小的事件处理程序
        private void OnPopup(object sender, PopupEventArgs e)
        {
            int Column2MaxWidth = 0; // 用于存储第二列的最大宽度
            int maxHeight = 0; // 用于存储工具提示的最大高度
            //设置将文本拆分两个数组,用于后期显示为两列---在这里通过tip控件自带的GetToolTip方法获取提示文本内容然后进行拆分初始化
			SetContent(this.GetToolTip(ParentCtrl));
            // 计算第一列的最大宽度和高度
            foreach (var text in Column1)
            {
                var sz = TextRenderer.MeasureText(text, TextFont);
                if (sz.Width > Column1MaxWidth)
                    Column1MaxWidth = sz.Width;
                maxHeight += sz.Height;
            }

            // 计算第二列的最大宽度
            foreach (var text in Column2)
            {
                var sz = TextRenderer.MeasureText(text, TextFont);
                if (sz.Width > Column2MaxWidth)
                    Column2MaxWidth = sz.Width;
            }

            // 确保高度适应两列中较高的一列
            maxHeight = Math.Max(maxHeight, Column2.Length * TextRenderer.MeasureText("A", TextFont).Height);
            e.ToolTipSize = new Size(Column1MaxWidth + Column2MaxWidth + 20, maxHeight + 30); // 设置工具提示大小,并添加一些间距
        }
    }
}
csharp 复制代码
        private CustomToolTip custom ;
        public Form1()
        {
            InitializeComponent();
           
        }
        private void Form1_Load(object sender, EventArgs e)
        {
 			custom = new CustomToolTip(button1);
            string aa = $"工作人员姓名:aaa,出勤地点:aaa333344445555555555," +
               $"工号:aaa,出勤时间:aaa," +
               $"手机:aaaaaaaa,本站时间:aaa," +
               $"站名:aaa,工作班制:aaa," +
               $"当前已工作时间:aaa,班制时长:aaa1111," +
               $"工作人员所属部门:aaa";
            custom.SetToolTip(button1,aa);
        }
相关推荐
我要洋人死14 分钟前
导航栏及下拉菜单的实现
前端·css·css3
科技探秘人26 分钟前
Chrome与火狐哪个浏览器的隐私追踪功能更好
前端·chrome
科技探秘人26 分钟前
Chrome与傲游浏览器性能与功能的深度对比
前端·chrome
JerryXZR32 分钟前
前端开发中ES6的技术细节二
前端·javascript·es6
七星静香34 分钟前
laravel chunkById 分块查询 使用时的问题
java·前端·laravel
q24985969336 分钟前
前端预览word、excel、ppt
前端·word·excel
小华同学ai42 分钟前
wflow-web:开源啦 ,高仿钉钉、飞书、企业微信的审批流程设计器,轻松打造属于你的工作流设计器
前端·钉钉·飞书
Gavin_9151 小时前
【JavaScript】模块化开发
前端·javascript·vue.js
懒大王爱吃狼2 小时前
Python教程:python枚举类定义和使用
开发语言·前端·javascript·python·python基础·python编程·python书籍
△曉風殘月〆4 小时前
WPF MVVM入门系列教程(二、依赖属性)
c#·wpf·mvvm