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:
- A custom transparent bitmap background
- A skinnable 3-State close button
- A clickable title text
- A clickable content text
- A selection rectangle
- Custom fonts and colors for the different states of the text (normal/hover)
- Animation speed parameters
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
- First of all, copy TaskbarNotifier.cs in your project directory.
- Add on the top of your source code the directive:
using CustomUIControls;
- Add a member variable in your class:
TaskbarNotifier taskbarNotifier;
- In your constructor add the following lines:
taskbarNotifier=new TaskbarNotifier();
taskbarNotifier.SetBackgroundBitmap("skin.bmp",
Color.FromArgb(255,0,255));
taskbarNotifier.SetCloseBitmap("close.bmp",
Color.FromArgb(255,0,255),new Point(127,8));
taskbarNotifier.TitleRectangle=new Rectangle(40,9,70,25);
taskbarNotifier.ContentRectangle=new Rectangle(8,41,133,68);
taskbarNotifier.TitleClick+=new EventHandler(TitleClick);
taskbarNotifier.ContentClick+=new EventHandler(ContentClick);
taskbarNotifier.CloseClick+=new EventHandler(CloseClick);
Details:
taskbarNotifier.SetBackgroundBitmap("skin.bmp",
Color.FromArgb(255,0,255));
taskbarNotifier.SetCloseBitmap("close.bmp",
Color.FromArgb(255,0,255),new Point(127,8));
The first line sets the background bitmap skin and transparency color (must be present), and the second line sets the 3-State close button with its transparency color and its location on the window (this line is optional if you don't want a close button).
taskbarNotifier.TitleRectangle=new Rectangle(40,9,70,25);
taskbarNotifier.ContentRectangle=new Rectangle(8,41,133,68);
These two lines allow us to define the rectangles in which will be displayed, the title and content texts.
taskbarNotifier.TitleClick+=new EventHandler(OnTitleClick);
taskbarNotifier.ContentClick+=new EventHandler(OnContentClick);
taskbarNotifier.CloseClick+=new EventHandler(OnCloseClick);
These 3 lines allow us to intercept events on the popup such as title/content or close button have been clicked
- Then we are done, we just need to call:
taskbarNotifier.Show("TitleText","ContentText",500,3000,500);
This will show the popup animation with the showing/visible/hiding animations time set as 500ms/3000ms/500ms.
You can play with a few properties:
- Title, content fonts and colors
- Ability to click or not on the title/content/close button
- You can disable the focus rect
- ... (see below for more details)
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
strTitle
: The string which will be shown as the title of the popup
strContent
: The string which will be shown as the content of the popup
nTimeToShow
: Duration of the showing animation (in milliseconds)
nTimeToStay
: Duration of the visible state before collapsing (in milliseconds)
nTimeToHide
: Duration of the hiding animation (in milliseconds)
void Hide()
Forces the popup to hide.
void SetBackgroundBitmap(string strFilename, Color transparencyColor)
Sets the background bitmap and its transparency color.
Parameters
strFilename
: Path of the background bitmap on the disk
transparencyColor
: Color of the bitmap which won't be visible
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
strFilename
: Path of the 3-state close button bitmap on the disk (width must be a multiple of 3)
transparencyColor
: Color of the bitmap which won't be visible
position
: Location of the close button on the popup
void SetCloseBitmap(Image image, Color transparencyColor, Point position)
Sets the 3-State close button bitmap, its transparency color and its coordinates.
Parameters
image
: Image
/Bitmap
object which represents the 3-state close button bitmap (width must be a multiple of 3)
transparencyColor
: Color of the bitmap which won't be visible
position
: Location of the close button on the popup
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)
Rectangle ContentRectangle (get/set)
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
- 01 April 2003: Small bug fix in the
OnMouseUp
handler.
- 11 January 2003: Patrick Vanden Driessche updated both the C# and VB.NET versions:
- The popup now doesn't close automatically when the mouse is still over it
- The popup is shown again when it was disappearing and the mouse comes over it
- A few other bugs have been corrected.
- 10 January 2003: A port of
TaskbarNotifier
has been done by Patrick Vanden Driessche in VB.NET
- 05 December 2002: The popup is now shown using the Win32 function
ShowWindow(SW_SHOWNOACTIVATE)
, to prevent the popup from stealing the focus.
Conclusion
I hope this code will be useful to you. If you have suggestions to enhance this class functionalities, please post a comment.