A different take on the .NET ToolTip/BalloonTip






1.22/5 (9 votes)
How to implement a .NET ToolTip/BalloonTip using the standard .NET Form.
Introduction
Standard NotificationIcon ToolTip is only 64 chars wide, and BalloonTip
is too intrusive and inflexible to use. I have written my own version of a tooltip that gives me more text and is easy to use and unobtrusive.
Background
This code uses standard WinForms controls and techniques. I looked around and found esoteric implementations using PInvoke and the like. So I created this simpler (at least for me) way of giving me what I want.
Here is a bitmap of what it looks like while hovering over an icon:
Using the Code
The code is just a method (InfoTip
) and some event handlers. You will note that it is simple to use and hopefully it will give you some ideas to take it further. It can certainly be expanded to have other controls and functionality. I should also mention that this is my first article, so please forgive me if I missed anything in the way of article entry etiquette.
//the InfoTip method takes in a whole seconds int value
private void InfoTip(int theTimeOut)
{
//we want the current position so we can calculate where the
//info tip will be displayed relative to the NotificationIcon
Point aXY = Cursor.Position;
//create a new form for housing the text label
_InfoTipForm = new Form();
//register load and formclosing event so that
//we can control interaction with context menu
_InfoTipForm.FormClosing +=
new FormClosingEventHandler(_InfoTipForm_FormClosing);
_InfoTipForm.Load += new EventHandler(_InfoTipForm_Load);
//set up the form's attributes to mimic standard ToolTip look and feel
_InfoTipForm.FormBorderStyle = FormBorderStyle.None;
_InfoTipForm.BackColor = Color.Cornsilk;
_InfoTipForm.ControlBox = false;
_InfoTipForm.MaximizeBox = false;
_InfoTipForm.MinimizeBox = false;
_InfoTipForm.Width = 0; //these two prop settings prevent flashing
_InfoTipForm.Height = 0; //when the form draws itself
_InfoTipForm.TopMost = true;
_InfoTipForm.ShowInTaskbar = false;
_InfoTipForm.Visible = true;
//this is the label that will display the Tip's text
//this is what allows us to go beyond
//the 64 char limit of the standard tooltip
//but you can also make this be any container type
//of control to hold an image, rich text, etc...
Label aInfoTip = new Label();
//format to mimic ToolTip look and feel
aInfoTip.BackColor = Color.Cornsilk;
aInfoTip.ForeColor = Color.Black;
aInfoTip.Font = new Font("Arial", 9, FontStyle.Regular);
aInfoTip.AutoSize = true;
aInfoTip.Location = new Point(0, 0);
aInfoTip.TextAlign = ContentAlignment.MiddleLeft;
aInfoTip.Visible = true;
//for my application I assign the text
//on a global but you can pass it in.
aInfoTip.Text = _NotifyText;
aInfoTip.Refresh();//forces control to redraw
//now we add the label to the form and
//set the form size to the label size
_InfoTipForm.Controls.Add(aInfoTip);
_InfoTipForm.Width = aInfoTip.Width;
_InfoTipForm.Height = aInfoTip.Height;
//keep the form within the screen viewing area and above the icon
if(Screen.PrimaryScreen.Bounds.Width - aXY.X < _InfoTipForm.Width)
_InfoTipForm.DesktopLocation =
new Point(aXY.X - _InfoTipForm.Width, aXY.Y - 34);
else
_InfoTipForm.DesktopLocation = new Point(aXY.X, aXY.Y - 34);
//force form to refresh
_InfoTipForm.Refresh();
_InfoTipForm.Show();
//global manualresetevent that waits the timeout period,
//used to close the tip before timeout ends
_TipWait.WaitOne(theTimeOut * 1000, false);
//close the form when done waiting
_InfoTipForm.Close();
//reset the signaller so it's ready the next time our tip shows
_TipWait.Reset();
}
///////////////////////////////////////////////////////////////////////////
//the info tip form global
Form _InfoTipForm;
//control the showing of the tip
bool _isCanShowInfoTip=true;
//wait signaller
ManualResetEvent _TipWait=new ManualResetEvent();
//when the infottip form loads set the show controller boolean to false
private void _InfoTipForm_Load(object sender, EventArgs e)
{
_isCanShowInfoTip = false;
}//_InfoTipForm_Load
//when the tip form closes then we can show the tip again
private void _InfoTipForm_FormClosing(object sender, FormClosingEventArgs e)
{
_isCanShowInfoTip = true;
}//_InfoTipForm_FormClosing
//contextmenu and infotip are mutually exclusive,
//so when context menu shows, infotip closes
private void contextMenuStrip1_Opening(object sender, CancelEventArgs e)
{
_isCanShowInfoTip = false;
//tell the signaller to stop blocking and continue
//so the tip can close before the timeout period
_TipWait.Set();
}//contextMenuStrip1_Opening
//show the infotip on mousemove (simulates hover)
//this is the InfoTip's entry point
private void notifyIcon1_MouseMove(object sender, MouseEventArgs e)
{
//if we can show the tip and there's
//no contextmenu showing then create the infotip
if(_isCanShowInfoTip && !contextMenuStrip1.Visible)
InfoTip(3);//timeout of three seconds
}//notifyIcon1_MouseMove
Points of Interest
This is just a simple implementation for my own needs, but you could certainly take this and expand on it, make it more robust for your needs.