Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

A different take on the .NET ToolTip/BalloonTip

0.00/5 (No votes)
15 Feb 2008 1  
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:

InfoTip.JPG

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.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here