Click here to Skip to main content
Click here to Skip to main content
Go to top

OSD window with animation effect, in C#

, 25 May 2006
Rate this:
Please Sign up or sign in to vote.
The article explains how to create an OSD window with animation/semi-transparent effects, in C#, using the NativeWindow class.

Introduction

I needed an OSD-like window to show some important information from my WinForms application. I looked everywhere for samples in C#/.NET, but the samples that I could find were weak (from my point of view) and written in C++ (or C). So, I had no choice but to write my own OSD window (hereafter, just OW). But the excellent article "Floating, collapsible transparent window in C#" by olvio had some great code that helped me a lot. Thank you very much, olvio!

Background

First of all, what is an OSD? OSD is a short text message, displayed to the user when some event occurs – like the user presses the key, file downloading is complete, a new mail has arrived, and so on. An OSD (and OW, obviously) must possess three main characteristics:

  • Should always be the top most window: User must see our message even if he/she is working in Word, IE, or reading a mail.
  • Should always be completely transparent: User must see the text, and not the background of OW.
  • Should always be completely transparent to mouse/keyboard events: This means that the user must be able to select an icon positioned "under" OW through OW. Or, if the user is working in Word, and OSD's text is displayed "above" Word's main area and the user moves the mouse pointer in OSD's client area, then the mouse pointer must not change its appearance to "Arrow". Instead, it must keep the "Text select" form. In other words, the mouse/keyboard doesn't "see" OW, but the user does. Smile | :) Needless to say, OW must be transparent to the system as a whole – no button on the task bar, no entry in Task Manager, etc.

The suggested solution completely fulfills all the three requirements. Moreover, it offers additional features (optional, of course) – a bunch of animation effects when OW is shown/hidden, the OSD text itself may be fully opaque, fully transparent, or in between, and some others.

General architecture

As said earlier, the great code from olvio serves as the starting point. But I have "stripped off" a few redundant functions from the original FloatingWindow and kept only the required ones for OSD. So, my FloatingWindow is much, much simpler than the original. To be brief, the FloatingWindow is created as a System.Windows.Forms.NativeWindow with some special ExStyle flags:

  • WS_EX_TOPMOST helps OW to be the top most window.
  • WS_EX_TRANSPARENT helps OW to be completely transparent (by sight).
  • WS_EX_LAYERED (this flag is supported by Windows 2000 and above!) and WS_EX_TOOLWINDOW help OW to be completely transparent to the mouse/keyboard/system.

Now, we can show a new window (with or without animation) and also hide it (also with optional animation). From this window inherits FloatingOSDWindow, our main "work horse". It overrides the PerformPaint() method of the base class to show the OSD text, and gives us the public method Show(…) with many parameters. As a matter of fact, I have used the OW suffice to know what each parameter of this single method means, and nothing more. Let's jump to this method.

Using the code

We instantiate the new OW by calling a parameter-less constructor:

FloatingOSDWindow osd1 = new FloatingOSDWindow();

Now, we are ready to call Show(…):

public void Show(Point pt, byte alpha, 
    Color textColor, Font textFont, int showTimeMSec, 
    AnimateMode mode, uint time, string text)

The purpose of these parameters:

  • pt - Coordinate of the top-left corner of OW in screen coordinates.
  • alpha - Degree of transparency of the OSD text. This is not the transparency of OW's background. This window doesn't have the background. So this parameter is for the text's transparency. As you may expect, 0 means totally transparent (no text) and 255 means totally opaque – any object "under" the text is hidden. As a general rule, any value in the range 100-210 is fine.
  • textColor - OSD text color.
  • textFont - OSD text font. Again, the font must be large enough (18-48 point) to attract the user's attention.
  • showTimeMSec - For how long the OSD text will be displayed on the screen, in milliseconds. After this, OW will be automatically closed and disposed.
  • mode - One of the AnimateMode enum members. Determines the effect that will be used when OW opens/closes. Also see the next parameter, time.
  • time - If this parameter is zero, no animation effect is used, the mode parameter is just ignored, and OW opens/closes at once. If it is greater than 0, it specifies how long it takes to play the animation, in milliseconds. This time is not included in showTimeMSec but used twice – when OW opens, and when it closes. Example: showTimeMSec = 3500 and time = 500. In this case, after calling Show(…), for 0.5 sec, OW will be opened with the effect specified in mode. Next, the fully opened window will be displayed for 3.5 sec. Finally, during the same 0.5 sec, OW will be closed with the same effect. Again, a general (if we want animation) value in the range 100-500 is fine for this parameter.
  • text - OSD text itself, at last. Smile | :)

Example of calling the function:

osd1.Show(new Point(20, 45), 155, Color.Lime, 
    new Font("Verdana", 26f, FontStyle.Bold | FontStyle.Italic), 
                 2400, FloatingWindow.AnimateMode.ExpandCollapse, 
                 370, "Hello! I am OSD window...");

After calling Show(…), you don't need to call the Hide()/Close() method explicitly. See the description of the showTimeMSec parameter if you have forgotten. But, of course, you can do it if, for example, if you want to force OW to close before showTimeMSec expires.

Points of interest

When I tried to override the PerformPaint() method in the FloatingOSDWindow class to provide the drawing of the OSD text, my first approach was to draw the string with:

Graphics g = e.Graphics;
g.TextRenderingHint = 
   System.Drawing.Text.TextRenderingHint.AntiAlias;
g.DrawString(…);

It works, but in spite of the AntiAlias rendering mode for the text, the OSD text comes into view with a black edge around the letters. This edging is very thin, but noticeable. So I tried another way – create GraphicsPath from the given string and fill up this path with the given color:

Graphics g = e.Graphics;
this._gp = new GraphicsPath();
this._gp.AddString("OSD text", …..);
g.SmoothingMode = SmoothingMode.HighQuality;
g.FillPath(this._brush, this._gp);

This approach works perfectly as you can see from the demo project. The interesting problem was with this._gp.AddString(…). This string of code, as you expect, adds the given text string to the path. One of the parameters for this method, float emSize, is the font size. Of course, this size must be the same as the size of the textFont font, which is passed to Show(…). At first glance, there is no problem: use textFont.SizeInPoints and we have the needed value. But this is tricky: AddString(…) expects float emSize in pixel, but we try to pass it as point. So, we need to convert between points and pixels, which in turn requires detailed knowledge of the DPI of the device we are drawing on. The last value returned by the Graphics.DpiY property:

Graphics g = e.Graphics;
…
this._gp.AddString(..., ..., ..., 
    g.DpiY * textFont.SizeInPoints / 72, ..., ...);

We divide by 72, since point is 1/72 of an inch, no matter on what device we draw. And, Graphics.DpiY returns in dots (and, in fact, pixels) per inch. So this formula works just fine.

Final notes

This solution was developed under VS2005/FW2.0. So it may not open in VS2003. But the code will, no doubt, work in VS2003/FW1.1(1.0). Just create a new solution and use the *.cs files from the pack.

History

  • 1/1/2006: Version 1.0 - First release.
  • 5/25/2006: Version 1.1 - Fixed problem with handles leak.

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

Share

About the Author

Mr.Smarty
Web Developer
Russian Federation Russian Federation
Professional C#/.NET/WinForms/ADO.NET developer. Microsoft Certified Solution Developer (MCSD) for Microsoft .NET since 2003.

Comments and Discussions

 
QuestionNot visible on Screenshot with CopyFromScreen [modified] PinmemberCommerzpunk_cp4-Jun-13 1:52 
QuestionLittle problem in .net framework 4.0 Pinmembersuper10227-May-13 16:12 
QuestionThis is AWESOME!!!!!! Pinmemberflippydeflippydebop16-Jan-13 3:44 
QuestionWay to create OSD window in the bottom level? PinmemberAli_MH26-Nov-11 21:58 
Generalmulti monitor Pinmemberproximus98313-Oct-10 22:28 
QuestionHow can I change it's color when it's displaying? Pinmemberbaihualin198328-Sep-10 22:15 
GeneralThanks, but it wont work in my app PinmemberFullmetal9901227-Feb-10 15:34 
GeneralGood, but ... PinmemberKartun20-Jan-10 4:04 
QuestionAny way to get it to Update faster? PinmemberKbirger2-Jun-09 3:35 
NewsJust a little correction Pinmembersiamoen10-Mar-09 14:55 
GeneralExcellent work Pinmemberjtradke28-Aug-08 16:36 
Generalthank you :o) Pinmembersqweez8-Feb-08 14:12 
GeneralDisplaying Images Pinmemberkevinwebster839-Oct-07 0:57 
GeneralProblem when using OSD with BSPlayer, or other DirectX software PinmemberVandra Akos9-Apr-07 23:31 
Questionvery good article, but some small questions... Pinmembermmaddin26-Mar-07 3:17 
GeneralChanging the text PinmemberTTCDave9-Mar-07 19:11 
AnswerRe: Changing the text PinmemberVladimir N.2-Sep-07 20:48 
QuestionLicense Pinmembergodfatherb5-Mar-07 10:37 
QuestionMouseMove/MouseEnter/MouseLeave on control beneath it Pinmemberlok_tan31-Aug-06 17:45 
QuestionNice, but.. Pinmembergrep224-Aug-06 21:09 
QuestionCan have 100% opaque window text while 70% transparent window background? [modified] PinmemberAlexandru30-May-06 23:03 
AnswerRe: Can have 100% opaque window text while 70% transparent window background? [modified] PinmemberMr.Smarty31-May-06 2:47 
GeneralRe: Can have 100% opaque window text while 70% transparent window background? [modified] PinmemberAlexandru31-May-06 5:37 
GeneralRe: Can have 100% opaque window text while 70% transparent window background? [modified] PinmemberMr.Smarty31-May-06 9:17 
GeneralRe: Can have 100% opaque window text while 70% transparent window background? [modified] PinmemberAlexandru31-May-06 9:56 
GeneralRe: Can have 100% opaque window text while 70% transparent window background? PinmemberChristian W30-Mar-07 2:11 
GeneralPlease provide an EXE too... [modified] PinmemberAlexandru23-May-06 22:29 
GeneralRe: Please provide an EXE too... [modified] Pinmemberreflex@codeproject29-May-06 15:45 
GeneralResource leaks PinmemberXozar14-Apr-06 0:11 
GeneralRe: Resource leaks Pinmemberoykica25-May-06 20:32 
GeneralRe: Resource leaks PinmemberMr.Smarty25-May-06 23:03 
QuestionRefresh problem when OSD window is covered Pinmembernagarsoft3-Apr-06 2:54 
AnswerRe: Refresh problem when OSD window is covered PinmemberMr.Smarty3-Apr-06 3:59 
GeneralRe: Refresh problem when OSD window is covered Pinmembermegamacy18-Jul-07 2:35 
QuestionVS.NET 2003 version Pinmembernagarsoft2-Apr-06 22:27 
AnswerRe: VS.NET 2003 version PinmemberMr.Smarty3-Apr-06 1:31 
GeneralGreat article Pinmembertatkowski23-Feb-06 22:58 
GeneralMouse Events Pinmemberjgallen237-Feb-06 5:56 
GeneralRe: Mouse Events PinmemberMr.Smarty7-Feb-06 10:24 
GeneralRe: Mouse Events Pinmemberjgallen237-Feb-06 10:27 
GeneralRe: Mouse Events PinmemberMr.Smarty7-Feb-06 14:31 
GeneralRe: Mouse Events Pinmemberjgallen238-Feb-06 7:37 
GeneralRe: Mouse Events PinmemberMr.Smarty8-Feb-06 15:37 
GeneralThank You Very Much PinmemberKdukes7-Feb-06 4:15 
GeneralThanks PinmemberPetrica9-Jan-06 10:50 
GeneralConcise and works exactly as described PinmemberHal Angseesing4-Jan-06 1:06 

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
Web01 | 2.8.140916.1 | Last Updated 25 May 2006
Article Copyright 2006 by Mr.Smarty
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid