在Windows窗体(C#)中,有一种方法可以设置工具提示';s的高度和宽度是动态的

本文关键字:工具提示 动态 设置 高度 窗体 Windows 方法 一种 | 更新日期: 2023-09-27 18:25:25

在Windows窗体(C#)中,有一种方法可以动态设置工具提示的高度和宽度(在代码中表示)。我使用的是DataViewGrid控件,所以我必须使用Show方法。然而,我注意到(当留给它自己的设备时)工具提示控件并不总是根据提供的内容进行调整。。。。

一个例子:

将ToolTip控件添加到表单(称为ttText),然后让它首先显示文本:

ttText.Show("I'm hungry'nand waiting!");  

将截断下一个调用:

ttText.Show("Well, too bad -- so much for your stamina, you should not be here!'nSo the little bear responds!");

对此有什么想法吗?

请记住,DataGridView需要一种显示工具提示帮助的机制,因此使用了Show方法,我在非DataViewGrids的其他地方看到过这种行为。。。

以下是代码示例:使用System。集合。通用的使用System。绘画使用System。林克;使用System。Windows。表格;

namespace TestForm
{
    class Form1 : Form
    {
        /// <summary>
        /// Required designer variable.
        /// </summary>
        private System.ComponentModel.IContainer components = null;
        /// <summary>
        /// Clean up any resources being used.
        /// </summary>
        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
        protected override void Dispose(bool disposing)
        {
            if (disposing && (components != null))
            {
                components.Dispose();
            }
            base.Dispose(disposing);
        }
        /// <summary>
        /// Required method for Designer support - do not modify
        /// the contents of this method with the code editor.
        /// </summary>
        private void InitializeComponent()
        {
            this.components = new System.ComponentModel.Container();
            this.dataGridView1 = new System.Windows.Forms.DataGridView();
            this.ttText = new System.Windows.Forms.ToolTip(this.components);
            ((System.ComponentModel.ISupportInitialize)(this.dataGridView1)).BeginInit();
            this.SuspendLayout();
            // 
            // dataGridView1
            // 
            this.dataGridView1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
                        | System.Windows.Forms.AnchorStyles.Left)
                        | System.Windows.Forms.AnchorStyles.Right)));
            this.dataGridView1.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
            this.dataGridView1.Location = new System.Drawing.Point(13, 19);
            this.dataGridView1.Name = "dataGridView1";
            this.dataGridView1.Size = new System.Drawing.Size(453, 321);
            this.dataGridView1.TabIndex = 0;
            this.dataGridView1.CellMouseEnter += new System.Windows.Forms.DataGridViewCellEventHandler(this.dataGridView1_MouseCellEnter);
            // 
            // ttText
            // 
            this.ttText.AutomaticDelay = 60;
            this.ttText.AutoPopDelay = 600000;
            this.ttText.InitialDelay = 60;
            this.ttText.IsBalloon = true;
            this.ttText.ReshowDelay = 60;
            // 
            // Form1
            // 
            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
            this.ClientSize = new System.Drawing.Size(478, 352);
            this.Controls.Add(this.dataGridView1);
            this.Name = "Form1";
            this.Text = "Form1";
            ((System.ComponentModel.ISupportInitialize)(this.dataGridView1)).EndInit();
            this.ResumeLayout(false);
        }

        private System.Windows.Forms.DataGridView dataGridView1;
        private System.Windows.Forms.ToolTip ttText;
        public Form1()
        {
            InitializeComponent();
            var ds = Sayings().ToList();
            dataGridView1.DataSource = ds;
        }
        public List<dynamic> Sayings()
        {
            return new List<dynamic>
            {
                new 
                { 
                    Human = "I'm hungry'nand waiting!",
                    BabyBear = "Well, too bad -- so much for your stamina, you should not be here!'nSo the little bear responds!"
                }
            };
        }
        private void dataGridView1_MouseCellEnter(object sender, DataGridViewCellEventArgs e)
        {
            if (e.ColumnIndex != -1 && e.RowIndex != -1)
            {
                var rect = dataGridView1.GetColumnDisplayRectangle(e.ColumnIndex, true);
                var left = rect.Left + (int)(rect.Width * .5f);
                var top = rect.Top;
                Point displayPoint = new Point(left + this.ClientRectangle.Left, top + this.ClientRectangle.Top + 40);
                ttText.Show(dataGridView1[e.ColumnIndex, e.RowIndex].Value.ToString(), this, displayPoint);
            }
        }
    }
}

如果将鼠标悬停在第一列上,然后悬停在第二列上,则工具提示文本将被截断。

在Windows窗体(C#)中,有一种方法可以设置工具提示';s的高度和宽度是动态的

好吧,我发布这个问题已经好几个月了。从那时起,我就没有真正考虑过这个问题——只是接受了这种行为。。。直到今晚。

由于没有其他人想到答案(或者愿意提供另一个Window Forms的想法),我突然重新审视了这个普遍的问题。气球工具提示似乎是一种自由形式的东西。。。它采用以前遇到的形状。这可能是微软在工作上的懒惰。或者更好——这是微软为开发人员指明不同方向的方式。毕竟,唯一提供的新方向是wpf。。。

然而,正如我在最初的问题中所说,我需要的解决方案只是windows窗体,而不是将WPF、Silverlight或其他技术混合在一起。毕竟,如果你是一名WPF程序员,你可能想在混合中添加Windows窗体控件,但对于最纯粹的控件来说,这是行不通的。

因此,这里有更多的谜题解决方案——如何将气球调整到所需的尺寸。。。

我重新审视了这个问题,注意到每次鼠标指针进入单元格时,气球都会调整大小,因此,得出了以下结果:

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Windows.Forms;
namespace TestForm
{
    class Form1 : Form
    {
        /// <summary>
        /// Required designer variable.
        /// </summary>
        private System.ComponentModel.IContainer components = null;
        /// <summary>
        /// Clean up any resources being used.
        /// </summary>
        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
        protected override void Dispose(bool disposing)
        {
            if (disposing && (components != null))
            {
                components.Dispose();
            }
            base.Dispose(disposing);
        }
        /// <summary>
        /// Required method for Designer support - do not modify
        /// the contents of this method with the code editor.
        /// </summary>
        private void InitializeComponent()
        {
            this.components = new System.ComponentModel.Container();
            this.dataGridView1 = new System.Windows.Forms.DataGridView();
            this.ttText = new System.Windows.Forms.ToolTip(this.components);
            ((System.ComponentModel.ISupportInitialize)(this.dataGridView1)).BeginInit();
            this.SuspendLayout();
            // 
            // dataGridView1
            // 
            this.dataGridView1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
            | System.Windows.Forms.AnchorStyles.Left)
            | System.Windows.Forms.AnchorStyles.Right)));
            this.dataGridView1.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
            this.dataGridView1.Location = new System.Drawing.Point(17, 23);
            this.dataGridView1.Margin = new System.Windows.Forms.Padding(4);
            this.dataGridView1.Name = "dataGridView1";
            this.dataGridView1.Size = new System.Drawing.Size(604, 395);
            this.dataGridView1.TabIndex = 0;
            this.dataGridView1.CellMouseEnter += new System.Windows.Forms.DataGridViewCellEventHandler(this.dataGridView1_MouseCellEnter);
            this.dataGridView1.MouseLeave += new System.EventHandler(this.dataGridView1_MouseLeave);
            this.dataGridView1.MouseMove += new System.Windows.Forms.MouseEventHandler(this.event_MouseMove);
            // 
            // ttText
            // 
            this.ttText.AutomaticDelay = 0;
            this.ttText.AutoPopDelay = 0;
            this.ttText.InitialDelay = 10;
            this.ttText.IsBalloon = true;
            this.ttText.OwnerDraw = true;
            this.ttText.ReshowDelay = 0;
            this.ttText.ShowAlways = true;
            this.ttText.UseAnimation = false;
            this.ttText.UseFading = false;
            // 
            // Form1
            // 
            this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 16F);
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
            this.ClientSize = new System.Drawing.Size(637, 433);
            this.Controls.Add(this.dataGridView1);
            this.Margin = new System.Windows.Forms.Padding(4);
            this.Name = "Form1";
            this.Text = "Form1";
            this.MouseMove += new System.Windows.Forms.MouseEventHandler(this.event_MouseMove);
            ((System.ComponentModel.ISupportInitialize)(this.dataGridView1)).EndInit();
            this.ResumeLayout(false);
        }
        private System.Windows.Forms.DataGridView dataGridView1;
        private System.Windows.Forms.ToolTip ttText;
        public Form1()
        {
            InitializeComponent();
            dataGridView1.ShowCellToolTips = false;
            var ds = Sayings().ToList();
            dataGridView1.DataSource = ds;
        }

        public List<dynamic> Sayings()
        {
            return new List<dynamic>
            {
                new 
                { 
                    Human = "I'm hungry'nand waiting!",
                    BabyBear = "Well, too bad -- so much for your stamina, you should not be here!'nSo the little bear responds!"
                },
                new 
                { 
                    Human = "What a selfish bear!'n'n'nAt least you could do is wait for'nothers to join you!",
                    BabyBear = "Boo Hoo!"
                },
                new 
                { 
                    Human = "Oh, I'm sorry!",
                    BabyBear = "Now, I'm going to eat you!"
                },
                new 
                { 
                    Human = "'n'n'n!!!'n'nWhat?????'n'n'n'nI don't think so!'n'n(Human pulls out Honey Jar)",
                    BabyBear = "Yum!"
                },
            };
        }
        private void dataGridView1_MouseCellEnter(object sender, DataGridViewCellEventArgs e)
        {
            if (e.ColumnIndex != -1 && e.RowIndex != -1)
            {
                this.SuspendLayout();
                var rectC = dataGridView1.GetColumnDisplayRectangle(e.ColumnIndex, true);
                var left = rectC.Left + (int)(rectC.Width * .5f);
                var rectR = dataGridView1.GetRowDisplayRectangle(e.RowIndex, true);
                var top = (rectR.Top + (int)(rectR.Height * .5f));
                Point displayPoint = new Point(left + this.ClientRectangle.Left, top + this.ClientRectangle.Top + 40);
                var column = e.ColumnIndex;
                var row = e.RowIndex;
                for (int i = 0; i < 5; ++i)
                {
                    ttText.Show(dataGridView1[column, row].Value.ToString(), this, displayPoint);
                    ttText.Hide(this);
                }
                ttText.Show(dataGridView1[column, row].Value.ToString(), this, displayPoint);
                this.ResumeLayout();
            }
        }
        private void dataGridView1_MouseLeave(object sender, EventArgs e)
        {
            Rectangle mouseRect = new Rectangle(MousePosition, new Size(1, 1));
            var rectC = dataGridView1.GetColumnDisplayRectangle(dataGridView1.Columns.Count - 1, true);
            var right = rectC.Right;
            var rectR = dataGridView1.GetRowDisplayRectangle(dataGridView1.Rows.Count - 1, true);
            var bottom = rectR.Bottom;
            var rect = new Rectangle(
                dataGridView1.PointToScreen(dataGridView1.Location),
                new Size(right, bottom));
            if (!rect.IntersectsWith(mouseRect))
                ttText.Hide(this);
        }
        void event_MouseMove(object sender, MouseEventArgs e)
        {
            dataGridView1_MouseLeave(sender, EventArgs.Empty);
        }
    }
    static class Program
    {
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new Form1());
        }
    }
}

我扩展了网格中的叙述,以帮助演示一般问题。

我知道这不是一个完全优雅的解决方案,但这就是封装的意义所在。

新问题。。。有可能在鼠标点显示气球工具提示的点吗?还是我只是在做白日梦?

现在,尽可能的解决方案。。。我读过一些关于继承Tool Tip对象以使用自定义类执行绘图的内容。用它来确定文本的大小,然后确定气球将显示的方向和文本的偏移量,这不可行吗?

在MSDN上,它提到对这类事情使用RenderSize属性,但有一些注意事项。

我避免截断工具提示的方法是显式设置工具提示文本。我认为微妙的是,默认的ToolTip文本使用相同的单元格内容,只有默认的处理程序会截断它,如原问题中所述。通过覆盖事件并设置工具提示文本(即使它是完全相同的单元格文本!),现在默认的长度限制似乎消失了。

protected override void OnCellToolTipTextNeeded(DataGridViewCellToolTipTextNeededEventArgs e)
{
    if((e.RowIndex >= 0) && (e.ColumnIndex >= 0))
    {
        // By setting this explicitly we can make the ToolTip show the           
        // entire length even though the content itself has not changed.
        e.ToolTipText = this[e.ColumnIndex, e.RowIndex].Value.ToString();
    }
    base.OnCellToolTipTextNeeded(e);
}