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

Drawing smooth text and pictures on the extended glass area of your WinForm in Windows Vista

By , 10 Jul 2008
 

Introduction

Windows Vista has a new aero theme that includes what we call the glass effect (powered by the Desktop Windows Manager). While the non-client area of all windows get glass for free, extending glass into the client area and drawing text or pictures on glass are things you have to work for, as a developer.

[This intro text is borrowed from Daniel Moth: Windows Vista: Get the glass effect in your C# applications <-You can go to this link and see more about Vista glass ^_^]

[Copyright Daniel Moth, Aug 22, 2006. All rights reserved.]

The demonstration is written in C#, and was tested on Windows Vista Beta 2.5472.

How to extend the frame into client area?

The Desktop Windows Manager (DWM) provides a group of APIs called DWM API, two of them can help us: DwmIsCompositionEnabled and DwmExtendFrameIntoClientArea.

DwmIsCompositionEnabled is used to check whether the glass is enabled by the user:

[System.Runtime.InteropServices.DllImport("dwmapi.dll")]
public extern static int DwmIsCompositionEnabled(ref int en ) ;

And DwmExtendFrameIntoClientArea is used to extend the frame into your window's client area:

[System.Runtime.InteropServices.DllImport("dwmapi.dll")]
public extern static int DwmExtendFrameIntoClientArea(IntPtr hwnd, 
                         ref MARGINS margin ) ;

The second parameter of DwmExtendFrameIntoClientArea is a structure MARGINS, which indicates how far into the client area the frame should be extended. If you want to render the entire client and non-client area as a seamless sheet of glass, just set any margin to -1:

int en=0;
MARGINS mg=new MARGINS();
mg.m_Buttom = -1;
mg.m_Left = -1;
mg.m_Right = -1;
mg.m_Top = -1 ;
//make sure you are not on a legacy OS 
if (System.Environment.OSVersion.Version.Major >= 6)             
{
    DwmIsCompositionEnabled(ref en);
    //check if the desktop composition is enabled

    if(en>0)
    {
          DwmExtendFrameIntoClientArea(this.Handle, ref mg);

    }else{
          MessageBox.Show("Desktop Composition is Disabled!");

    }
}else{
     MessageBox.Show("Please run this on Windows Vista.");
}

If you run your app now, you can’t see any effect. Because the system will draw the client area with the window backcolor automatically. So we have to paint it with a solid black brush(it so happens that the bit pattern for RGB black (0x00000000) is the same as the bit pattern for the 100% transparent ARGB), or just set the TansparencyKey property into your form’s BackColor. Then run your app, there will be the desired effect.

Sample Image - textonglass_6.png

Problems

But soon you will find some problems:

If there’s a Label on the glass area, or you draw some text using a Graphics object, you’ll see the text smoothing works “ugly”. Since it uses the form’s background to determine the color it should smooth against --- if you set the TansparncyKey,it’s the tansparncy key color, if you paint the area with a black brush, it is black, and, even worse, all the black area(usually the control’s text) is also transparent:

Sample screenshot

Sample screenshot

Solution

The solution to these problem is: do not use any Label, and draw the text by yourself. But don’t draw your text directly on the glass using the Graphics.DrawString() method for the ugly text smoothing. You have to “draw” your text into a GraphicsPath object first, then release the path to the glass surface by using the Graphics.FillPath method:

Graphics g = this.CreateGraphics();
GraphicsPath blackfont = new GraphicsPath();
SolidBrush brsh = new SolidBrush(Color.White);

blackfont.AddString("Hello Vista", 
    new FontFamily("Tahoma", (int)FontStyle.Regular, 26, 
    new Point(0, 0), StringFormat.GenericDefault);

//SmoothingMode must be set, or text smoothing will not work

g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality  ;   
g.FillPath(brsh, blackfont);    //Fill the font with White brush

Here is the effect:

Sample screenshot

Or drawing some “glow” behind the text is also OK, the only thing to remember is to do this with the GraphicsPath object:

Graphics g = this.CreateGraphics();

Rectangle r = new Rectangle(pictureBox1.Left, pictureBox1.Top, 
              pictureBox1.Width, pictureBox1.Height);

GraphicsPath path = new System.Drawing.Drawing2D.GraphicsPath();

GraphicsPath fontpath = new GraphicsPath();

path.AddEllipse(r);

fontpath.AddString("Hello Vista", new FontFamily("Tahoma"), 
    (int)FontStyle.Regular, 26,pictureBox1.Location , 
     StringFormat.GenericDefault );
PathGradientBrush pgb = new System.Drawing.Drawing2D.PathGradientBrush(path);

Color[] c ={ (Color.Transparent) };

//SmoothingMode must be set, or text smoothing will not work
 
g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality  ;  
pgb.CenterColor = Color.FromArgb(255, Color.White);

pgb.SurroundColors = c;

g.FillEllipse(pgb, r);
g.FillPath(Brushes.Black  , fontpath);

Sample screenshot

And drawing a picture with the Alpha channel on the glass area is quite easy, if you make the form into glass by painting it black (that’s also why the demo project did not use the transparency key method to extend the glass). Just call the Graphics.DrawImage() method and it will work correctly.

Sample screenshot

Some Tips

By the way, don’t extend the glass area by using the transparency key method. Because this method has another problem – Click Transparent: When you click on the glass area, you just click something at the back of your window.

Using DrawThemeTextEx

The method above is simple, but not the standard way Windows Vista uses to draw text. Windows Vista provides an API DrawThemeTextEx for us to darw the glowing text on the Aero glass. It's a little complex to use this API.

First, we must create a memory DC by using the P/Invoke API CreateCompatibleDC. Second, you need to create a 32-bit bitmap by using the API CreateDIBSection. Third, select both the bitmap and the font into the memory DC you created before, and draw the text in the memory DC using DrawThemeTextEx. Fourth, draw the text to screen by using BitBlt. Fifth....there's no fifth now, that's all.

Sample screenshot

To see more details, please visit Vista Goodies in C++: Using Glass in Your UI or Aero Glass from Managed Code, or see the GlassText.cs in the code package.

History

  • 08.29.2006 -- Initial post
  • 07.10.2008 -- Source updated

License

This article, along with any associated source code and files, is licensed under The GNU General Public License (GPLv3)

About the Author

Pang Wu
Software Developer
China China
Member
Pang is experienced in developing IM system, distributed backend caching & storage system for large scale internet services. He also has a broad interest in playing around all kinds of programming stuff, like hacking, UI programming. He's current project is MSNPSharp, a C# implementation of MSNP API library which allows you to develop your own MSN client and bot. Please see http://code.google.com/p/msnp-sharp/

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
GeneralMy vote of 4memberBarbu Victor18 Nov '12 - 4:49 
It does not cover the HitTest
SuggestionIt's not a perfect way!memberMember 86589752 Aug '12 - 20:58 
It's not a perfect way, I think! Because, when you change the system aero theme to basic theme, this code does not working any more(or maximize, minimize the form)! Must be an implementation to work perfectly.
GeneralMy vote of 5membertarek-aec14 Apr '12 - 18:44 
Perfect way!
Generalvb6memberJaseem Ahmed1 Apr '11 - 9:46 
can u plz convert this code in vb6...i need same thing for vb, whaT HAVE Y MADE for vb.net..
GeneralRe: vb6mvpDave Kreskowiak19 Jun '11 - 6:02 
VB6 doesn't support doing this, and frankly, since VB6 has been dead for quite some time now, it's not worth the effort.
 
There will be no VB6 runtime support in Windows 8 and beyond, so you better get off of VB6.

GeneralRe: vb6memberi0025 Sep '12 - 14:46 
Yes it does, I used to do this with some of my old projects. Will post an example (if i can find them, haven't used vb6 for a while) when I get home (away on business atm).
 
Kris

GeneralRe: vb6mvpDave Kreskowiak25 Sep '12 - 17:29 
VB6 itself does not. You have to PInvoke the crap out of GDI and Win32 to get this effect.
 
For VB6, is it REALLY worth the effort? Don't bother digging up the code.

QuestionIs this a Windows 7 thing I discovered?memberNetForeverOften28 Feb '10 - 18:31 
I was having difficulty getting this to work in Windows 7 (using VS 2008, .Net 3.5). Painting black left it black and painting transparent did nothing. Drawing a blank bitmap did nothing as well. So I tried e.Graphics.Clear() and it worked beautifully. Just thought if this worked in Vista as well that this one line of code might be a heck of a lot easier than targeting an area and painting it or creating a bitmap for that purpose.
AnswerRe: Is this a Windows 7 thing I discovered?memberPang Wu1 Mar '10 - 18:05 
Hi,
You mean the example code not work in Windows 7? In my system it's ok.
Regards
 
Pang Wu

GeneralRe: Is this a Windows 7 thing I discovered?memberjase_02415 Apr '10 - 16:31 
on win7, works for me too
QuestionHow to fix TextBox?memberOleg Shilo5 Feb '10 - 14:23 
The solution seems to work reasonably well for the labels.
 
Is there any way to use fix "ugly" TextBox rendering?
 
Thanks
AnswerRe: How to fix TextBox?memberPang Wu5 Feb '10 - 14:50 
Hello Oleg,
 
Actually, there is a solution, you can gathering all of the controls into a panel with BackColor set to "Control" and Dock set to "Fill".
 
Good luck!
Regards
 
Pang Wu

GeneralRe: How to fix TextBox?memberOleg Shilo5 Feb '10 - 21:55 
Thanks Pang,
 
I already tried this. Unfortunately it does not work.
 
Doesn't matter what TextBox parent is the text rendering is always distorted. With buttons it is easy as you can set UseCompatibleTextRendering = true and problems goes away. But TextBox isn't so lucky (does not have this property).
 
I actually found that it is a well known problem and usually people solve it by Owner-Draw approach.
 
Thanks anyway.
GeneralRe: How to fix TextBox?memberNetForeverOften28 Feb '10 - 18:32 
Maybe look into System.Windows.Forms.TextBoxRenderer?
GeneralRe: How to fix TextBox?memberKing4848828 May '10 - 11:34 
I have problems to fix the hugly textbox. no from this solutions work.
Generalwhy dwmextendintocilentareo doesn't take effect when the SetWindowRgn is usedmembermarch199327 Jan '10 - 3:09 
i am now developing a plugin for maxthon2 to make it supports the glass effect in win7/vista
 
but. because the maxthon2 'dig' a hole on its window to show the ieframe,so the dwmextendintocilentareo take effect only when maxthon2 show the quick access(when the windowrgn is complete),when the window is incomplete,the back of the window is just black. Frown | :(
 
and then, i use enableblurbehindwindow to enable blur,but it brings a lot of troubles, i should rewrite all the functions about text or it will be transparent.
just see the picture in http://bbs.maxthon.cn/viewthread.php?tid=216462&extra=page%3D1[^]
GeneralRe: why dwmextendintocilentareo doesn't take effect when the SetWindowRgn is usedmemberPang Wu27 Jan '10 - 15:29 
Hi,
You should ask the developers of maxthon how they implement it. I guess SetWindowRgn may not compatible with dwmextendintocilentareo.
 
And the transparent text is always a problem, you have to redraw them on the controls by yourself.
 
Regards
 
Pang Wu

GeneralDraw Text flicker...memberalecic20 Nov '09 - 4:44 
Hi, first of all thanks for this great article... I've combined it with the GlassLib that lacks on text witing on glass. My first test is a download progress glass form with a progressbar and a text writing bytes downloaded of total bytes. Everything works fine except an evident flickering effect on the text write rectangle. I've tried to use double buffering but see no differences. Any Ideas?
 
Thanks
Alessandro
GeneralRe: Draw Text flicker...memberPang Wu5 Dec '09 - 0:19 
Please see the "Using glass with double buffer" message followed.
 
Regards
 
Pang Wu

GeneralI Uses VB, i wrote the code with dwmexteadclientintoarea and draw a string,but the program unable to debugmemberleesong12 Oct '09 - 14:12 
Hi
I Uses VB, i wrote the code with dwmexteadclientintoarea and draw a string,but the program unable to debug
the code 100% translated from here, but when i am going to debug, it says that xxx.vshost.exe has stopped working,
 
Making Youtube Video Downloader Using VB.NET!

GeneralRe: I Uses VB, i wrote the code with dwmexteadclientintoarea and draw a string,but the program unable to debugmemberPang Wu12 Oct '09 - 18:12 
What version of VS you are using? Will that be the problem of your visual studio?
 
Regards
 
Pang Wu

GeneralRe: I Uses VB, i wrote the code with dwmexteadclientintoarea and draw a string,but the program unable to debugmemberNetForeverOften28 Feb '10 - 18:35 
You're not on x64 are you? If so, make sure Project->Compile->Advance Compile Options->Target CPU is set to x86. Otherwise, sounds like something is broken or miscopied.
GeneralMy vote of 1memberEmil - Gabriel17 Sep '09 - 7:51 
This is just a hack. You can't get controls with transparent backgrounds like in Internet Explorer.
GeneralRe: My vote of 1memberPang Wu12 Oct '09 - 18:15 
Hi,
 
I am afraid that you need to understand the title of an article before you getting down to read the content next time.
 
Regards
 
Pang Wu

GeneralDraw Text in another colormemberAlireza Noori28 May '09 - 4:50 
How can we draw text using DrawTextOnGlass with a color other than Black? For example white.
Thanks.

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

Permalink | Advertise | Privacy | Mobile
Web02 | 2.6.130516.1 | Last Updated 10 Jul 2008
Article Copyright 2006 by Pang Wu
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid