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

Google Talk styled Windows Form

By , 8 May 2006
 

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
No Biography provided

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   
QuestionThe form Designer of VS2008 is always shiningmemberxulianjie5 Jun '12 - 0:38 
In the code window, I input "StyledForms.GoogleTalkForm" to replace "Form", then i select "view Designer" after click mouse right button, The form Designer is always shining, I don't know why, could you help me? Big Grin | :-D
QuestionLicense Terms for Google Talk styled Windows FormmemberMary Mayiladumpara21 Jul '08 - 2:21 
Hi ,
 
We would like to use Google Talk styled Windows Form in a windows based chat application being developed by us (AdventNet, Inc.). I am unable to find the applicable license either in the article text or the download files. Can you please guide me?
 
Thanks and regards,
 
Mary Mayiladumpara
AdventNet, Inc.
AnswerRe: License Terms for Google Talk styled Windows FormmemberNiaWs21 Jul '08 - 23:11 
Hi Mary,
 
I have never thought someone would be interested in using the Google Talk styled Windows Forms in a product so I did not bother to research which open source license to use. I have gone through a couple and decided to license my work under the CPOL (Code Project Open License). This should allow you to use my work in your own product.
 
Even though your company is not obliged to do so, I would really appreciate if any changes/optimization are contributed back to the community.
 
Please do not hesitate to contact me if you need help.
 
Thanks once again for taking the interest in my work,
Best regards,
Alan
GeneralDock Propertymemberbadtoto12 May '08 - 0:46 
seems it doesn't support dock property
QuestionHow to change the default windows form helpmembermuktesh patel2 Apr '08 - 20:44 
How to change the default windows form help

can any body tell me how to change the default form design.I mean when we create a new project in C# WindowsApplication in Visual Studio 2005 we get a default form box type. I want to change that box type. Example you have seen some Keygen.exe there form design looks cool. plz ant body can help me .
 
wating for reply.
GeneralRe: How to change the default windows form helpmemberNiaWs2 Apr '08 - 21:19 
You may create custom shaped Windows Forms by using regions. Kindly refer to the following articles for more information:
 
Creating Custom Shapes for Forms in Windows Forms[^]
An Alpha Channel Composited Windows Form with Designer Support[^]
 
I hope these articles will help you achieve what you require.
 
Take care Smile | :)
Generalresizing problemmemberIfYouSaySo3 Jul '07 - 10: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 problemmemberIfYouSaySo3 Jul '07 - 11:10 
Ok...so I realized that on regular forms, the mouse doesn't stop moving when you hit minimum x or y length. But if you float over the title bar, it DOES stay in resize mode, not switch to move mode. So I applied the following additional changes:
 
1) Add member variable:
 

# region clickInTitleArea
 
private bool clickInTitleArea = false;
 
# endregion
 

 
2) Modify the onmousedown override to set these values as needed:
 

 
protected override void OnMouseDown(MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
mouseDown = true;
mousePosition = Control.MousePosition;
this.clickInTitleArea = this.mouseInTitleArea;
}
}
 

 
3) Modify the mouse up handler to reset both clickInTitleArea/clickInResizeArea to false:
 

 
protected override void OnMouseUp(MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
this.mouseDown = false;
this.windowMoving = false;
this.windowResizing = false;
this.clickInTitleArea = false;
 
if (this.mouseInCloseIconArea == true)
this.Close();
 
if (this.mouseInMinimizeIconArea == true)
{
this.onMinimizeIcon = false;
this.Region = null;
this.WindowState = FormWindowState.Minimized;
}
}
}
 

 
4) And modify the mouse move code to only move the form when the original mousedown click was in the title bar:
 

 
protected override void OnMouseMove(MouseEventArgs e)
{
int x, y, width, height;
Point currentMousePosition = Control.MousePosition;
 
if (mouseDown == true)
{
// Window moving
if this.clickInTitleArea == true || this.windowMoving == true)
{
 

QuestionBug using panelsmemberivomuccioli22 Nov '06 - 6:44 
Hi NiaWs!
 
Very good work, but I found a Little Bug:
When you add a panel to the form, and then add a control (like a label) in the panel, the label couldn't be placed in the first part of the panel, that seems to be reserved to the drawing of the form title.
 
May You can help me to solve this problem.
 
Thanks a lot.
 
Ivo
 

GeneralResize IssuememberRichard Parsons22 Nov '06 - 3:34 
First off let me say this looks like one of the best attempts at custom from borders that I've seen in my searching. One thing is bothering me about this though, and that is when I resize the form I see a black box outside of the form as it's being resized. Have you seen this and do you have any ideas on fixing it?
 
Richard
http://www.BellaDev.net

GeneralRe: Resize IssuememberIfYouSaySo3 Jul '07 - 11:31 
The problem is the onpaint code region "Create/Apply Transparent region". The problem is that Bitmap.GetPixel()/Bitmap.SetPixel() are VERY slow. If you comment this section out, you will see huge improvements. Of course, then you need to figure out some other way to make the top right/top left corners of the form transparent. I'm looking into that so if I come up with something, I'll post it...
GeneralRe: Resize IssuememberIfYouSaySo3 Jul '07 - 11:55 
Ok, so I have a fix for this particular problem. First comment out the "Create/Apply Transparent Region" code block. Then in the constructor, add:
 

this.TransparencyKey = transparentColor;

 
Hopefully this works with 1.1...I'm using 2.0 and it works. But also I've been customizing a little bit, so I've also removed some of the styles that are set in the constructor, and added:
 

this.DoubleBuffered = true;

 
And I removed the code related to double-buffering in OnPaint. This is all extra & unnecessary code, because 2.0 provides double buffering for free. Anyway, I don't think that affects the transparency code at all...
QuestionHow to use it, sorry but i am now at c#memberMadCodeC#15 Nov '06 - 5:30 
Well how do i use it?
 
I compiled the source to a DLL file and added it as Reference to my project. But how do i now "Add" a new form with the style of this Google like thing? :S
 
Please help me somehow Smile | :)
AnswerRe: How to use it, sorry but i am now at c#memberMadCodeC#15 Nov '06 - 5:34 
public partial class steamlogger : StyledForms.GoogleTalkForm
 
Ok, only a few seconds after i posted it ^^
 
I am sorry.
AnswerRe: How to use it, sorry but i am now at c#memberNiaWs15 Nov '06 - 19:35 
Hi MadCodec#,
 
If you look at the class Form1 in the demo project you'll notice that it inherits from class StyledForms.GoogleTalkForm and not from the default WinForms class System.Windows.Forms.Form
 
C# inheritance example
public class Form1 : StyledForms.GoogleTalkForm
{
// Add code
}

 
VB.NET inheritance example
Public Class Form1
Inherits StyledForms.GoogleTalkForm
' Add code
End Class

 
Best regards,
Alan
GeneralRe: How to use it, sorry but i am now at c#memberMadCodeC#15 Nov '06 - 22:35 
Thank you pretty much Smile | :)
 
But i found that out pretty instantly after i posted this question, see my second reply ^^
 
But thanks anyway Smile | :)
GeneralMenu and Status barmembercoldfiretreachon23 Oct '06 - 20:47 
Hi Guys,
 
Ive seen the control and it is really cool!!! superb work!! But there are issues ive encountered (already posted by others), the menu and status docks on the center of the form. Any idea on why is it like that? im trying to see where on the code that resulted to the issue and i cant find it.
GeneralMinimize and Close buttons generating CPU loadmemberMikeydoho28 Sep '06 - 12:58 
Hi NiaWs!
 
Just wanted to start off by saying you have done a great job! I'm very impressed by how well you've structered the code.
It's very easy to find what your looking for Smile | :)
 
To the subject then.. I noticed that when I hovered with the mouse over the minimize or close button my computer fans started to accelerate. I checked the CPU load in the Task Manager and noticed that the app was using 50% as long as I was holding the mouse pointer over the buttons.
 
So I took a look at your event handlers for the mouse and noticed that you called for Invalidate eventhough you didn't have to.
 
Here is the code for the minimize event as an example:

if (this.mouseInMinimizeIconArea == true)
{
if(!this.onMinimizeIcon) // Check if MinimizeIcon is active
{
this.onMinimizeIcon = true;
this.Invalidate(this.rectMinimizeIcon, false);
}
}
else
{
if (this.onMinimizeIcon)
this.Invalidate(this.rectMinimizeIcon, false);
this.onMinimizeIcon = false;
}

 
As you can see I only call for Invalidate if I really need to. This way the CPU load jumps up to 2% at the most and then drops to zero Smile | :)
 
I'll let you know if I find any other similar issues.
 
Best regards,
Micke
GeneralRe: Minimize and Close buttons generating CPU loadmemberNiaWs28 Sep '06 - 20:18 
Hi Micke,
 
I'm really happy that you reviewed the internal code of the Google Talk styled Windows Form in such detail Smile | :)
 
Thanks for pointing out the inefficient code. I will make a note of this and make sure that this will not happen in the new version (complete rewrite).
 
Best regards,
Alan
NewsRe: Minimize and Close buttons generating CPU loadmemberMikeydoho28 Sep '06 - 23:49 
Hi Alan,
 
I don't know why but "this.onMinimizeIcon" became "this.remove" when I posted the code. Hope that didn't cause any confusion Smile | :)
 
I've started to play around with TextRenderingHint. If you're not familiar with this it's a class that makes it possible to add effects to the text. I added TextRenderingHint.ClearTypeGridFit to the common variables under OnPaint to add the ClearType effect on the Title bar, making the text look really smooth.
 
I'm trying to figure out how I can make the controls inherit this setting so that all the text in the form will get this text rendering.
 
You can find more information about the TextRenderingHint class here:
TextRenderingHint at MSDN
 
Take care mate
/Micke
NewsGoogle Talk styled Windows FormmemberNiaWs20 Aug '06 - 22:04 
Hi all,
 
I'm currently working on a new version of the Google Talk styled Windows Form that will include some new features you've requested and hopefully solve the problems you've encountered (and add some new ones to make things interesting Wink | ;) ).
 
Thanks for all the support you showed so far Big Grin | :-D
GeneralRe: Google Talk styled Windows Form [modified]memberpashudizhu24 Aug '06 - 2:59 
waiting for your new vesion.
 
don't forget notes me,my mail:pashudizhu@hotmail.com
-- modified at 9:00 Thursday 24th August, 2006
Questionstatic vs. dynamic linkmemberNir Livne20 Aug '06 - 11:49 
How can I link the StyledForms project statically into my project
and produce independant exe without the need of dll ??
AnswerRe: static vs. dynamic linkmemberNiaWs20 Aug '06 - 19:55 
If you reference any project to your Windows Forms application you will end up with an .exe and 1 or more .dll files. The only way (that I know of) to produce an independent exe is to embed the class files that make up the StyledForms project inside your Windows Forms application.
 
There might be a way of embedding the whole dll in your exe file and then extract it & reference it at runtime but I never had the requirement or the time to try it out.
NewsRe: static vs. dynamic linkmemberNiaWs20 Aug '06 - 21:54 
I managed to find an article on codeproject.com which can help you to embed dll files into your Windows Forms executable and use reflection to create a dynamic instance.
 
Using DLL component as Embedded Resource (Using reflection)[^]
GeneralRe: static vs. dynamic linkmemberLowell Heddings25 Sep '06 - 7:33 
I personally found it easiest to just copy the files into my project, as I ended up making a ton of changes to the library.
 
Very nice work.
Questiondesigntime problemmemberpashudizhu10 Aug '06 - 17:20 
hi,nice job,but i found a problem.
 
when resized the form out the edit window,i can't drag the edit window to display the entired form,seem that form is snapped.
 
pardon mu poor en.Frown | :(
Confused | :confused:
Generalgood ,excellentmemberwdpnever27 Jul '06 - 23:16 
good ,excellent
 
wdpnever
QuestionHow to add a graphicmemberrealmontanakid10 Jul '06 - 3:21 
Hi
 
Nice code.. Exatly what i'm looking for. But how can i replace the maximizeBox on the form with a graphic.
GeneralExecutablememberTechyMaila21 Jun '06 - 1:48 
Could you include an Executable of the DEMO with your DEMO code? I have the .NET Framework 1.1 installed but no SDK or Visual Studio to go with it.
 
The Exe would be much appreciated. Smile | :)
 
---
With best regards,
A Manchester United Fan
 
The Genius of a true fool is that he can mess up a foolproof plan!
GeneralRe: ExecutablememberMarijn Stevens24 Jun '06 - 9:17 
Most of the people exclude the exe because of trust.. anyway, you should download the SDK and use a (free) program like #develop if you don't like to spend much money. Big Grin | :-D
GeneralMissing functionalitiesmembergabis15 May '06 - 19:59 
Nice control but I found a few missing functionalities.
 
1. There's no MaximizeBox on the form.
2. There's no HelpBox on the form.
3. You cannot add/remove control boxes (Minimize,
Maximize, Help, Control) at design time.
4. There's no system menu on the form when clicking
on the application icon or Alt+Spacebar.
5. Statusbar is stuck in the middle of the form as
the DockPadding of the form is All-100.
If I remove the dock padding and I add a status
bar double click on the title and you're stuck
with only the statub bar on screen and no way back.
6. The maximize covers the whole screen including
the windows bar.
 
I didn't try it but it might be simpler to use WM_NCPAINT
as shown here: Creating Forms with Custom Title Bars
GeneralRe: Missing functionalitiesmemberPunCha18 May '06 - 4:41 
Very nice job, Yes, I meet the same problems with gabis's, hope u fix them soon.
 
follows are the problems i found :
 
1. The snap actions is not same as google-talks, i try to discribe the difference(but i like your style):
a) Move your window to Desktop(X=0,Y=0)
b) Move your window to the left slowly for about 5cm, your window won't move, but google's will.
 
2. StyledForms::GoogleTalkForm::OnMouseMove(...)
{
...
 
if (this.IsWindowSnappable)
{
...
 
if (snapHitTest(x, 0) == true)
x = 0;
 
// i cannot catch out what this mean( isn't this.Width = this.ClientRectangle.Width ???)
else if (snapHitTest(x + this.Width, this.ClientRectangle.Width) == true)
x = this.ClientRectangle.Width - this.Width;
 
// i think you'd better add "this.MdiParent == null && ...
else if (snapHitTest(x + this.Width, Screen.PrimaryScreen.WorkingArea.Width) == true)
x = Screen.PrimaryScreen.WorkingArea.Width - this.Width;
 
else if (this.MdiParent != null && snapHitTest(x + this.Width, this.MdiParent.ClientRectangle.Width - 4) == true)
x = this.MdiParent.ClientRectangle.Width - this.Width - 4;
 
}
...
}
 
PunCha
GeneralIncompatbility problemmemberChisFischer15 May '06 - 4:14 
Hey there!
 
Got a problem with using this MacOS styled buttons with your Google Talk Form: http://www.codeproject.com/cs/miscctrl/aquabutton.asp
I always got a gray rect. around the button... May u can help me to solve this prob.
 
Thank.
 
chris
AnswerRe: Incompatbility problemmemberNiaWs15 May '06 - 21:32 
Hi chris,
 
I've download the MacOS styled button source code and had some chance to play around to identity the problem. The grey rectangle you've mentioned is the BackColor value of the parent form. There are 2 solutions to this problem :
 
Solution 1 (settings in the Google Talk Styled inherited form) :
Set BackColor property value = BodyBackColor property value
Set BodyStyle property value = Solid
 
Solution 2 (alterations in the MacOS styled buttons):
The following code can be added to the MacOS styled button so that it copies the graphics painted by the parent form underneath the button's area.
 
Add the following in the Member Variables region
private Point curLocation;
private Size  curSize;
private Bitmap parentBitmap;
 
Add the following in the Implementation region
protected virtual void DrawBackground(Graphics g )
{
	Graphics gfx = null;
	Rectangle rectParentForm;
	Rectangle rectSource;
	Rectangle rectDestination;
 
	if (isButtonStateChanged == true || this.parentBitmap == null)
	{
		if (this.parentBitmap != null)
			this.parentBitmap.Dispose();
 
		try
		{
			this.parentBitmap = new Bitmap(this.Parent.Width, this.Parent.Height);
			gfx = Graphics.FromImage(this.parentBitmap);
			rectParentForm = new Rectangle(0, 0, this.Parent.Width, this.Parent.Height);
 
			PaintEventArgs e = new PaintEventArgs(gfx, rectParentForm);
			this.InvokePaint(this.Parent, e);
		}
		finally
		{
			if (gfx != null)
			{
				gfx.Flush();
				gfx.Dispose();
			}
		}
	}
 
	rectSource = new Rectangle(this.Location, this.Size);
	rectDestination = new Rectangle(0, 0, this.Size.Width, this.Size.Height);
	g.DrawImage(this.parentBitmap, rectDestination, rectSource, GraphicsUnit.Pixel);
}
 
private bool isButtonStateChanged
{
	get
	{
		bool stateChanged = false;
 
		if (curLocation == Point.Empty)
			stateChanged = true;
		else if (curSize == Size.Empty)
			stateChanged = true;
		else if (this.curLocation != this.Location)
			stateChanged = true;
		else if (this.curSize != this.Size)
			stateChanged = true;
 
		if (stateChanged == true)
			saveButtonState();
 
		return stateChanged;
	}
}
 
private void saveButtonState()
{
	this.curLocation = this.Location;
	this.curSize = this.Size;
}
 
Modify the following in the Implementation region
protected virtual void Draw( Graphics g )
{
	DrawBackground(g);
	DrawButton(g);
	DrawText(g);
}
 
I hope that helps to solve your problem. Thanks for trying out my custom control Smile | :)
GeneralQuestionmemberkresso11 May '06 - 1:46 
Hello
 
I have a win application with MDIForm, when i create a new form (MDIchild) an inherits from this styledform but i cannot resize and move this new form.
 
This new form is "snapping" in the desktop, and is not enable for any action for the mouse and for the keyboard.
 
Can you help me?
 
Thanks
 
VictorK
AnswerRe: QuestionmemberNiaWs11 May '06 - 4:11 
Thanks for pointing that out Smile | :)
 
I've reviewed the code and found out that the following code was causing the problem
 
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);
}
I had to change the way I was calculating the mouse pointer relative to the form as follows
 
private bool isMousePointerInArea(Point mousePosition, Rectangle area)
{
	if (!this.isDisposing)
		return area.Contains(this.PointToClient(mousePosition));
	else
		return false;
}
While testing my form inside an MDI Container I noticed that some methods where accessing the form object when it was being disposed. This should now be fixed as well.
GeneralRe: Questionmemberkresso11 May '06 - 4:24 
Thanks NiaWS for your response.
 
When you think that has a new version with these adjustments?
 
I take use your control in all my project, is very nice!!!!
 
Best Regards
 
VictorK
GeneralNice job, but...memberD_Guidi10 May '06 - 0:57 
When i minimize the form and ther i maximize itself, the form not works...
GeneralRe: Nice job, but...memberNiaWs11 May '06 - 1:12 
Thanks for your comments. I tried to replicate your problem but couldn't. Can you post the code you're using to help me debug better? Please note that I made some minor fixes that might have solved your problem.
GeneralRe: Nice job, but...memberD_Guidi11 May '06 - 2:15 
I've simply used your sample code without modifies... maybe the next version fix the problems.
I try to re-download the problem and verify if problem persist.
Thanks for response
GeneralRe: Nice job, but...memberD_Guidi11 May '06 - 3:32 
With the new code all works well! Wink | ;)
Thanks Smile | :)
GeneralRe: Nice job, but...memberNir Livne19 Aug '06 - 23:22 
When running the demo code and playing a bit with the window size i.e minimize
Then right click on taskbar and choose maximize and restore
few times, the painting gets corrupted.
first, I saw that not all background was painted
then only title was painted and finnaly an exception was thrown (see below)
 
one more thing, when resizing the window, the mouse lose the grip even if mouse button was not released. try resize the window with quick and changing moves.
 
Exception details:
 
System.ArgumentException was unhandled
Message="Rectangle '{X=0,Y=24,Width=368,Height=0}' cannot have a width or height equal to 0."
Source="System.Drawing"
StackTrace:
at System.Drawing.Drawing2D.LinearGradientBrush..ctor(Rectangle rect, Color color1, Color color2, LinearGradientMode linearGradientMode)
at StyledForms.GoogleTalkForm.OnPaint(PaintEventArgs e) in GoogleTalkForm.cs:line 786
at System.Windows.Forms.Control.PaintWithErrorHandling(PaintEventArgs e, Int16 layer, Boolean disposeEventArgs)
at System.Windows.Forms.Control.WmPaint(Message& m)
at System.Windows.Forms.Control.WndProc(Message& m)
at System.Windows.Forms.ScrollableControl.WndProc(Message& m)
at System.Windows.Forms.ContainerControl.WndProc(Message& m)
at System.Windows.Forms.Form.WndProc(Message& m)
at StyledForms.GoogleTalkForm.WndProc(Message& m) in GoogleTalkForm.cs:line 1226
at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)
at System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(Int32 dwComponentID, Int32 reason, Int32 pvLoopData)
at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
at System.Windows.Forms.Application.Run(Form mainForm)
at NormalForms.Form1.Main() in Form1.cs:line 47
at System.AppDomain.nExecuteAssembly(Assembly assembly, String[] args)
at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.ThreadHelper.ThreadStart()
GeneralCode tipmemberAlrightyThen9 May '06 - 4:59 
Just a quick tip. The following line :
 
else if ((mouseInResizeArea == true || windowResizing == true) && IsResizable == true)
 
can be changed to:
 
else if ((mouseInResizeArea || windowResizing) && IsResizable)
 
to increase readability and decrease the number of comparisons.
GeneralRe: Code tipmemberNiaWs9 May '06 - 8:37 
Hi AlrightyThen
 
Thanks for your comment Smile | :) It does look better the way you suggested but I've had to make some research to find out if it will actually optimize my code and reduce comparisons. I'm not an IL expert but here is what I found out.
 
I've compiled my current source and used ILDASM to decompile my .dll assembly. I went into the method OnMouseMove IL and located the boolean comparision as follows
 
L_01a1: ldarg.0 
L_01a2: call instance bool StyledForms.GoogleTalkForm::get_mouseInResizeArea()
L_01a7: brtrue.s L_01b4
L_01a9: ldarg.0 
L_01aa: ldfld bool StyledForms.GoogleTalkForm::windowResizing
L_01af: brfalse L_0255
L_01b4: ldarg.0 
L_01b5: call instance bool StyledForms.GoogleTalkForm::get_IsResizable()
L_01ba: brfalse L_0255
 
The IL instruction brtrue.s at location L_01a7 checks if the previously loaded variable is true, if so it will jump to location L_01b4, otherwise it continues execution at location L_01a9.
 
I've edited my source to the suggested code, compiled, ILDASM the .dll assembly and found out that the C# compiler has emitted the same IL as before.
GeneralRe: Code tipmemberFilip Duyck9 May '06 - 23:42 
That the IL would be the same is pretty normal. Has nothing to do with readability though Smile | :)
Generalnice graphical jobmemberpaillave9 May '06 - 1:28 
This is a nice render. But I'm gonna make few comments. Your OnFormPaint is unbelievebly hudge! What I could suggest you:
An interface ICloseButtonRenderer, IWindowRenderer, IMaximiseButtonRenderer, IMinimiseButtonRenderer, IRestoreButtonRenderer, IIconRenderer. Those interfaces has a function GetDrawingRectangle and a function Paint.
Then you make your classes that implements those interfaces. GetDrawingRectangle returns the rectangle where the drawing should be done, and it would be called everytime the windows is resized (OnLoad & OnResize). Paint would be called everytime the window need to be repaint (OnPaint) and would receive rectangle that has been computed by the matching GetDrawingRectangle.
Advantages of that?
1) your code becomes absolutely clear
2) you can now implement many times those interfaces in different way and then your window would be able to support styles.
 
Other detail, when you reduce and restore your windows the normal XB bar is shown.
 
Finally, seems we can draw on the bar; you should set the padding property correctly. Then if you put a control that has the dock property at "full" it won't fill completly the window.
 
Ah also something: if you want to know if a point is inside a rectangle you can do :
if(myRectangle.Contains(myPoint)) { //todo }
 
But this is still a nice job, cheer up.
 
Paillave
GeneralA couple more comments.memberuasking9 May '06 - 3:40 
I agree with paillave comments and I also think it's a great control. A couple of other things though is that instead of handling the painting and clicking as events override the OnPaint event of the form. Two reasons 1, it's actually faster because there are no delegates involved, just virtual method calls and if you switch the thing over to an mdi container it draws the borders correctly.
 
Speaking of MDI container and the docking, if you override DisplayRectangle and make that rectangle inside the drawing area then the MDI container (MdiClient) will be drawn inside as well, no need for padding which can be manipulated by inherited objects. It can all be changed anyway but will provide a nicer feal.
 
Good work though.
 

GeneralRe: A couple more comments.memberNiaWs9 May '06 - 11:18 
Thanks for your comments and the praises for my work Blush | :O . I agree with you that it would be faster to override the OnPaint event (and other events such as OnMouseDown, OnMouseUp) and I've updated my code accordingly (will upload as soon I solve the problem with child controls painted on my title bar)
 
I've tried your suggestion (i.e. to override the DisplayRectangle and set the IsMdiContainer property to true. This does create a MDI container using the display rectangle but did not stop the child control from being dragged on top of the title bar at design time in Visual Studio .NET
 
Any suggestions?
 
Thanks in advance,
NiaWs
GeneralRe: A couple more comments.memberuasking9 May '06 - 22:39 
You may have to start entering the world of designers there.
 
After looking around on the internet, have a look in the System.Design assembly there is the System.Windows.Forms.Design.FormDocumentDesigner which is designer for all form objects. That may help. You'll need a copy of the .NET Reflector though to have a look at the good stuff.

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