📄 ballontooltip.cs
字号:
using System;
using System.Collections;
using System.Drawing;
using System.ComponentModel;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using gowk.common;
namespace ToolTipLibrary
{
/// <summary>
/// Displays text with a cartoon-style "balloon" with a stem pointing to the tool.
/// </summary>
[ProvideProperty("ToolTip", typeof(Control))]
public class BallonToolTip : Component, IExtenderProvider
{
//Reference to the Native win32 window
NativeTooltipWindow m_window;
//Hashtable of controls. The keys are Control references and the values are
// the tooltip text to display with each control.
private Hashtable m_controls;
//True if tooltips are on. False otherwise.
private bool m_active;
//True if tooltips should always be shown. False otherwise.
private bool m_showAlways;
#region Win32 Constants
private const int TTM_TRACKACTIVATE = 1041;
private const int TTF_CENTERTIP = 2;
private const int TTF_TRANSPARENT = 256;
private const int TTM_ACTIVATE = 0x0401;
private const int TTF_SUBCLASS = 0x0010;
private const int TTF_IDISHWND = 1;
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;
#endregion
#region Constructors
/// <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();
}
/// <summary>
/// Initializes a new instance of the <see cref="ToolTipLibrary.BallonToolTip"/>
/// class attached to a container.
/// </summary>
/// <param name="container">
/// The container of the control to add tool tips.
/// </param>
public BallonToolTip(System.ComponentModel.IContainer container) : this()
{
///
/// Required for Windows.Forms Class Composition Designer support
///
container.Add(this);
}
#endregion
#region Dispose Override
/// <summary>
/// Releases the unmanaged resources used by the Component.
/// </summary>
/// <param name="disposing">
/// <b>true</b> to release both managed and unmanaged resources; <b>false</b>
/// to release only unmanaged resources.
/// </param>
protected override void Dispose(bool disposing)
{
if (m_window.Handle != IntPtr.Zero)
{
m_window.DestroyHandle();
}
base.Dispose(disposing);
}
#endregion
#region Component Designer generated code
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.Container components;
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
components = new System.ComponentModel.Container();
}
#endregion
#region Public Properties / Methods
/// <summary>
/// Gets or sets a value indicating whether the ToolTip is currently active.
/// </summary>
/// <value>true if the ToolTip is currently active; otherwise, false. The default is true.</value>
[DefaultValue(true), Category("Misc"),
Description("Determines if the tooltip is active. Tips will not appear if the ToolTip is not active.")]
public bool Active
{
get
{
return m_active;
}
set
{
if (m_active != value)
{
m_active = value;
if (m_window.IsHandleCreated)
{
NativeMethods.SendMessage(m_window.Handle, TTM_ACTIVATE, value ? 1 : 0, 0);
}
}
}
}
/// <summary>
/// Gets or sets if tooltips should always be displayed.
/// </summary>
/// <value>true if tooltips should always be displayed. false otherwise. The default is false.</value>
[DefaultValue(false), Category("Misc"),
Description("If true, tips are always displayed, even if the mouse is not over the control")]
public bool ShowAlways
{
get
{
return m_showAlways;
}
set
{
if (value != m_showAlways)
{
m_showAlways = value;
if (m_window.IsHandleCreated)
{
SetTrackActive();
}
}
}
}
/// <summary>
/// Retrieves the ToolTip text associated with the specified control.
/// </summary>
/// <param name="control">The Control for which to retrieve the ToolTip text.</param>
/// <returns>The ToolTip text for the specified control.</returns>
[DefaultValue("")]
public string GetToolTip(Control control)
{
string retval = (string)m_controls[control];
if (retval == null)
return "";
return retval;
}
/// <summary>
/// Associates ToolTip text with the specified control.
/// </summary>
/// <param name="control">
/// The Control whos ToolTip text you want to update.
/// </param>
/// <param name="text">
/// The ToolTip text to display when the mouse cursor is over the control.
/// </param>
public void SetToolTip(Control control, string text)
{
bool newControl;
bool removeText;
if (control == null)
throw new ArgumentNullException("control");
newControl = !m_controls.ContainsKey(control);
removeText = text == null || text.Length == 0;
if (newControl)
{
if (!removeText)
{
m_controls[control] = text;
if (!this.DesignMode)
{
control.HandleCreated +=new EventHandler(HandleCreated);
control.HandleDestroyed +=new EventHandler(HandleDestroyed);
if (control.IsHandleCreated)
HandleCreated(control, EventArgs.Empty);
}
}
}
else
{
if (removeText)
{
RemoveControl(control);
}
else
{
//Update the tooltip
UpdateControlText(control, text);
}
}
}
#endregion
#region Private Methods
#region GetToolInfo Methods
/// <summary>
/// Creates and initializes a TOOLINFO structure.
/// </summary>
/// <param name="control">Control reference</param>
/// <param name="text">Tooltip to display for the control.</param>
/// <returns>A filled in TOOLINFO structure</returns>
private NativeMethods.TOOLINFO GetToolInfo(Control control, string text)
{
return GetToolInfo(control, text, 0);
}
/// <summary>
/// Creates and initializes a TOOLINFO structure with given set of flags.
/// </summary>
/// <param name="control">Control reference</param>
/// <param name="text">Tooltip to display for the control.</param>
/// <param name="flags">Flags info</param>
/// <returns>A filled in TOOLINFO structure</returns>
private NativeMethods.TOOLINFO GetToolInfo(Control control, string text, int flags)
{
NativeMethods.TOOLINFO ti = new NativeMethods.TOOLINFO(flags);
ti.flags |= TTF_IDISHWND;
ti.uId = control.Handle;
ti.text = text;
return ti;
}
#endregion
#region IExtenderProvider Members
/// <summary>
/// Specifies whether this object can provide its extender properties to
/// the specified object.
/// </summary>
/// <param name="extendee">The Object to receive the extender properties.</param>
/// <returns>
/// true if this object can provide extender properties to the specified
/// object; otherwise, false.
/// </returns>
bool IExtenderProvider.CanExtend(object extendee)
{
return (extendee is Control);
}
#endregion
#region Window Handle Event Handlers
/// <summary>
/// Registers the control with the tooltip window when its handle is created.
/// </summary>
/// <param name="sender">Control that raised the event.</param>
/// <param name="e">Event arguements</param>
private void HandleCreated(object sender, EventArgs e)
{
//Add the control to the list and create a new tooltip
CreateToolTip((Control)sender);
this.UpdateIcon();
}
/// <summary>
/// Deletes the control from the tooltip window when its handle is destroyed.
/// </summary>
/// <param name="sender">Control that raised the event.</param>
/// <param name="e">Event arguements</param>
private void HandleDestroyed(object sender, EventArgs e)
{
RemoveControl((Control)sender);
}
#endregion
/// <summary>
/// Activates or deactivates Active tracking for all tooltips.
/// </summary>
private void SetTrackActive()
{
foreach (Control control in m_controls.Keys)
{
NativeMethods.TOOLINFO ti = GetToolInfo(control, null);
NativeMethods.SendMessage(m_window.Handle, TTM_TRACKACTIVATE, m_showAlways ? 1 : 0, ref ti);
}
}
/// <summary>
/// Creates a new tooltip for a control.
/// </summary>
/// <param name="control">
/// The Control whos ToolTip text you want to set.
/// </param>
private void CreateToolTip(Control control)
{
//Create the underlying handle if it does not already exist.
CreateWindowHandle(control);
/////////////////////////
this.SetArgs();
/////////////////////////
//Get the text for the control
string text = GetToolTip(control);
// Do the standard ToolTip coding.
NativeMethods.TOOLINFO ti = GetToolInfo(control, text, TTF_TRANSPARENT | TTF_SUBCLASS );
//Send the ADDTOOL message to add the tooltip
NativeMethods.SendMessage(m_window.Handle, TTM_ADDTOOL, 0, ref ti);
}
/// <summary>
/// Updates the text associated with a control.
/// </summary>
/// <param name="control">
/// The Control whos ToolTip text you want to update.
/// </param>
/// <param name="text">
/// The ToolTip text to display when the mouse cursor is over the control.
/// </param>
private void UpdateControlText(Control control, string text)
{
//Store the text.
m_controls[control] = text;
if (control.IsHandleCreated)
{
//Update the tooltip window control.
NativeMethods.TOOLINFO ti = GetToolInfo(control, text);
NativeMethods.SendMessage(m_window.Handle, TTM_UPDATETIPTEXT, 0, ref ti);
}
}
/// <summary>
/// Removes the control from the tooltip provider.
/// </summary>
/// <param name="control">
/// The Control you no longer want to display tooltips for.
/// </param>
private void RemoveControl(Control control)
{
//Unhook events
control.HandleCreated -=new EventHandler(HandleCreated);
control.HandleDestroyed -=new EventHandler(HandleDestroyed);
//Remove the control from our reference list.
m_controls.Remove(control);
if (m_window.IsHandleCreated)
{
//Update the tooltip window
NativeMethods.TOOLINFO ti = GetToolInfo(control, null);
NativeMethods.SendMessage(m_window.Handle, TTM_DELTOOL, 0, ref ti);
}
}
/// <summary>
/// Creates the native window if it does not already exist.
/// </summary>
/// <param name="control">Control that is causing this window to be created.</param>
private void CreateWindowHandle(Control control)
{
if (!m_window.IsHandleCreated)
{
if(control.FindForm()!=null)
{
m_window.CreateHandle(control.FindForm());
}
else
{
m_window.CreateHandle(control.TopLevelControl);
}
//Create the window handle.
//m_window.CreateHandle(control.TopLevelControl);
//Set if tooltips should initially be active.
NativeMethods.SendMessage(m_window.Handle, TTM_ACTIVATE, m_active ? 1 : 0, 0);
//Update the track active setting.
if (m_showAlways)
SetTrackActive();
}
}
#endregion
public IntPtr Handle
{
get{return this.m_window.Handle;}
}
/* public Rectangle ClientRectangle
{
get
{
// Rectangle rect=new Rectangle();
// API.GetWindowRect(this.Handle,ref rect);
return rect;
}
set
{
if(this.rect==value)
{
}
else if(this.Handle==IntPtr.Zero)
{
API.SetWindowPos(this.Handle, new IntPtr(-1), value.X, value.Y,value.Width, value.Height, 19);
API.GetWindowRect(this.Handle,ref rect);
}
else
{
this.rect=value;
}
}
}*/
public void ShowX()
{
NativeMethods.SetWindowPos(this.Handle, NativeMethods.HWND_TOPMOST, 0, 0,0, 0, 19 |gowk.common.API.SWP_SHOWWINDOW);
}
public bool Visible
{
set
{
bool b=API.ShowWindow(this.Handle,value?API.SW_SHOW:API.SW_HIDE);
System.Diagnostics.Trace.WriteLine(b.ToString());
}
}
public void Show()
{
this.Visible=true;
}
public void Hide()
{
this.Visible=false;
}
/// <summary>
/// lResult = SendMessage(
/// (HWND) hWndControl, // handle to destination control
/// (UINT) TTM_SETMAXTIPWIDTH, // message ID
/// (WPARAM) wParam, // = 0; not used, must be zero
/// (LPARAM) lParam // = (LPARAM) (INT) iWidth; );
/// </summary>
public int MaxTipWidth
{
get{return (int)API.SendMessage(this.Handle,(int)API.TTM_GETMAXTIPWIDTH,0,0);}
set
{
if(this.maxTipWidth!=value)
API.SendMessage(this.Handle,API.TTM_SETMAXTIPWIDTH,0,value);
}
}
private void UpdateIcon()
{
IntPtr ptr1 = IntPtr.Zero;
if (this.icon != null)
{
ptr1 = this.icon.Handle;
}
int i=API.SendMessage(this.Handle, 0xf7, (IntPtr) 1, ptr1);
}
public Icon Icon
{
get
{
return this.icon;
}
set
{
this.icon = value;
if (this.Handle!=IntPtr.Zero)
{
this.UpdateIcon();
}
}
}
public Color BackColor
{
get{return this.bc;}
set{this.bc=value;}
}
private void SetArgs()
{
// bool b=API.SetWindowPos(this.Handle, new IntPtr(-1), rect.X, rect.Y,rect.Width, rect.Height, 19);
// b=API.GetWindowRect(this.Handle,ref rect);
API.SendMessage(this.Handle,API.TTM_SETMAXTIPWIDTH,0,this.maxTipWidth);
}
Icon icon;
Color bc;
int maxTipWidth=150;
//Rectangle rect;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -