Click here to Skip to main content
Email Password   helpLost your password?

Introduction

Since I am learning C#, I thought it would be helpful for me to port my C++ CTaskbarNotifier class (http://www.codeproject.com/dialog/TaskbarNotifier.asp[ ^])

As a result, I coded a MSN Messenger-like skinnable popup, with a close button which looks almost like Microsoft's one (with the associated skin).

The TaskbarNotifier class inherits from System.Windows.Forms.Form and adds a few methods to it.

Features

The MSN messenger like popup supports:

Compatibility

This class is stand alone and doesn't need any particular libraries except .NET default ones. It runs in managed code and hence should be portable.

How to use the class

You can play with a few properties:

Class documentation

Methods

void Show(string strTitle, string strContent, int nTimeToShow, 
                                            int nTimeToStay, int nTimeToHide)

Displays the popup for a certain amount of time.

Parameters

void Hide()

Forces the popup to hide.

void SetBackgroundBitmap(string strFilename, Color transparencyColor)

Sets the background bitmap and its transparency color.

Parameters

void SetBackgroundBitmap(Image image, Color transparencyColor)

Sets the background bitmap and its transparency color.

Parameters

  • image: Background bitmap
  • transparencyColor: Color of the bitmap which won't be visible
    void SetCloseBitmap(string strFilename, 
                Color transparencyColor, Point position)

    Sets the 3-State close button bitmap, its transparency color and its coordinates.

    Parameters

    void SetCloseBitmap(Image image, Color transparencyColor, Point position)

    Sets the 3-State close button bitmap, its transparency color and its coordinates.

    Parameters

    Properties

    string TitleText (get/set)
    string ContentText (get/set)
    TaskbarStates TaskbarState (get)
    Color NormalTitleColor (get/set)
    Color HoverTitleColor (get/set)
    Color NormalContentColor (get/set)
    Color HoverContentColor (get/set)
    Font NormalTitleFont (get/set)
    Font HoverTitleFont (get/set)
    Font NormalContentFont (get/set)
    Font HoverContentFont (get/set)
    Rectangle TitleRectangle (get/set) //must be defined before calling show())
    
    Rectangle ContentRectangle (get/set) //must be defined before calling show())
    
    bool TitleClickable (get/set) (default = false);
    bool ContentClickable (get/set) (default = true);
    bool CloseClickable (get/set) (default = true);
    bool EnableSelectionRectangle (get/set) (default = true);

    Events

    event EventHandler CloseClick
    event EventHandler TitleClick
    event EventHandler ContentClick

    Technical issues

    The popup is skinned using a region generated dynamically from a bitmap and a transparency color:

    protected Region BitmapToRegion(Bitmap bitmap, Color transparencyColor)
    {
        if (bitmap == null)
            throw new ArgumentNullException("Bitmap", "Bitmap cannot be null!");
    
        int height = bitmap.Height;
        int width = bitmap.Width;
    
        GraphicsPath path = new GraphicsPath();
    
        for (int j=0; j<height; j++ )
            for (int i=0; i<width; i++)
            {
                if (bitmap.GetPixel(i, j) == transparencyColor)
                    continue;
    
                int x0 = i;
    
                while ((i < width) && 
                        (bitmap.GetPixel(i, j) != transparencyColor))
                    i++;
    
                path.AddRectangle(new Rectangle(x0, j, i-x0, 1));
            }
    
        Region region = new Region(path);
        path.Dispose();
        return region;
    }

    The refresh() of the popup is done using the double buffering technique to avoid flickering:

    protected override void OnPaintBackground(PaintEventArgs pea)
    {
        Graphics grfx = pea.Graphics;
        grfx.PageUnit = GraphicsUnit.Pixel;
    
        Graphics offScreenGraphics;
        Bitmap offscreenBitmap;
    
        offscreenBitmap = new Bitmap(BackgroundBitmap.Width, 
                                    BackgroundBitmap.Height);
        offScreenGraphics = Graphics.FromImage(offscreenBitmap);
    
        if (BackgroundBitmap != null)
        {
            offScreenGraphics.DrawImage(BackgroundBitmap, 
                0, 0, BackgroundBitmap.Width, BackgroundBitmap.Height);
        }
    
        DrawCloseButton(offScreenGraphics);
        DrawText(offScreenGraphics);
    
        grfx.DrawImage(offscreenBitmap, 0, 0);
    }

    Bugs/Limitations

    Since I wanted to keep only managed code, I used the Screen.GetWorkingArea(WorkAreaRectangle) function instead of using unmanaged code to get the taskbar position. As a result, I made the popup always appear at the bottom of WorkAreaRectangle whichever position the taskbar has.

    I didn't find any C# managed equivalent to the Win32 function ShowWindow(SW_SHOWNOACTIVATE) to make the popup, not steal the focus of the active window.

    Updates

    Conclusion

    I hope this code will be useful to you. If you have suggestions to enhance this class functionalities, please post a comment.

  • You must Sign In to use this message board.
     
     
    Per page   
     FirstPrevNext
    Generalpropage message through network
    TrumanChua
    7:01 5 Feb '10  
    hi john,

    just read your article on codeproject

    TaskbarNotifier, a skinnable MSN Messenger-like popup in C# and now in VB.NET too

    was wondering if you've seen any articles or have any thoughts on
    how to wire this software up so that you can pop the message on another
    computer other than your own, basically propagate the message through
    an existing network

    great article.

    thank you.

    truman

    tchua@wolve.com
    QuestionText Alignment of strContent
    flaurita
    6:04 19 Nov '09  
    How can I change the "center text alignment" of the strContent?

    I tryed to play with the StringFormat object but without luck.
    I'd like to align text on the left of the ContentRectangle.

    Tnx in advance
    GeneralEvents won't fire
    nowh3r32h1d3
    0:03 30 Oct '09  
    Weird.
    Everything works fine except my events won't fire.
    Even the "textRectangle" won't show up.

    What could be the problem?

    (Nice Toast!)
    GeneralNotifier do not appear if client code is on a class library o console project
    Francesco Randazzo
    6:08 14 Oct '09  
    I hava an application with multiple dll. in the deeper application layer there is a dll containing the NotifierTaskbar class(called deep.dll). a client dll (called client.dll) intercepts an event, prepare the taskbar class to show and call the show method. The problem is that the popup do not appear.
    Any idea? There is something i ignore?
    p.s. I tried to call the dll containing the taskbarclass from a console project but the problem persists.
    GeneralRe: Notifier do not appear if client code is on a class library o console project
    allentranks
    22:43 9 Dec '09  
    class library or console project can not hold the thread for TaskbarNotifier..
    a messbox can:

    /* codes: */

    notifier.Show("title","content",500,3000,500);
    System.Windows.Forms.MessageBox.Show("anything");

    /* end of codes */

    you will see the notifier works.

    However, we cannot use MessageBox to hold the thread for notifier anyway...

    It's headachy..
    Generalproperty no found "Skin.bmp" VC# Express
    Daniel Garzon
    13:52 7 Oct '09  
    Hi,i have a problem which is: "Resource 'skin3.bmp' cannot be found in class 'Form1.Front'", i already put the images on the local folder, even in the bin folder plus i changed the property build action to a "embedded resource". any ideas??? thkx lots
    QuestionProblem with Win7
    bzyy11
    0:26 15 Sep '09  
    The background is black , not transparent . but it is ok in win2008 r2. I think it is win7 aero cause it.
    AnswerRe: Problem with Win7
    bzyy11
    2:20 15 Sep '09  
    I solved this problem . In the ontimer function , replace with follow:
    case TaskbarStates.appearing:
    if (Height < BackgroundBitmap.Height)
    {
    Top -= nIncrementShow;
    Height += nIncrementShow;
    //SetBounds(Left, Top - nIncrementShow, Width, Height + nIncrementShow, BoundsSpecified.All);
    }


                            if (Top < WorkAreaRectangle.Bottom)
    {
    Top += nIncrementHide;
    Height -= nIncrementHide;
    //SetBounds(Left, Top + nIncrementHide, Width, Height - nIncrementHide);
    }


    Perhaps SetBounds dos not clear the old image in win7.
    GeneralRe: Problem with Win7
    see_seA
    6:08 5 Oct '09  
    Well done!! Was looking at a way to solve this problem! Works nicely.
    GeneralProblems with Vista?
    LegoMindstorms
    7:39 25 Aug '09  
    Hello,

    First, I would like to say thank you for this great control.

    Unfortunately, I have a problem with you control on Windows Vista. Some users of my program report that they don't get a popup. They all have Windows Vista, but others with Vista have a working popup.

    I cannot reproduce the problem, but have you any idea of what it could be and how to fix it?

    Regards,
    Thomas
    GeneralIs there a way to make the edges smooth
    Muhammad Ahmed
    7:16 10 Aug '09  
    Hello,
    Thanks for the great stuff first of all,
    I observed that edges of the bitmap based popups are little jagged, Is there a way to make them smooth ?

    Thanks,
    Ahmed Red faced

    Ahmed

    GeneralLicense
    tknman0700
    12:13 26 Jul '09  
    What is the license with this class? Great work!
    GeneralThanx!
    janniebun
    7:31 20 Jul '09  
    What an awesome control, and it works like a charm! thanx again! Laugh
    GeneralC++ version and messenger.zip
    tipiak07
    9:55 28 Jun '09  
    Hello,

    I find this class is very great. I viewed the c++ verison too, but i need to use it in a thread. I saw in the comments on the C++ version that the version xmessenger.zip but all the links are dead. Does anyone has it ?
    If yes please send me the archive to tipiak07@yahoo.com. I post this comment here because i saw last message for the C++ version was 1 year ago... so i hope people in this thread already used the C++ version Smile
    I will try to provide a link to share it for people who will need the archive in future reads of the article.
    Best regards.
    GeneralHow to make the pop up a scheduled one
    Yeshwanthhv
    0:28 16 Jun '09  
    Hi John,

    Thanks for the article. I was just working on popping up the toaster winodow in a scheduled manner. I was able to use Timercallback function and initiated the toast pop up function. However, it didnt worked for me. Can you give me some ideas regarding the same.

    Hai This is Yesh

    GeneralVery nice example
    Member 2234401
    11:53 29 May '09  
    This is a very nice example. However, I think you will want to do some significant cleanup here. You are using many disposable objects without properly managing them. As a rule of thumb, if you create a disposable object, you are responsible for cleaning it up.

    Also might want to consider running fxcop on this as well. Fxcop will help you in learning the langauage and the best uses of it.
    GeneralReally terrific, Thanks!
    Jamie Simon
    8:26 24 Apr '09  
    This is great. A certain co-worker's been bugging me for this for months, and thanks to your code I was able to bang this in quickly! Kudos! Smile

    -- Jamie
    Generalmissing resource file
    ottilia
    6:47 4 Apr '09  
    please help i am getting this message Additional information: Resource 'skin.bmp' could not be found in class 'filecopy.frmBackup'. the resources(bmp files) are in the project
    GeneralASP.NET
    Siphiwe
    2:37 25 Mar '09  
    Would it be possible to apply the same principle in asp.net application, if so please advise of the solution

    siphiwe.khuzwayo@standardbank.co.za

    GeneralVB 2005 skin.bmp
    roscael
    18:16 25 Feb '09  
    i have a problem "An error occurred creating the form. See Exception.InnerException for details. The error is: Resource 'skin.bmp' cannot be found in class 'task.Form1'" I tray save images in bin/debug (when in debug modE) and bin/release (when in release mode) but nothing
    GeneralRe: VB 2005 skin.bmp
    klemmax
    5:36 26 Feb '09  
    Try this: in "solution view" right click on the bmp -> properties -> in build action dropdown select "Embedded resource" then rebuild

    KlemMax

    GeneralRe: VB 2005 skin.bmp
    roscael
    7:26 26 Feb '09  
    thanks gracias!!!!!!!!, that was Big Grin
    GeneralFocus stealing woes
    r_hyde
    1:54 24 Feb '09  
    Generally, the notifier works as advertised and does not steal focus. However, if I set CloseClickable to true and add a CloseClicked event which calls Hide(), the next time I display a new notifier it does steal focus from whatever window is active (system-wide). If I let the focus-stealing popup disappear on its own then the next one to come up won't steal focus - it only happens on the next one, following one that is closed through the CloseClicked handler. This is driving me crazy, I can't figure out why it's doing this!
    GeneralRe: Focus stealing woes [modified]
    r_hyde
    17:20 25 Feb '09  
    Ah, I've got it solved! I removed TopMost from the constructor, P/Invoked SetWindowPos(), and modified the switch (taskbarState) block in Show() as follows:

    int left, top, width, height;
    switch (taskbarState)
    {
    case TaskbarStates.hidden:
    taskbarState = TaskbarStates.appearing;
    this.Opacity = 0.0;
    left = WorkAreaRectangle.Right - BackgroundBitmap.Width - nPadding - nBaseWindowRight;
    top = WorkAreaRectangle.Bottom - BackgroundBitmap.Height - nPadding - nBaseWindowBottom;
    width = BackgroundBitmap.Width;
    height = BackgroundBitmap.Height;
    SetWindowPos(this.Handle, -1, left, top, width, height, 0x0010);
    timer.Interval = nShowEvents;
    timer.Start();

    // Show the popup without stealing focus
    ShowWindow(this.Handle, 4);
    break;

    case TaskbarStates.appearing:
    Refresh();
    break;

    case TaskbarStates.visible:
    timer.Stop();
    timer.Interval = nVisibleEvents;
    timer.Start();
    Refresh();
    break;

    case TaskbarStates.disappearing:
    timer.Stop();
    taskbarState = TaskbarStates.visible;
    left = WorkAreaRectangle.Right - BackgroundBitmap.Width - nPadding - nBaseWindowRight;
    top = WorkAreaRectangle.Bottom - nPadding - nBaseWindowBottom;
    width = BackgroundBitmap.Width;
    height = 0;
    SetWindowPos(this.Handle, -1, left, top, width, height, 0x0010);
    timer.Interval = nVisibleEvents;
    timer.Start();
    Refresh();
    break;
    }

    I'm still not sure why the notifier was taking focus in such a limited way, but at least this made it stop. Now if only we had a 100% managed way to do this in WinForms, that would be excellent!

    modified on Wednesday, February 25, 2009 10:34 PM

    GeneralRe: Focus stealing woes
    Josh Powers
    9:04 27 Feb '09  
    I am having the same problem you were but when i try to impliment what you stated above I just get nothing. Any chance you could post a more complete code listing of your changes? Also where did the nPadding and nBaseWindowRight variables come from, the version I have doesnt have those variables.


    Last Updated 31 Mar 2003 | Advertise | Privacy | Terms of Use | Copyright © CodeProject, 1999-2010