Click here to Skip to main content
11,490,266 members (50,050 online)
Click here to Skip to main content

Google Talk styled Windows Form

, 8 May 2006 CPOL 172.4K 4.2K 180
Rate this:
Please Sign up or sign in to vote.
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)

Share

About the Author

NiaWs
Web Developer
Malta Malta
No Biography provided

Comments and Discussions

 
SuggestionGreat! Pin
brunopbarrote4-Oct-13 10:38
memberbrunopbarrote4-Oct-13 10:38 
QuestionAlways can't inherited form StyledForms Pin
Member 100881496-Jul-13 20:28
memberMember 100881496-Jul-13 20:28 
AnswerRe: Always can't inherited form StyledForms Pin
Member 100881496-Jul-13 21:25
memberMember 100881496-Jul-13 21:25 
GeneralRe: Always can't inherited form StyledForms Pin
NiaWs7-Jul-13 1:19
memberNiaWs7-Jul-13 1:19 
QuestionThe form Designer of VS2008 is always shining Pin
xulianjie5-Jun-12 1:38
memberxulianjie5-Jun-12 1:38 
QuestionLicense Terms for Google Talk styled Windows Form Pin
Mary Mayiladumpara21-Jul-08 3:21
memberMary Mayiladumpara21-Jul-08 3:21 
AnswerRe: License Terms for Google Talk styled Windows Form Pin
NiaWs22-Jul-08 0:11
memberNiaWs22-Jul-08 0:11 
GeneralDock Property Pin
badtoto12-May-08 1:46
memberbadtoto12-May-08 1:46 
QuestionHow to change the default windows form help Pin
muktesh patel2-Apr-08 21:44
membermuktesh patel2-Apr-08 21:44 
GeneralRe: How to change the default windows form help Pin
NiaWs2-Apr-08 22:19
memberNiaWs2-Apr-08 22:19 
Generalresizing problem Pin
IfYouSaySo3-Jul-07 11:51
memberIfYouSaySo3-Jul-07 11:51 
Small problem. When I resize to the form minimum in say the Y direction, I can no longer resize in the X direction (or vice-versa). The form just stops responding to mouse move events. I *thought* that I could just comment out the lines "this.windowResizing = false" in your MouseMove override. I.e.:


// Window resizing
else if ((this.mouseInResizeArea || this.windowResizing) && this.IsResizable)
{
width = currentMousePosition.X - this.mousePosition.X + this.Size.Width;
height = currentMousePosition.Y - this.mousePosition.Y + this.Size.Height;

if (width < this.MinimumWidth)
{
width = this.MinimumWidth;
// this.windowResizing = false;
}
else if (height < this.MinimumHeight)
{
height = this.MinimumHeight;
// this.windowResizing = false;
}
else
{
this.windowResizing = true;
}


This fixes the resize problem (good), but the mouse keeps on moving (bad). So when the mouse ends up over the title bar, you end up in window-move mode, not resize mode. Since Control.MousePosition is readonly, I wasn't quite sure how to freeze the mouse location, once the form reaches minimum size in either x or y direction.
GeneralRe: resizing problem Pin
IfYouSaySo3-Jul-07 12:10
memberIfYouSaySo3-Jul-07 12:10 
QuestionBug using panels Pin
ivomuccioli22-Nov-06 7:44
memberivomuccioli22-Nov-06 7:44 
GeneralResize Issue Pin
Richard Parsons22-Nov-06 4:34
memberRichard Parsons22-Nov-06 4:34 
GeneralRe: Resize Issue Pin
IfYouSaySo3-Jul-07 12:31
memberIfYouSaySo3-Jul-07 12:31 
GeneralRe: Resize Issue Pin
IfYouSaySo3-Jul-07 12:55
memberIfYouSaySo3-Jul-07 12:55 
QuestionHow to use it, sorry but i am now at c# Pin
MadCodeC#15-Nov-06 6:30
memberMadCodeC#15-Nov-06 6:30 
AnswerRe: How to use it, sorry but i am now at c# Pin
MadCodeC#15-Nov-06 6:34
memberMadCodeC#15-Nov-06 6:34 
AnswerRe: How to use it, sorry but i am now at c# Pin
NiaWs15-Nov-06 20:35
memberNiaWs15-Nov-06 20:35 
GeneralRe: How to use it, sorry but i am now at c# Pin
MadCodeC#15-Nov-06 23:35
memberMadCodeC#15-Nov-06 23:35 
GeneralMenu and Status bar Pin
coldfiretreachon23-Oct-06 21:47
membercoldfiretreachon23-Oct-06 21:47 
GeneralMinimize and Close buttons generating CPU load Pin
Mikeydoho28-Sep-06 13:58
memberMikeydoho28-Sep-06 13:58 
GeneralRe: Minimize and Close buttons generating CPU load Pin
NiaWs28-Sep-06 21:18
memberNiaWs28-Sep-06 21:18 
NewsRe: Minimize and Close buttons generating CPU load Pin
Mikeydoho29-Sep-06 0:49
memberMikeydoho29-Sep-06 0:49 
NewsGoogle Talk styled Windows Form Pin
NiaWs20-Aug-06 23:04
memberNiaWs20-Aug-06 23:04 
GeneralRe: Google Talk styled Windows Form [modified] Pin
pashudizhu24-Aug-06 3:59
memberpashudizhu24-Aug-06 3:59 
Questionstatic vs. dynamic link Pin
Nir Livne20-Aug-06 12:49
memberNir Livne20-Aug-06 12:49 
AnswerRe: static vs. dynamic link Pin
NiaWs20-Aug-06 20:55
memberNiaWs20-Aug-06 20:55 
NewsRe: static vs. dynamic link Pin
NiaWs20-Aug-06 22:54
memberNiaWs20-Aug-06 22:54 
GeneralRe: static vs. dynamic link Pin
Lowell Heddings25-Sep-06 8:33
memberLowell Heddings25-Sep-06 8:33 
Questiondesigntime problem Pin
pashudizhu10-Aug-06 18:20
memberpashudizhu10-Aug-06 18:20 
Generalgood ,excellent Pin
wdpnever28-Jul-06 0:16
memberwdpnever28-Jul-06 0:16 
QuestionHow to add a graphic Pin
realmontanakid10-Jul-06 4:21
memberrealmontanakid10-Jul-06 4:21 
GeneralExecutable Pin
TechyMaila21-Jun-06 2:48
memberTechyMaila21-Jun-06 2:48 
GeneralRe: Executable Pin
Marijn Stevens24-Jun-06 10:17
memberMarijn Stevens24-Jun-06 10:17 
GeneralMissing functionalities Pin
gabis15-May-06 20:59
membergabis15-May-06 20:59 
GeneralRe: Missing functionalities Pin
PunCha18-May-06 5:41
memberPunCha18-May-06 5:41 
GeneralIncompatbility problem Pin
ChisFischer15-May-06 5:14
memberChisFischer15-May-06 5:14 
AnswerRe: Incompatbility problem Pin
NiaWs15-May-06 22:32
memberNiaWs15-May-06 22:32 
GeneralQuestion Pin
kresso11-May-06 2:46
memberkresso11-May-06 2:46 
AnswerRe: Question Pin
NiaWs11-May-06 5:11
memberNiaWs11-May-06 5:11 
GeneralRe: Question Pin
kresso11-May-06 5:24
memberkresso11-May-06 5:24 
GeneralNice job, but... Pin
D_Guidi10-May-06 1:57
memberD_Guidi10-May-06 1:57 
GeneralRe: Nice job, but... Pin
NiaWs11-May-06 2:12
memberNiaWs11-May-06 2:12 
GeneralRe: Nice job, but... Pin
D_Guidi11-May-06 3:15
memberD_Guidi11-May-06 3:15 
GeneralRe: Nice job, but... Pin
D_Guidi11-May-06 4:32
memberD_Guidi11-May-06 4:32 
GeneralRe: Nice job, but... Pin
Nir Livne20-Aug-06 0:22
memberNir Livne20-Aug-06 0:22 
GeneralCode tip Pin
AlrightyThen9-May-06 5:59
memberAlrightyThen9-May-06 5:59 
GeneralRe: Code tip Pin
NiaWs9-May-06 9:37
memberNiaWs9-May-06 9:37 
GeneralRe: Code tip Pin
Filip Duyck10-May-06 0:42
memberFilip Duyck10-May-06 0:42 

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 | Terms of Use | Mobile
Web01 | 2.8.150520.1 | Last Updated 9 May 2006
Article Copyright 2006 by NiaWs
Everything else Copyright © CodeProject, 1999-2015
Layout: fixed | fluid