您的位置:首页 > 其它

DataGridView单元格字符超长,ToolTip冒泡提醒功能,可控制宽度和持续显示时间

2012-06-25 13:31 836 查看
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Windows.Forms;
using System.ComponentModel;

/*
* Bob 2012-06-25 写
* 自定义原因:DataGridView单元格默认ToolTip冒泡提醒无法控制其宽度和显示时间的,如果单元格字符超长,则ToolTip冒泡也会拉的很长,影响美观(真不知道有没有,所以自己写了一个)
* 注意:BindGridView属性(必选属性)不能为空
* 调用很简单:本来是写的一个类,但是后来干脆写成一个组件,使用更方便,托到窗体上,选择BindGridView属性和OwnerForm属性即可
* 说明:还有什么其他需求,可以自己扩展
*
* 关键属性:
* BindGridView属性 --> 绑定一个DataGridView控件
* OwnerForm属性 --> 绑定一个Form(即当前控件拖放窗体),主要(Duration = -1)时,当窗体失去焦点,隐藏ToolTip冒泡
* Duration属性 --> 冒泡持续时间,单位毫秒
* DisColumns属性 --> 指定需要冒泡的列,默认全部都显示(当文字超过单元格宽度时),注意是列的Name
* Width、MinWidth、MaxWidth --> 设置冒泡宽度
*
* Bug说明:
* 1、当单元格全部为数字、字母、数字字母混合则无法换行
* 2、当前DataGridView工作区域,DataGridView最后一行,鼠标从单元格下面移出,ToolTip不隐藏,所以有了OwnerForm属性
*/

namespace ProjectTest
{
/// <summary>
/// DataGridView显示自定义ToolTip冒泡
///  Bob 2012-06-25 写
/// </summary>
public class DataGridViewCellToolTip : System.ComponentModel.Component
{
ToolTipEx tooltip = null;
DataGridView dgvList = null;
Graphics graphics = null;
int CurrentRowIndex = -1;
int CurrentColIndex = -1;
int minWidth = -1;   //显示最小宽度
int maxWidth = -1;
int currentWidth = -1;
string[] colnames = null;       //要显示ToolTip提醒的列
private Form ownerForm = null;
int duration = -1;   //持续显示时间
#region 构造方法

/// <summary>
/// DataGridView显示自定义ToolTip冒泡
/// </summary>
public DataGridViewCellToolTip(DataGridView dgv)
{
InstallToolTip();
this.OwnerForm = null;
this.BindGridView = dgv;
this.colnames = new string[0];
}

/// <summary>
/// DataGridView显示自定义ToolTip冒泡
/// </summary>
public DataGridViewCellToolTip()
{
InstallToolTip();
}

/// <summary>
/// DataGridView显示自定义ToolTip冒泡
/// </summary>
/// <param name="dgv">要绑定的DataGridView控件</param>
public DataGridViewCellToolTip(Form ownerform, DataGridView dgv)
{
InstallToolTip();
this.OwnerForm = ownerform;
this.BindGridView = dgv;
this.colnames = new string[0];
}

/// <summary>
/// DataGridView显示自定义ToolTip冒泡
/// </summary>
/// <param name="dgv">要绑定的DataGridView控件</param>
/// <param name="columns">要冒泡列(为空或者Length等于0则所有列显示)</param>
public DataGridViewCellToolTip(Form ownerform, DataGridView dgv, string[] columns)
{
InstallToolTip();
this.OwnerForm = ownerform;
this.BindGridView = dgv;
this.colnames = columns;
}

#endregion

#region 属性

/// <summary>
/// 绑定DataGridView控件
/// </summary>
[DefaultValue(null)]
[Description("绑定DataGridView对象【必填项】")]
public DataGridView BindGridView
{
get { return dgvList; }
set
{
UninstallDgvEvents();
dgvList = value;
InstallDgvEvents();
}
}

/// <summary>
/// 所属窗体
/// </summary>
[Description("所属窗体,有利于弹出的冒泡隐藏【建议填写】")]
public Form OwnerForm
{
get { return ownerForm; }
set
{
UninstallFormDeactivate(ownerForm);
ownerForm = value;
InstallFormDeactivate(value);
}
}

/// <summary>
/// 要显示冒泡提醒的列名名字集合
/// </summary>
[Description("要显示冒泡提醒的列名名字集合")]
[DefaultValue(null)]
public string[] DisColumns
{
get { return colnames; }
set { colnames = value; }
}

/// <summary>
/// ToolTip显示最小宽度
/// </summary>
[DefaultValue(-1)]
public int MinWidth
{
get { return minWidth; }
set
{
if (value < -1)
{
throw new Exception("输入参数错误,不能小于-1");
}
if (value > maxWidth && maxWidth > -1)
{
minWidth = maxWidth;
}
else
{
minWidth = value;
}

if (currentWidth > -1 && minWidth > currentWidth)
{
currentWidth = minWidth;
}
}
}

/// <summary>
/// ToolTip显示最小宽度
/// </summary>
[DefaultValue(-1)]
public int MaxWidth
{
get { return maxWidth; }
set
{
if (value < -1)
{
throw new Exception("输入参数错误,不能小于-1");
}
maxWidth = value;
if (value > -1 && value < minWidth)
{
minWidth = value;
}

if (value > -1 && value < currentWidth)
{
currentWidth = value;
}
}
}

[DefaultValue(-1)]
[Description("冒泡宽度,如果为-1,则按DataGridView的列宽计算")]
public int Width
{
get { return currentWidth; }
set
{
if (value < -1)
{
throw new Exception("输入参数错误,不能小于-1");
}
if (value < minWidth && value > -1)
{
currentWidth = minWidth;
}
else if (value > maxWidth && maxWidth > -1)
{
currentWidth = maxWidth;
}
else
{
currentWidth = value;
}
}
}

[DefaultValue(-1)]
[Description("持续显示时间,单位毫秒,默认值(-1)则一直显示")]
public int Duration
{
get { return duration; }
set
{
if (value < -1)
{
throw new Exception("输入参数错误,不能小于-1");
}
duration = value;
}
}

/// <summary>
/// 对外公开ToolTip对象[只读]
/// </summary>
//public ToolTipEx ToolTipControl
//{
//    get { return tooltip; }
//}
#endregion

#region 方法
private void InstallDgvEvents()
{
if (dgvList == null)
{
throw new Exception("DataGridView对象不能为空!");
}
graphics = dgvList.CreateGraphics();
dgvList.ShowCellToolTips = false;
dgvList.CellMouseEnter += new DataGridViewCellEventHandler(DgvCellToolTip_CME);
dgvList.MouseDown += new MouseEventHandler(DgvCellToolTip_MD);
}

private void UninstallDgvEvents()
{
if (dgvList != null)
{
try
{
dgvList.CellMouseEnter -= DgvCellToolTip_CME;
dgvList.MouseDown -= DgvCellToolTip_MD;
}
catch { }
}
}

private void InstallToolTip()
{
if (tooltip == null)
{
tooltip = new ToolTipEx(this);
//tooltip.ToolTipIcon = ToolTipIcon.Info;
//tooltip.ToolTipTitle = "Test";
tooltip.Popup += new PopupEventHandler(tooltip_Popup);
}
}

/// <summary>
/// 窗体失去焦点 ToolTip隐藏
/// </summary>
/// <param name="form"></param>
private void InstallFormDeactivate(Form form)
{
if (form != null)
{
form.Deactivate += new EventHandler(OF_DActive);
InstallFormDeactivate(form.ParentForm);
}
}

private void UninstallFormDeactivate(Form form)
{
if (form != null)
{
form.Deactivate -= OF_DActive;
InstallFormDeactivate(form.ParentForm);
}
}

private void ResetIndex()
{
CurrentRowIndex = CurrentColIndex = -1;
}
#endregion

#region 事件绑定方法
private void OF_DActive(object sender, EventArgs e)
{
if (!dgvList.IsDisposed)
{
tooltip.Hide(dgvList);
}
}

/// <summary>
/// 显示前 控制Size
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void tooltip_Popup(object sender, PopupEventArgs e)
{
ToolTipEx tp = sender as ToolTipEx;
if (tp != null)
{
int width = currentWidth;
if (CurrentColIndex > -1 && currentWidth == -1)
{
width = dgvList.Columns[CurrentColIndex].Width;
}
if (width < minWidth)
{
width = minWidth;
}
else if (width > maxWidth && maxWidth > -1)
{
width = maxWidth;
}
Size size = this.MeasureString(graphics, tp.ToolTipText, dgvList.DefaultCellStyle.Font, width);
e.ToolTipSize = new Size(width, size.Height + 6);
}
}

private void DgvCellToolTip_CME(object sender, DataGridViewCellEventArgs e)
{
if (e.ColumnIndex > -1 && e.RowIndex > -1)
{
//单元格没有发送改变则不需要显示,防止闪烁
if (CurrentRowIndex != e.RowIndex || CurrentColIndex != e.ColumnIndex)
{
CurrentRowIndex = e.RowIndex;
CurrentColIndex = e.ColumnIndex;
string colname = dgvList.Columns[e.ColumnIndex].Name;
//string existname = colnames.FirstOrDefault(n => n.Equals(colname));  //是否存在名字
if (IsDisplayToolTip(colname))
{
DataGridViewCell cell = dgvList.Rows[e.RowIndex].Cells[e.ColumnIndex];
if (cell.Value != null)
{
string cellvalue = cell.Value.ToString();
//计算文字显示Size
Size size = this.MeasureString(graphics, cellvalue, dgvList.DefaultCellStyle.Font);
int width = dgvList.Columns[e.ColumnIndex].Width;
//文字宽度大于列宽
if (size.Width >= width)
{
Point cellPoint = dgvList.GetCellDisplayRectangle(e.ColumnIndex, e.RowIndex, false).Location;
tooltip.Show(cellvalue, dgvList, cellPoint.X, cellPoint.Y + dgvList.Rows[e.RowIndex].Height, duration);
return;
}
}
}

}
else
return;  //相同单元格返回,不做任何操作,否则当ToolTip覆盖单元格时,鼠标放到ToolTIp上会闪烁(不断的隐藏和显示)
}
tooltip.Hide(dgvList);
}

private bool IsDisplayToolTip(string colname)
{
bool ret = true;
if (colnames != null && colnames.Length > 0)
{
string existname = colnames.FirstOrDefault(n => n.Equals(colname));  //是否存在名字
if (existname == null)
{
ret = false;
}
}
return ret;
}

private void DgvCellToolTip_MD(object sender, MouseEventArgs e)
{
tooltip.Hide(dgvList);
}
#endregion

#region 获取文本高度
protected Size MeasureString(Graphics g, String content, Font font, int width)
{
//首先得到每一行文本的标准高度
SizeF sizef = g.MeasureString(content, font, width);
Size size = Size.Round(sizef);
return size;
}

protected Size MeasureString(Graphics g, String content, Font font)
{
//首先得到每一行文本的标准高度
SizeF sizef = g.MeasureString(content, font);
Size size = Size.Round(sizef);
return size;
}
#endregion

#region 自定义ToolTip对象
/// <summary>
/// Bob 2012-06-25 重写ToolTip组件
/// </summary>
class ToolTipEx : ToolTip
{
string _ToolTipText;
int _defaultduration = -1;
DataGridViewCellToolTip _DGVToolTip;

public ToolTipEx()
: base()
{
_ToolTipText = String.Empty;
}

public ToolTipEx(DataGridViewCellToolTip dgvtooltip)
: base()
{
_DGVToolTip = dgvtooltip;
_ToolTipText = String.Empty;
}

public ToolTipEx(System.ComponentModel.IContainer container)
: base(container)
{
_ToolTipText = String.Empty;
}

public ToolTipEx(DataGridViewCellToolTip dgvtooltip, System.ComponentModel.IContainer container)
: base(container)
{
_DGVToolTip = dgvtooltip;
_ToolTipText = String.Empty;
}

public string ToolTipText
{
get { return _ToolTipText; }
}

public new void SetToolTip(Control control, string caption)
{
_ToolTipText = caption;
base.SetToolTip(control, caption);
}

public new void Show(string text, IWin32Window window, int x, int y)
{
_ToolTipText = text;
base.Show(text, window, x, y);
}

public new void Show(string text, IWin32Window window)
{
_ToolTipText = text;
base.Show(text, window);
}

public new void Show(string text, IWin32Window window, int duration)
{
_ToolTipText = text;
if (duration > _defaultduration)
{
base.Show(text, window, duration);
}
else
{
base.Show(text, window);
}
}

public new void Show(string text, IWin32Window window, Point point)
{
_ToolTipText = text;
base.Show(text, window, point);
}

public new void Show(string text, IWin32Window window, Point point, int duration)
{
_ToolTipText = text;
if (duration > _defaultduration)
{
base.Show(text, window, point, duration);
}
else
{
base.Show(text, window, point);
}
}

public new void Show(string text, IWin32Window window, int x, int y, int duration)
{
_ToolTipText = text;
if (duration > _defaultduration)
{
base.Show(text, window, x, y, duration);
}
else
{
base.Show(text, window, x, y);
}
}

public new void Hide(IWin32Window window)
{
_ToolTipText = String.Empty;
base.Hide(window);
if (_DGVToolTip != null)
{
_DGVToolTip.ResetIndex();
}
}
}
#endregion
}
}


使用: 托到窗体上,选择BindGridView属性(必选)和OwnerForm属性(建议选择)即可

本来想上传几张效果图的,不知道怎么了我没有上次图片的权限了
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐