在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);
}
}
}
}
如果将鼠标悬停在第一列上,然后悬停在第二列上,则工具提示文本将被截断。
好吧,我发布这个问题已经好几个月了。从那时起,我就没有真正考虑过这个问题——只是接受了这种行为。。。直到今晚。
由于没有其他人想到答案(或者愿意提供另一个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);
}