在.NET框架中,标准的ToolTip控件提供了基本的提示功能,但它并不支持IE 3.0及以上版本中的可爱气球提示样式。为了实现这种视觉效果,可以通过创建一个自定义的气球提示工具类来扩展.NET的Win32Tooltip控件的功能。
这个自定义的气球提示工具类提供了与.NET自带的ToolTip控件相似的功能。要在窗体或控件上使用它,只需从Visual Studio的toolbox中拖拽一个实例到窗体上。添加后,窗体上的每个控件都会有一个新的ToolTip属性,可以为特定对象设置。Visual Studio会自动添加必要的代码,将控件的提示与BallonToolTip提供者关联起来。
API接口与.NET框架提供的标凈ToolTip类相同。每个BallonToolTip类的实例可以为多个控件提供工具提示。要为控件设置提示,可以使用SetToolTip方法:
public void SetToolTip(Control control, string tooltip)
同样,要获取给定控件的提示,可以使用GetToolTip方法:
public string GetToolTip(Control control)
与ToolTip类一样,BallonToolTip类在设计时也支持设置提示。要为任何属性添加此支持,首先,类必须派生自System.ComponentModel.Component。其次,类必须使用ProvideProperty属性进行装饰,并实现IExtenderProvider接口。ProvideProperty属性为设计器提供了应该添加到任何控件的属性的名称和类型,这些控件的IExtenderProvider.CanExtend方法返回true。这两个元素共同工作,为窗体上的每个控件提供ToolTip属性。
BallonToolTip类的声明如下:
[ProvideProperty("ToolTip", typeof(Control))]
public class BallonToolTip : Component, IExtenderProvider
使用ProvideProperty属性时有一些技巧。首先,添加到的类必须提供GetX和SetX方法,其中X是传递给ProvideProperty属性的属性名称。其次,GetX方法应该使用DefaultValue属性进行装饰,以减少设计器需要创建的代码量。在BallonToolTip提供者的情况下,GetToolTip方法被装饰如下:
[DefaultValue("")]
public string GetToolTip(Control control)
当从类所在的InitializeComponent方法中调用SetToolTip时,提示可能尚未存在。为了处理这种情况,BallonToolTip控件在任何控件传递给SetToolTip时,会钩住Control基类的HandleCreate事件。当此事件触发时,提示提供者会自动使用新创建的控件的信息更新底层Win32提示窗口。为了完整性,SetToolTip方法还钩住了HandleDestroyed事件,以便在控件被销毁时删除本地提示(在典型的窗体中,这并不是一个真正的问题,因为控件将在提供者被销毁的同时或几乎同时被销毁)。
System.Windows.Forms命名空间中有一个鲜为人知的类,即NativeWindow类。这个类的唯一目标是为Win32CreateWindowEx函数提供一个托管的包装器。在BallonToolTip方法中,创建了一个派生的NativeWindow类(NativeTooltipWindow),它提供了一些有用的包装器。例如,NativeTooltipWindow构建了用于创建本地提示提供者的CreateParams结构,而不需要外部类的输入。这样,关于如何创建窗口的知识就封装在实际执行创建的类中(有关更多评论和信息,请参见源代码)。
在向底层Win32提示窗口发送消息时,有些消息需要根据在Windows 9x机器上运行(使用基于ASCII的文本)还是基于NT的系统(使用Unicode)来发送不同的值。在类的构造过程中,设置了readonly int,以便在代码中更容易地处理这种差异:
private const int TTM_ADDTOOLA = 1028;
private const int TTM_ADDTOOLW = 1074;
private const int TTM_UPDATETIPTEXTA = 1036;
private const int TTM_UPDATETIPTEXTW = 1081;
private const int TTM_DELTOOLA = 1029;
private const int TTM_DELTOOLW = 1075;
private readonly int TTM_ADDTOOL;
private readonly int TTM_UPDATETIPTEXT;
private readonly int TTM_DELTOOL;