Click here to Skip to main content
Click here to Skip to main content

.NET TrayBalloon with hyper-links and fading

, 17 Nov 2010
Rate this:
Please Sign up or sign in to vote.
.NET C# TrayBalloon component with hyper-links and fading.

Introduction

.NET Framework has a rich set of user notifications, but there is no tray balloon that you can use in message-oriented applications. This article presents you a ready to use component and explains how to customize and use it.

Background

Sometimes when writing user interactive applications, especially those dealing with internet resources, we need to show some information balloons to the user. A MessageBox or a memo in the bottom are not very convenient. The most convenient way of notifications is a tray balloon appearing in the right bottom side of the screen (like in MSN, Skype, and ICQ).

Since I developed this component the first time, it has changed many times to meet all the requirements of its customers. Here is a list of the most significant:

  • It has to be configurable (background, sound)
  • It hast to work with extended desktop
  • It doesn't have to attract input focus when appearing
  • It doesn't have to be displayed in Alt-Tab
  • It has to support hyper links and open a browser when a link is clicked
  • It has to appear stacked on the screen when there are other balloons displayed
  • It has to support the multi-threading async model, dealing with service from any thread (not GUI only)
  • It hast to stay visible when the mouse is in the balloon's region

Key points

I will explain some the most interesting things here.

How to make the tray balloon appear without grabbing the input focus

It's really inconvenient when you're typing some text in a program and a balloon appears grabbing the input focus. We will get this bad behavior if we use the regular Form.Show method. To show a balloon without changes in the input focus, we have to deal with the PInvoke ShowWindow method.

[DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
public static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, 
              int x, int y, int cx, int cy, int flags);

SetWindowPos(Frm.Handle, (IntPtr)(-1), 0, 0, 0, 0, 0x50);

In the snippet above, I call the native Windows API function to show our window on the top of the screen, above any window. Additionally, according to the last parameter, it will be shown without activation. That's what we need. So, the user typing some text will not be redirected to our window.

How to parse input text and create hyperlinks

To setup a LinkLabel with multiple links is very easy, and described in MSDN in detail. But we need to do that using HTML text in the input (we should be able to copy a link from somewhere and just paste it in the .config file or whatever, and this code has to be parsed and all <a> tags should be converted into links). The most optimal way to do this task is to use Regular Expressions. Usually, Regex can solve text-based problems in the most elegant way than any code-based alternatives. Thus, we just use Regex to parse text and strip all <a> tags, and then we use them as links in the LinkLabel control.

static readonly System.Text.RegularExpressions.Regex A = 
    new System.Text.RegularExpressions.Regex(
            "\\<a\\w+href=\"(?<href>[^\"]*)\"\\W*\\>(?<text>[^\\<]*)\\", 
            System.Text.RegularExpressions.RegexOptions.IgnoreCase | 
            System.Text.RegularExpressions.RegexOptions.Multiline);

        private void SetupText()
        {
            TitleLabel.Text = Title;
            string msg = Message ?? string.Empty;

            var matches = A.Matches(msg);
            if (matches == null || matches.Count == 0)
            {
                MessageLabel.Text = msg;
                MessageLabel.LinkArea = new LinkArea(msg.Length, 0);
            }
            else
            {
                StringBuilder sb = new StringBuilder();
                int last_index = 0;
                foreach (System.Text.RegularExpressions.Match match in matches)
                {
                    var href = match.Groups["href"].Value;
                    var text = match.Groups["text"].Value;

                    sb.Append(msg, last_index, match.Index - last_index);
                    MessageLabel.Links.Add(new LinkLabel.Link(sb.Length,
                        text.Length) { LinkData = href });
                    sb.Append(text);
                    last_index = match.Index + match.Length;
                }
                if (last_index < msg.Length)
                    sb.Append(msg.Substring(last_index));

                MessageLabel.Text = sb.ToString();
            }
        }

How it works

After you've created and adjusted the TrayBalloon object, you should display it calling the Run method. This method will return immediately because it is designed to be used from multiple threads which want to notify the user, not interact with them. Once you've called this method, you can continue execution and not care about how it works.

Now, let's look at the key steps that TrayBalloon passes through. First of all, it queues form show into the thread pool. After that, the thread pool thread calls the main entry point of the TrayBalloon form. In this method, TrayBalloon checks for other visible instances to choose free space in the screen (remember, it has to be stacked on the screen). If there are no other instances, it is shown at the bottom; if there are other TrayBalloons already displayed, it will choose a free space between or above them. If there is no free space in the screen, it will just overlay the top most TrayBalloon widow. Also, when appearing, it uses animation and fading (however, this can be skipped, depending on settings that you may use before show).

TrayBalloon keeps itself on the screen for a few seconds and the animation starts disappearing. However, if the user keeps the mouse above the form, it will not be hidden. After the TrayBalloon is hidden, it unregisters itself in the visible queue to free space in the screen and lets other TrayBalloons to reuse its space.

This is a very brief description of the internal infrastructure; please read the source code for more detailed understanding of how it works.

Result

Here is the test application that can be used to learn more about the TrayBalloon.dll component.

tester.JPG

Here is the resulting customized balloon window:

trayballoon.JPG

Points of interest

During testing of many apps with tray balloons (not just this one), I've accidentally found a very interesting bug. If you make the Windows Taskbar editable and re-attract it to another corner of the screen when the tray balloon is appearing, Explorer may hang up Smile | :) Be careful.

Before using this component, we need to setup some properties such as Title, Message, etc. Look at the form sample to see the required minimum set of fields to be set. If you need to specify some sound when it appears, or a custom background, please do it. There are many other different tweaks that can be applied to obtain performance, beauty, and so on.

History

This is the initial version of the article. Any new improvements will be posted here in future.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

PavPS
Software Developer (Senior) iSoft
Russian Federation Russian Federation
No Biography provided

Comments and Discussions

 
GeneralMy vote of 4 PinmemberRoey C24-Nov-10 21:26 
GeneralMy vote of 3 Pinmemberapoloion24-Nov-10 0:58 
GeneralChanges PinmemberPavPS17-Nov-10 6:38 
GeneralNice try, but... PinmemberIgor Kushnarev17-Nov-10 1:36 
GeneralRe: Nice try, but... PinmemberPavPS17-Nov-10 6:42 
GeneralRe: Nice try, but... PinmemberIgor Kushnarev17-Nov-10 18:05 
GeneralI'm curious, why do you "catch".... PinmemberPaw Jershauge16-Nov-10 21:35 
GeneralCorrected Download links PinmemberPaw Jershauge16-Nov-10 21:20 
GeneralTrayBalloon with hyper-links and fading Link is removed PinmemberAsutosha16-Nov-10 19:19 
Generalcannot download the packages Pinmembertsz16-Nov-10 15:29 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web04 | 2.8.140814.1 | Last Updated 17 Nov 2010
Article Copyright 2010 by PavPS
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid