Click here to Skip to main content
Licence CPOL
First Posted 8 May 2006
Views 143,339
Bookmarked 172 times

Google Talk styled Windows Form

By | 8 May 2006 | Article
How to use a custom Paint event handler to draw your own Windows Form.

Sample Image - GoogleTalkWindowsForm.gif

Introduction

This article mainly explains how to use a custom Paint event handler to draw your own Windows control (in this case, a Form control). The GoogleTalkForm class inherits and extends the System.Windows.Forms.Form control (provided by the Microsoft .NET Framework) to provide the look and feel of the Google Talk Windows Form.

The class properties IsWindowSnappable, IsResizable, ResizableColor, TitleColor, TitleFont, TitleBackColor, TitleForeColor, TitleStyle, BodyBackColor, BodyForeColor, BodyStyle, OutlineColor, OutlineSize, IconsNormalColor, IconsHiLiteColor, MinimumHeight, and MinimumWidth can be used to alter the form's standard look and feel, and behaviour.

The GoogleTalkForm class provides:

  • Drawing of the Windows Form.
  • Drawing using double buffering.
  • Form snapping to specific client desktop regions.
  • Mouse event handling.
  • System context menu item drawing.

How it works

First of all, we need to override the form events such as OnPaint, OnMouseDown, OnMouseUp, and OnMouseMove, OnDoubleClick to handle the Form Paint event and mouse events.

protected override void OnPaint(PaintEventArgs e)
{
   ...
}

protected override void OnMouseDown(MouseEventArgs e)
{
   ...
}

The Form's style must be set using the method SetStyle in the GoogleTalkForm class constructor, to reflect the required behaviour.

this.SetStyle(ControlStyles.AllPaintingInWmPaint | 
              ControlStyles.UserPaint, true);
this.SetStyle(ControlStyles.Selectable, true);
this.SetStyle(ControlStyles.StandardClick, true);
this.SetStyle(ControlStyles.StandardDoubleClick, true);
this.SetStyle(ControlStyles.DoubleBuffer, true);
this.SetStyle(ControlStyles.ResizeRedraw, true);
this.SetStyle(ControlStyles.Opaque, true);
this.SetStyle(ControlStyles.SupportsTransparentBackColor, false);
this.UpdateStyles();

The method isMousePointerInArea is used to check if the current mouse position is within a specific client rectangle area. The mouse location with respect to the Windows Form has to be worked out because the Control.MousePosition returns the mouse position relative to the desktop.

private bool isMousePointerInArea(Point mousePosition, Rectangle area)
{
    Point relativePoint = new Point(0, 0);
    relativePoint.X = mousePosition.X - this.Location.X;
    relativePoint.Y = mousePosition.Y - this.Location.Y;

    return area.Contains(relativePoint);
}

The custom Form painting is all done by the method OnFormPaint onto a newly created Bitmap object having the exact width and height of the form. A Graphics object is created from the Bitmap, and methods such as DrawString, DrawImage, DrawLine, and DrawArc are used. As soon as all painting is complete, the buffered bitmap is copied onto the form graphics instance, using the method DrawImageUnscaled.

// Create a new Pen object
p = new Pen(this.OutlineColor, this.OutlineSize);

// Draw the form outline
g.DrawArc(p, rectLeftCorner, 180, 90);
g.DrawArc(p, rectRightCorner, 270, 90);
g.DrawLine(p, edgeRadius, 0, this.Width - edgeRadius, 0);
g.DrawLine(p, 0, edgeRadius, 0, this.Height);
g.DrawLine(p, this.Width - 1, edgeRadius, 
           this.Width - 1, this.Height);
g.DrawLine(p, 0, this.Height - 1, 
           this.Width, this.Height - 1);

// Dispose the Pen object
p.Dispose();
p = null;

A custom Region is created and applied to the form, to make a rounded edge effect. To create the required region, we have to iterate pixel by pixel and add a 1x1 rectangle to the GraphicsPath object (that will be used to create the Region object) when the currently selected pixel is not the same color as the transparent color. To optimise the code, only the top corners of the form are checked for transparent colored pixels.

// Create GraphicsPath to be used to crop the region required
gpRegion = new GraphicsPath();

// Loop through every pixel in the top left corner.
// Create a 1 x 1 rectangle regions of pixels
// that do not match the transparent color
for (int x = rectLeftCorner.X; x < rectLeftCorner.Width; x++)
{
    for (int y = rectLeftCorner.Y; y < rectLeftCorner.Height / 2; y++) 
    {
        if (isSameColor(bmp.GetPixel(x, y), 
            this.transparentColor) == false) 
        {
            gpRegion.AddRectangle(new Rectangle(x, y, 1, 1));
        }
    }
}

// Loop through every pixel in the top right corner.
// Create a 1 x 1 rectangle regions of pixels
// that do not match the transparent color
for (int x = rectRightCorner.X + 1; x < 
             rectRightCorner.X + 
             rectRightCorner.Width + 1; x++)
{
    for (int y = rectRightCorner.Y; y < 
         rectRightCorner.Y + rectRightCorner.Height / 2; y++) 
    {
        if (isSameColor(bmp.GetPixel(x, y), 
            this.transparentColor) == false) 
        {
            gpRegion.AddRectangle(new Rectangle(x, y, 1, 1));
        }
    }
}

// Create the remaining rectangular regions
// to complete cover all the windows form area
gpRegion.AddRectangle(new Rectangle(rectLeftCorner.Width, 0, 
         this.Width - (edgeRadius * 4), rectLeftCorner.Height / 2));
gpRegion.AddRectangle(new Rectangle(0, 
         rectLeftCorner.Height / 2, this.Width, this.Height));

// Apply region
this.Region = new Region(gpRegion);

History

  • 1.0 - First release - (09 May 2006).
  • 1.1 - (11 May 2006).
    • Created a form designer to control the form (and child controls) behaviour.
    • Fixed the form behaviour when hosted inside an MDI container.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

NiaWs

Web Developer

Malta Malta

Member



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. (secure sign-in)
 
Search this forum  
 FAQ
    Noise  Layout  Per page   
  Refresh
QuestionLicense Terms for Google Talk styled Windows Form PinmemberMary Mayiladumpara2:21 21 Jul '08  
AnswerRe: License Terms for Google Talk styled Windows Form PinmemberNiaWs23:11 21 Jul '08  
GeneralDock Property Pinmemberbadtoto0:46 12 May '08  
QuestionHow to change the default windows form help Pinmembermuktesh patel20:44 2 Apr '08  
GeneralRe: How to change the default windows form help PinmemberNiaWs21:19 2 Apr '08  
Generalresizing problem PinmemberIfYouSaySo10:51 3 Jul '07  
GeneralRe: resizing problem PinmemberIfYouSaySo11:10 3 Jul '07  
QuestionBug using panels Pinmemberivomuccioli6:44 22 Nov '06  
GeneralResize Issue PinmemberRichard Parsons3:34 22 Nov '06  
GeneralRe: Resize Issue PinmemberIfYouSaySo11:31 3 Jul '07  
GeneralRe: Resize Issue PinmemberIfYouSaySo11:55 3 Jul '07  
QuestionHow to use it, sorry but i am now at c# PinmemberMadCodeC#5:30 15 Nov '06  
AnswerRe: How to use it, sorry but i am now at c# PinmemberMadCodeC#5:34 15 Nov '06  
AnswerRe: How to use it, sorry but i am now at c# PinmemberNiaWs19:35 15 Nov '06  
GeneralRe: How to use it, sorry but i am now at c# PinmemberMadCodeC#22:35 15 Nov '06  
GeneralMenu and Status bar Pinmembercoldfiretreachon20:47 23 Oct '06  
GeneralMinimize and Close buttons generating CPU load PinmemberMikeydoho12:58 28 Sep '06  
GeneralRe: Minimize and Close buttons generating CPU load PinmemberNiaWs20:18 28 Sep '06  
NewsRe: Minimize and Close buttons generating CPU load PinmemberMikeydoho23:49 28 Sep '06  
NewsGoogle Talk styled Windows Form PinmemberNiaWs22:04 20 Aug '06  
GeneralRe: Google Talk styled Windows Form [modified] Pinmemberpashudizhu2:59 24 Aug '06  
Questionstatic vs. dynamic link PinmemberNir Livne11:49 20 Aug '06  
How can I link the StyledForms project statically into my project
and produce independant exe without the need of dll ??
AnswerRe: static vs. dynamic link PinmemberNiaWs19:55 20 Aug '06  
NewsRe: static vs. dynamic link PinmemberNiaWs21:54 20 Aug '06  
GeneralRe: static vs. dynamic link PinmemberLowell Heddings7:33 25 Sep '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.

Permalink | Advertise | Privacy | Mobile
Web02 | 2.5.120529.1 | Last Updated 9 May 2006
Article Copyright 2006 by NiaWs
Everything else Copyright © CodeProject, 1999-2012
Terms of Use
Layout: fixed | fluid