本文重构了ToolTip组件,只为可以在上面显示图片所作,具体参考如下代码:
重写ToolTip
- using System.Drawing;
- using System.Drawing.Drawing2D;
- using System.Windows.Forms;
- using System;
- using System.Diagnostics;
- using System.ComponentModel;
- namespace CustomToolTipDemo
- {
- /// <summary>
- /// CustomizedToolTip to create tooltips with Image.
- /// </summary>
- internal class CustomizedToolTip : ToolTip
- {
- #region Constants
- /// <summary>
- /// 边框的粗细度
- /// </summary>
- private const int BORDER_THICKNESS = 2;
- #endregion
- #region Fields
- private static Color myBorderColor = Color.Red;
- private static Font myFont = new Font("Arial", 8);
- private StringFormat myTextFormat = new StringFormat();
- private Rectangle myImageRectangle = new Rectangle();
- private Rectangle myToolTipRectangle = new Rectangle();
- private Brush myBackColorBrush = new SolidBrush(Color.LightYellow);
- private Brush myTextBrush = new SolidBrush(Color.Black);
- private Brush myBorderBrush = new SolidBrush(myBorderColor);
- private Size mySize = new Size(500, 500);
- #endregion
- #region Properties
- /// <summary>
- /// 获取或设置一个值,该值指示工具提示是由操作系统绘制还是由您提供的代码绘制。若是true,表示ToolTipIcon和ToolTipTitle这两个属性值将被设为默认值并且工具提示将显示图片,否则将只显示文本提示信息
- /// </summary>
- public new bool OwnerDraw
- {
- get
- {
- return base.OwnerDraw;
- }
- set
- {
- if (value)
- {
- this.ToolTipIcon = ToolTipIcon.None;
- this.ToolTipTitle = string.Empty;
- }
- base.OwnerDraw = value;
- }
- }
- /// <summary>
- /// 获取或设置一个值,该值定义要在工具提示文本旁显示的图标的类型。当OwnerDraw属性值为true时,无法设置该属性
- /// </summary>
- public new ToolTipIcon ToolTipIcon
- {
- get
- {
- return base.ToolTipIcon;
- }
- set
- {
- if (!OwnerDraw)
- {
- base.ToolTipIcon = value;
- }
- }
- }
- /// <summary>
- /// 获取或设置工具提示窗口的标题。当OwnerDraw属性值为true时,无法设置该属性
- /// </summary>
- public new string ToolTipTitle
- {
- get
- {
- return base.ToolTipTitle;
- }
- set
- {
- if (!OwnerDraw)
- {
- base.ToolTipTitle = value;
- }
- }
- }
- /// <summary>
- /// 获取或设置工具提示的背景色
- /// </summary>
- public new Color BackColor
- {
- get
- {
- return base.BackColor;
- }
- set
- {
- base.BackColor = value;
- Brush temp = myBackColorBrush;
- myBackColorBrush = new SolidBrush(value);
- temp.Dispose();
- }
- }
- /// <summary>
- /// 获取或设置工具提示的前景色
- /// </summary>
- public new Color ForeColor
- {
- get
- {
- return base.ForeColor;
- }
- set
- {
- base.ForeColor = value;
- Brush temp = myTextBrush;
- myTextBrush = new SolidBrush(value);
- temp.Dispose();
- }
- }
- /// <summary>
- /// 获取或设置工具提示窗口的大小
- /// </summary>
- public Size Size
- {
- get { return mySize; }
- set
- {
- mySize = value;
- myToolTipRectangle.Size = mySize;
- }
- }
- /// <summary>
- /// 获取或设置工具提示窗口边框的颜色
- /// </summary>
- public Color BorderColor
- {
- get
- {
- return myBorderColor;
- }
- set
- {
- myBorderColor = value;
- Brush temp = myBorderBrush;
- myBorderBrush = new SolidBrush(value);
- temp.Dispose();
- }
- }
- #endregion
- #region Constructor
- /// <summary>
- /// 构造一个可以显示图片的ToolTip类实例
- /// </summary>
- public CustomizedToolTip()
- {
- try
- {
- this.OwnerDraw = true;
- myTextFormat.FormatFlags = StringFormatFlags.LineLimit;
- myTextFormat.Alignment = StringAlignment.Near;
- myTextFormat.LineAlignment = StringAlignment.Center;
- myTextFormat.Trimming = StringTrimming.None;
- this.Popup += new PopupEventHandler(CustomizedToolTip_Popup);
- this.Draw += new DrawToolTipEventHandler(CustomizedToolTip_Draw);
- }
- catch (Exception ex)
- {
- string logMessage = "Exception in CustomizedToolTip.CustomizedToolTip () " + ex.ToString();
- Trace.TraceError(logMessage);
- throw;
- }
- }
- #endregion
- #region Methods
- /// <summary>
- /// 释放组件
- /// </summary>
- protected override void Dispose(bool disposing)
- {
- try
- {
- try
- {
- if (disposing)
- {
- if (myFont != null)
- {
- myFont.Dispose();
- }
- if (myTextBrush != null)
- {
- myTextBrush.Dispose();
- }
- if (myBackColorBrush != null)
- {
- myBackColorBrush.Dispose();
- }
- if (myBorderBrush != null)
- {
- myBorderBrush.Dispose();
- }
- if (myTextFormat != null)
- {
- myTextFormat.Dispose();
- }
- }
- }
- finally
- {
- base.Dispose(disposing);
- }
- }
- catch (Exception ex)
- {
- string logMessage = "Exception in CustomizedToolTip.Dispose (bool) " + ex.ToString();
- Trace.TraceError(logMessage);
- throw;
- }
- }
- /// <summary>
- /// 当绘制工具提示提示并且OwnerDraw属性设置为true时发生
- /// </summary>
- void CustomizedToolTip_Draw(object sender, DrawToolTipEventArgs e)
- {
- try
- {
- e.Graphics.CompositingQuality = CompositingQuality.HighQuality;
- myToolTipRectangle.Size = e.Bounds.Size;
- //this condition add @2010-11-23
- if (myToolTipRectangle.Width == 540) //抑制listview项的自带提示信息覆盖图片
- {
- e.Graphics.FillRectangle(myBorderBrush, myToolTipRectangle);
- myImageRectangle = Rectangle.Inflate(myToolTipRectangle, -BORDER_THICKNESS, -BORDER_THICKNESS);
- e.Graphics.FillRectangle(myBackColorBrush, myImageRectangle);
- Control parent = e.AssociatedControl;
- Image toolTipImage = parent.Tag as Image;
- if (toolTipImage != null)
- {
- e.Graphics.DrawImage(toolTipImage, myImageRectangle);
- }
- else
- {
- e.Graphics.DrawString(e.ToolTipText, myFont, myTextBrush, myImageRectangle, myTextFormat);
- }
- }
- }
- catch (Exception ex)
- {
- string logMessage = "Exception in CustomizedToolTip.BlindHeaderToolTip_Draw (object, DrawToolTipEventArgs) " + ex.ToString();
- Trace.TraceError(logMessage);
- throw;
- }
- }
- /// <summary>
- /// 在工具提示最初显示之前发生
- /// </summary>
- void CustomizedToolTip_Popup(object sender, PopupEventArgs e)
- {
- try
- {
- if (OwnerDraw)
- {
- e.ToolTipSize = mySize;
- }
- }
- catch (Exception ex)
- {
- string logMessage = "Exception in CustomizedToolTip.CustomizedToolTip_Popup (object, PopupEventArgs) " + ex.ToString();
- Trace.TraceError(logMessage);
- throw;
- }
- }
- #endregion
- }
- }
实例:
- using System;
- using System.Collections.Generic;
- using System.ComponentModel;
- using System.Data;
- using System.Drawing;
- using System.Text;
- using System.Windows.Forms;
- using CustomToolTipDemo.Properties;
- namespace CustomToolTipDemo
- {
- public partial class Form1 : Form
- {
- /// <summary>
- /// 构造一个可以显示图片的ToolTip类实例
- /// </summary>
- CustomizedToolTip myToolTip = new CustomizedToolTip();
- public Form1()
- {
- InitializeComponent();
- // 设定工具提示窗口的大小
- myToolTip.Size = new Size(600, 300);
- }
- /// <summary>
- /// 当鼠标悬停于某项上时,给出带有图片的提示信息
- /// </summary>
- private void listView1_ItemMouseHover(object sender, ListViewItemMouseHoverEventArgs e)
- {
- switch (e.Item.Text) //根据项的文本值提示相应信息
- {
- case "item1":
- myToolTip.SetToolTip(listView1, "Title");
- listView1.Tag = Resources.Image1; //设定要提示的图片
- break;
- case "item2":
- myToolTip.SetToolTip(listView1, "Title");
- listView1.Tag = Resources.Image2;
- break;
- default:
- break;
- }
- }
- /// <summary>
- /// 当鼠标处于“无项区域”时,立即“隐藏”提示信息窗口
- /// </summary>
- private void listView1_MouseMove(object sender, MouseEventArgs e)
- {
- ListViewHitTestInfo info = listView1.HitTest(e.Location);
- if (info.Item == null) //是否处于“无项区域”
- {
- myToolTip.SetToolTip(listView1, "");
- listView1.Tag = null;
- }
- }
- }
- }
最后,会有一个问题:比如listView上有项item1、item2、…如本例给出的参考代码,当鼠标悬停于某项(如item1)上时,第一次可以正常显示带有图片的提示信息,然后我们在这个时候把鼠标移到“无项区域”,然后再把鼠标悬停于item1,此时我们会发现没有提示信息出现,只有先移到其他项(如item2)后再悬停于item1时,才会使提示信息重现。本人愚昧,这个问题还不得而解,还请各位不吝赐教。。
///ADD @2010-11-15
昨日的问题终于得到解决,无需ItemMouseHover事件,只需MouseMove外加一个全局变量tooltipOn用来保存当前提示信息项 即可。具体参考如下代码:
- /// <summary>
- /// 当前提示信息项
- /// </summary>
- ListViewItem tooltipOn;
- /// <summary>
- /// 根据项文本内容显示带有图片的提示信息
- /// </summary>
- private void listView1_MouseMove(object sender, MouseEventArgs e)
- {
- ListViewItem item = listView1.HitTest(e.Location).Item;
- if (item != null)
- {
- //如果不是当前提示信息项,更新提示信息及提示信息项
- if (item != tooltipOn)
- {
- switch (item.Text) //根据项的文本值提示相应信息
- {
- case "item1":
- //设定要提示的图片
- listView1.Tag = Resources.Image1;
- break;
- case "item2":
- listView1.Tag = Resources.Image2;
- break;
- default:
- break;
- }
- showToolTip(Cursor.Position, e.Location);
- tooltipOn = item;
- }
- }
- else //若鼠标处于“无项区域”,则清空提示信息相关的信息
- {
- myToolTip.Hide(listView1);
- listView1.Tag = null;
- tooltipOn = null;
- }
- }
- #region 根据所在位置显示tooltip
- /// <summary>
- /// 根据所在位置显示tooltip
- /// </summary>
- /// <param name="screenPos">当前屏幕坐标点</param>
- /// <param name="listViewPos">当前ListView坐标点</param>
- private void showToolTip(Point screenPos, Point listViewPos)
- {
- if (screenPos.X + 540 > Screen.AllScreens[0].WorkingArea.Width) //越过工作区右边界
- {
- int X = listViewPos.X - (540 + 5); //定位提示信息的左边界
- if (X < listViewPos.X - screenPos.X + 5) //越过左边界
- {
- X = listViewPos.X - screenPos.X + 5; //定位左边界位于工作区左边界offset=5
- }
- if (screenPos.Y + 235 > Screen.AllScreens[0].WorkingArea.Height) //越过工作区下边界
- {
- //鼠标左上区域显示tooltip
- myToolTip.Show("Caption", listView1, X, listViewPos.Y - (235 + 5));
- }
- else
- {
- //鼠标左下区域显示tooltip
- myToolTip.Show("Caption", listView1, X, listViewPos.Y + 5);
- }
- }
- else if (screenPos.X - 540 < 0) //越过工作区左边界
- {
- if (screenPos.Y + 235 > Screen.AllScreens[0].WorkingArea.Height) //越过工作区下边界
- {
- //鼠标右上区域显示tooltip
- myToolTip.Show("Caption", listView1, listViewPos.X + 5, listViewPos.Y - (235 + 5));
- }
- else
- {
- //鼠标右下区域显示tooltip
- myToolTip.Show("Caption", listView1, listViewPos.X + 5, listViewPos.Y + 5);
- }
- }
- else //默认都是在鼠标右下区域显示tooltip
- {
- myToolTip.Show("Caption", listView1, listViewPos.X + 5, listViewPos.Y + 5);
- }
- }
- #endregion
- //说明上面的540和235是提示信息中图片的宽和高
注: 如果不用一个全局变量来保存当前提示信息项,也就是把if (item != tooltipOn) 这个判断逻辑拿掉,提示信息则会一直不停的闪烁。。