65.9K
CodeProject 正在变化。 阅读更多。
Home

构建 C# 中的气球工具提示提供程序

starIconstarIconstarIconstarIconstarIcon

5.00/5 (8投票s)

2004年2月25日

CPOL

4分钟阅读

viewsIcon

120597

downloadIcon

2104

演示了如何创建支持气球形工具提示的 ToolTip 提供程序,包括创建扩展属性和使用 NativeWindow 类相关的问题。

Sample Image - BallonTipExample.jpg

引言

System.Windows.Forms 命名空间包含一个内置类,用于在控件上显示工具提示。但是,此 ToolTip 控件不支持创建 IE 3.0 及更高版本中提供的可爱气球形工具提示。此类提供了一个托管包装器,用于支持显示气球形工具提示的 Win32 Tooltip 公共控件。

使用控件

该控件提供与 .NET 附带的当前 ToolTip 提供程序完全相同的功能。要在窗体或控件上使用它,只需将控件的一个实例从 Visual Studio .Net 工具箱拖到窗体上。添加后,窗体上的每个控件将拥有一个新的 ToolTip 属性,您可以为特定对象设置该属性。Visual Studio 将自动添加必要的代码,将控件的工具提示连接到 BallonToolTip 提供程序。

API

API 由 .NET Framework 提供的标准 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

使用 ProviderProperty 属性有一些技巧。一方面,它被添加到的类必须同时提供 GetXSetX 方法,其中 X 是传递给 ProvideProperty 属性的属性的名称。此外,您的 GetX 方法应使用 DefaultValue 属性进行修饰,以减少设计器需要创建的代码量。对于 BallonToolTip 提供程序,GetToolTip 方法的修饰如下:

[DefaultValue("")]
public string GetToolTip(Control control)

令人烦恼的是,当 SetToolTip 方法在具有工具提示的类的 InitializeComponent 方法中被调用时,控件可能尚未创建句柄。为了处理这种情况,当任何控件被传递给 SetToolTip 时,BallonToolTip 控件会挂钩 Control 基类的 HandleCreate 事件。当此事件触发时,工具提示提供程序会自动使用新创建控件的信息更新底层的 Win32 工具提示窗口。为了完整起见,SetToolTip 方法还挂钩 HandleDestroyed 事件,以便在控件被销毁时删除本机工具提示(在典型的窗体中,这通常不是问题,因为控件的销毁时间与提供程序的销毁时间大致相同)。

使用 NativeWindow 类

System.Windows.Forms 命名空间中一个鲜为人知的类是 NativeWindow 类。这个类唯一的目的是提供 Win32 CreateWindowEx 函数的托管包装器。在 BallonToolTip 方法中,我创建了一个派生的 NativeWindow 类(NativeTooltipWindow),它提供了一些围绕此类的有用包装器。例如,NativeTooltipWindow 构建了 CreateParams 结构,用于在不接受外部类输入的情况下创建本机 ToolTip 提供程序。这样,关于如何创建窗口的知识就被封装在了实际执行创建的类中(有关其他注释和信息,请参阅源代码)。

支持 Win9X

在向底层 Win32 Tooltip 窗口发送消息时,某些消息需要根据我们是在 Windows 9x 计算机(使用基于 ASCII 的文本)还是 NT 系统(使用 Unicode)上运行来发送不同的值。在类构造过程中,我们设置了 readonly ints,以便在代码中更轻松地处理这种差异。

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;

/// <SUMMARY>
/// Initializes a new instance of the
/// <SEE cref="ToolTipLibrary.BallonToolTip" /> class.
/// </SUMMARY>
public BallonToolTip()
{    
    m_controls = new Hashtable();
    m_active = true;
    m_showAlways = false;

    //Create a new native window.
    m_window = new NativeTooltipWindow();

    if (Marshal.SystemDefaultCharSize == 1)
    {
        //Win9x machines
        TTM_ADDTOOL = TTM_ADDTOOLA;
        TTM_UPDATETIPTEXT = TTM_UPDATETIPTEXTA;
        TTM_DELTOOL = TTM_DELTOOLA;
    }
    else
    {
        //WinNT machines
        TTM_ADDTOOL = TTM_ADDTOOLW;
        TTM_UPDATETIPTEXT = TTM_UPDATETIPTEXTW;
        TTM_DELTOOL = TTM_DELTOOLW;
    }

    InitializeComponent();
}

在代码中,我们从不使用上述常量。相反,我们始终引用 readonly 成员变量,以确保我们为平台发送了正确的消息。

变更

2004 年 3 月 4 日 - 修复了 CreateHandle 方法中的一个错误,该错误在工具提示句柄不存在时创建它。

© . All rights reserved.