Implement taskbar notification window with Visual C #

Source: Internet
Author: User
Tags definition contains function prototype functions header interface variable visual studio
Visual presumably most netizens have used QQ, MSN and other chat programs, their interface is quite gorgeous, especially when users online and message prompts will have a floating form from the bottom right side of the screen, both beautiful and humane, As a programmer in the enjoyment of the same time we can not help but ask: this is how to achieve it? This article leverages visual Studio. Net C # 2005 and. NET Framework drawing technology to implement this task bar notification window.

   Brief Introduction

QQ and MSN Taskbar Notification window is very user-friendly, it can not lose the owner of the form focus on the premise of the display of a skin skin notice form, when it shows a period of time will automatically disappear, so users do not have to interfere with it. Such a notification form and the general has a title bar, system icons and buttons of the form is not much different, the form surface is actually a picture of a bitmap, and the form of floating will be more complex, we will use. NET Framework's dual buffer mapping technology (see author compilation article "Windows form.") NET Framework drawing technology to ensure that the content displayed when the form is moved is smooth and not blinking, and that calls to the WIN32API function are made using P/invoke platform invoke to complete the form display and the non-title bar form Drag that does not have the focus. The skins of both bitmaps run with the following interface:

   Background Knowledge

The notification window is a general form attached to a layer of skin, where the so-called skin is a bitmap picture, the bitmap picture through the form of the OnPaintBackground event is drawn to the surface of the form, before attaching a bitmap need to adjust the visual properties of the form, because the drawing operation is for the form customer region , the customer area is the area below the title bar of the form and all areas within the form's border, so you need to adjust the form's border and appearance properties FormBorderStyle to: None so that the image you draw fills the entire form.

First of all, we will use the region object, the region object can accurately depict the contour range of any shape, create a region object through a bitmap image and then pass it to the region property of the form to show the form according to the outline defined by region. Bitmap files used as skins can be created and edited by any image editing software, such as: Photeshop, just to be aware that the background color of the picture needs to be colored so that it clears when the program is drawn, and we use a pink background here. In order to allow the region object to create a form based on the content border of interest in the image, we also need to use the GraphicsPath class to mark the outline of the image in a certain path, and later create the region object.

Then, by drawing events on the form, the contents of the bitmap are displayed on the surface of the form, and instead of using the OnPaintBackground event directly, we overload the method, and the benefit is that some low-level drawing operations continue to be handed over. NET Framework runtime to handle, we only consider the actual need to draw operations. In the OnPaintBackground method we have enabled the dual buffer mapping technique, which means that the image that will be displayed is displayed or processed first in the memory on a canvas, and then the image displayed on the canvas is placed on the surface of the form when the operation is complete, Such a mechanism can be very effective to reduce the appearance of flicker, so that the image display more smooth. The notification form is raised from the bottom right of the screen for a period of time and then slowly falls back, where you need to return to the size range of the screen area. NET Framework method Screen.getworkingarea (Workarearectangle), through a certain algorithm to calculate the notification form before the display of the initial position. Finally, the text that we want to display is drawn to the surface of the form in a certain format and in the range specified by the rectangle object. The shutdown of the notification form is by setting an area that detects whether the click coordinates are within the range when the user clicks with the mouse, and if the code for the hidden notification form can be executed within the range.

We notice that when the QQ and MSN Notification window is displayed, the focus of its main form is not lost, which means that the program does not transfer its focus to the displayed notification form. After testing, we call whatever. NET Framework provides form display routines such as: cannot guarantee that the main form's focus is not lost, we can use the Win32API showwindows function to complete the complex form display in VC environment, but the. NET Framework does not provide a similar method at all, so can we pass the. NET box Frame to call the API function to display the form? Fortunately. NET Framework provides P/invoke platform invoke, which enables managed code to invoke unmanaged functions implemented in a dynamic-link library, and to marshal its arguments, which we can easily display but do not get focus on. Windows used by the program The definitions of APIs and constants are stored in the WinUser.h header file, and the corresponding dynamic-link library file is user32.dll, and the imported function is defined using the DllImportAttribute class provided by the. NET Framework, and then it is convenient to call the function in the program.

Because we have hidden the title bar of the notification form, we also need to do our own processing for the form drag operation. This article describes how to more efficient drag form operations, some users in the non-title bar to drag the form programming when the combination of mouse events to use, the nature of doing nothing wrong, but frequent incident response and processing, but the performance of the program has been reduced. We will continue to use Win32API's underlying approach to solve the problem by sending a message to the form that is clicked on the title bar to simulate the actual drag operation.

We will use 2 timers to complete the display of the form, stay and hide, by setting the speed variable can change the window display and hidden speed.

   Program Implementation

Start Visual Studio. Net 2005, create a C # Windows forms application, name the solution Taskbarform, include the project name Taskbarform, and first create the program's main form FORM1, Add two button controls above, one to display the notification form, and the other to terminate the program. Then, in Solution Manager, right-click the project, click Add-Windows forms, and we'll name the newly created form Taskbarform.

Below the class Taskbarform definition, we create a variable that is used to display the string and its color, and then define the variables for a few rectangle objects to place the caption, the hint, and the area where the form can be dragged and the closing button. Then, we need to save the height of the form as it floats to calculate the new height after the move, and the Intervalvalue variable is used to determine how quickly the form is displayed and hidden. When making a platform call, we need to define the value of the constants in advance to pass to the function, the Wm_nclbuttondown and Ht_caption constants are used to drag the form, their values are saved in the WinUser.h header file, and the corresponding dynamic link library name is: user32.dll. The Win32API we use are: SendMessage, releasecapture, and ShowWindow, and by using DllImportAttribute you can import the corresponding functions and redefine them in your program as follows:

[DllImportAttribute ("User32.dll")]
public static extern int SendMessage (IntPtr hWnd, int Msg, int wParam, int lParam);
Function prototype definition in send Message//winuser.h
[DllImportAttribute ("User32.dll")]
public static extern bool ReleaseCapture (); Release mouse capture Winuser.h
[DllImportAttribute ("User32.dll")]//winuser.h
private static extern Boolean ShowWindow (IntPtr hWnd, Int32 ncmdshow);
SendMessage the message loop to simulate the drag of the form by sending a message to the header bar, ShowWindow to display the form for a particular handle, and note the second argument ncmdshow, which indicates how the form should be displayed, and we need the form not to get focus, SW _shownoactivate can meet our requirements, continue searching in the WinUser.h file to find the value of the constant corresponding to 4, so we can call to display the form:

ShowWindow (this. Handle, 4);
We created a custom function ShowForm to encapsulate the above ShowWindow used to display the form, passing several rectangle rectangular area objects used, and finally calling the Showwindows function to display the form with the following code snippet:

public void ShowForm (string ftitletext, String fcontenttext, Rectangle fregionofformtitle, Rectangle Fregionofformtitlebar, Rectangle fregionofformcontent, Rectangle fregionofclosebtn)
TitleText = Ftitletext;
ContentText = Fcontenttext;
Workarearectangle = Screen.getworkingarea (Workarearectangle);
This. top = Workarearectangle.height + this. Height;
FormBorderStyle = Formborderstyle.none;
WindowState = Formwindowstate.normal;
This. SetBounds (workarearectangle.width-this. Width, Workarearectangle.height-currenttop, this. Width, this. Height);
CurrentState = 1;
Timer1. Enabled = true;
Titlerectangle = Fregionofformtitle;
Titlebarrectangle = Fregionofformtitlebar;
Contentrectangle = fregionofformcontent;
Closebtnrectangle = fregionofclosebtn;
ShowWindow (this. Handle, 4); #define SW_SHOWNOACTIVATE 4
The CurrentState variable indicates whether the status of the form is in the display, in the stay or hidden, and two timers make changes to the position of the form based on the different states of the form, and we use the setbounds to do the action:

This. SetBounds (workarearectangle.width-this. Width, Workarearectangle.height-currenttop, this. Width, this. Height);
When a form needs to be raised, the top property value of the form is reduced, and when the form comes down, the top property value increases and exceeds the screen's height form disappears, although the principle is simple but still requires precise control.

The SETBACKGROUNDBITMAP function first saves the form background image to the Backgroundbitmap variable, and then creates the region based on the bitmap image outline and the transparent color. Bitmaptoregion is used to complete the conversion of bitmap to region, and the program then pays the region to the region property of the form to complete the creation of the irregular form.

public void Setbackgroundbitmap (image image, Color transparencycolor)
Backgroundbitmap = new Bitmap (image);
Width = Backgroundbitmap.width;
Height = Backgroundbitmap.height;
Region = Bitmaptoregion (Backgroundbitmap, TransparencyColor);

Public 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)
int x0 = i;
while ((I < width) && (bitmap. GetPixel (i, J)!= TransparencyColor))
Path. AddRectangle (New Rectangle (x0, J, i-x0, 1));
Region Region = new Region (path);
Path. Dispose ();
return region;
Notifies you that the form background and text are drawn in the overloaded OnPaintBackground method, and that the dual buffer technique is used for drawing operations, the code is as follows:

protected override void OnPaintBackground (PaintEventArgs e)
Graphics Grfx =;
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);
DrawText (Offscreengraphics);
Grfx. DrawImage (offscreenbitmap, 0, 0);
The code above first returns the graphics of the form's drawing surface and saves it in the variable Grfx, and then creates a memory graphics object Offscreengraphics and a memory bitmap object Offscreenbitmap, The value of the memory bitmap object is paid to Offscreengraphics so that all the drawing operations on the Offscreengraphics also work on the Offscreenbitmap, The background image that needs to be drawn to the surface of the notification form is then backgroundbitmap drawn to the memory graphics object. The DrawText function displays the size and range of the text as needed. Call Graphics.DrawString to display text in a specific area of the form. Finally, the call Graphics.DrawImage displays an image in memory that has been drawn to the surface of the notification form.

We also need to capture the mouse operation of the form, there are three operations here, 1, handle the drag form operation, 2, handle the closure of the notification form, 3, the content area of the click action. All three operations need to detect the current location of the mouse and the inclusion of each rectangle area, as long as the single shot down in a specific area we do the appropriate processing, the code is as follows:

private void Taskbarform_mousedown (object sender, MouseEventArgs e)
if (E.button = = MouseButtons.Left)
if (Titlebarrectangle.contains (e.location))//Drag when clicking the title bar
ReleaseCapture (); Release mouse capture
SendMessage (Handle, Wm_nclbuttondown, ht_caption, 0); Send the left-click Message to the form (title bar)
if (Closebtnrectangle.contains (e.location))//Click the Close button to turn off
This. Hide ();
Currenttop = 1;
if (Contentrectangle.contains (e.location))//click Content Area
System.Diagnostics.Process.Start ("");

The program can be very good for the notification form display, stay and hide operations, and have a simple skin mechanism, in the use of dual buffer mapping technology, you can ensure that the form of drawing smooth and no flicker.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.