|
 |
Prize winner in Competition "C# Nov 2005"
|
|
|

Introduction
The Grouper is a special group box control that is rounded and fully customizable. The control can paint borders, drop shadows, and has other features like gradient and solid backgrounds, custom text, and custom icons. The purpose of this control is to design a better looking group box WinForms control. I used the (Keep it Simple Stupid) philosophy to design a tight knitted re-useable control that I hope you all will enjoy. This control is still in beta version, but it seems to be stable.
Using the code
Before you add the control, you must add a reference (CodeVendor.Controls) to your project. using CodeVendor.Controls;
The Grouper control can be added to your project with the following code. Add this code to your class. private CodeVendor.Controls.Grouper Grouper1;
this.Grouper1 = new CodeVendor.Controls.Grouper();
Custom Control Properties
Below is a list of the Grouper control properties that change the physical appearance of the control.
| Property Name |
Type |
Description |
| Control Properties |
BackColor |
Color |
This feature will paint the background color of the control. |
BackgroundColor |
Color |
This feature will change the group control color. This color can also be used in combination with BackgroundGradientColor for a gradient paint. |
BackgroundGradientColor |
Color |
This feature can be used in combination with BackgroundColor to create a gradient background. |
BackgroundGradientMode |
GroupBoxGradientMode |
This feature turns on background gradient painting. |
BorderColor |
Color |
This feature will allow you to change the color of the control's border. |
BorderThickness |
Float |
This feature will allow you to set the control's border size. |
CustomGroupBoxColor |
Color |
This feature will paint the group title background to the specified color if PaintGroupBox is set to true. |
GroupImage |
Image |
This feature can add a 16 x 16 image to the group title bar. |
GroupTitle |
string |
This feature will add a group title to the control. |
PaintGroupBox |
bool |
This feature will paint the group title background to the CustomGroupBoxColor. |
RoundCorners |
int |
This feature will round the corners of the control. |
ShadowColor |
Color |
This feature will change the control's shadow color. |
ShadowControl |
bool |
This feature will allow you to turn on control shadowing. |
ShadowThickness |
int |
This feature will change the size of the shadow border. |
| Property Name |
Type |
Description | |
Grouper Source Code
I started off writing this control because I was tired of the plain old Windows GroupBox. My WinForms application group box needed an updated XP look with round edges and gradient backgrounds. Like most developers writing controls, I thought to myself, should I custom draw the original GroupBox control, or reinvent the wheel and start from the ground up? I chose to reinvent the wheel :).
Re-inventing the wheel gave me the power to draw the control without flicker and customize it to my preferences. Taking the time to make a control from the ground up seems long and futile, but having the satisfaction of knowing that I wrote the code and if anything breaks it's because of something I wrote and not someone else is fully worth it.
To start off designing the control, I had to figure out how the original GroupBox acts as a container for other controls during design mode. Below is the code for turning any control into a design-time container control: [Designer("System.Windows.Forms.Design.ParentControlDesigner,
System.Design", typeof(IDesigner))]
This code must be added on top of your class as an attribute to your control, like so: [Designer("System.Windows.Forms.Design.ParentControlDesigner,
System.Design", typeof(IDesigner))]
public class Grouper : System.Windows.Forms.UserControl
{
}
Once the attribute is added to your control, the control will now automatically turn into a design-time control Container. Wow! Very easy and self contained, Microsoft sure does think of everything. The URL I found for this resource is: Microsoft support.
Since that took hardly anytime at all to add such power to my control, I decided to invest more time into where the original GroupBox left off, which was the design.
Painting a Control Without Flicker
If you are painting your own custom control, you should think about "What is the best way to paint without Flicker?". To paint without flicker, you need a way to double buffer your drawing or graphics. Microsoft has given us an option for this using control styles. The code below shows how to add double buffering to your control:
this.SetStyle(ControlStyles.DoubleBuffer, true);
this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
this.SetStyle(ControlStyles.UserPaint, true);
this.SetStyle(ControlStyles.SupportsTransparentBackColor, true);
This code should be added to the constructor of your class. All of the styles are needed to create a non-flicker control. If you want to make a custom double buffer, you can create the same effect by drawing all graphics to an off-screen bitmap, and then drawing the bitmap to the screen all at once. This will virtually create the same effect as the code above. Also, notice this style: this.SetStyle(ControlStyles.SupportsTransparentBackColor, true);
This style allows any control to support transparent colors. By default, user controls cannot support transparent colors. So you must enable this to add transparency to your back-color property.
Let's continue on with the painting of our custom painted control. To paint a user control, you need to override one of two methods depending on the desired effect. The two methods are OnPaint() and OnPaintBackground(). Below is the code to override these methods: protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint (e);
}
protected override void OnPaintBackground(PaintEventArgs pevent)
{
base.OnPaintBackground (pevent);
}
For the Grouper, we will be using the OnPaint() method. The code is shown below:
protected override void OnPaint(PaintEventArgs e)
{
PaintBack(e.Graphics);
PaintGroupText(e.Graphics);
}
I receive the control's Graphics object from the PaintEventArgs, and pass it to my two custom methods, PaintBack() and PaintGroupText().
Creating a Rounded Control
So, you want to create a rounded custom user control? It is pretty simple to create a rounded control using the GDI+ library. Let's dive into the code to find out how it works.
private void PaintBack(System.Drawing.Graphics g)
{
g.SmoothingMode = SmoothingMode.AntiAlias;
int ArcWidth = this.RoundCorners * 2;
int ArcHeight = this.RoundCorners * 2;
int ArcX1 = 0;
int ArcX2 = (this.ShadowControl) ? (this.Width - (ArcWidth + 1))-
this.ShadowThickness : this.Width - (ArcWidth + 1);
int ArcY1 = 10;
int ArcY2 = (this.ShadowControl) ? (this.Height - (ArcHeight + 1))-
this.ShadowThickness : this.Height - (ArcHeight + 1);
System.Drawing.Drawing2D.GraphicsPath path =
new System.Drawing.Drawing2D.GraphicsPath();
System.Drawing.Brush BorderBrush = new SolidBrush(this.BorderColor);
System.Drawing.Pen BorderPen = new Pen(BorderBrush, this.BorderThickness);
System.Drawing.Drawing2D.LinearGradientBrush BackgroundGradientBrush = null;
System.Drawing.Brush BackgroundBrush = new SolidBrush(this.BackgroundColor);
System.Drawing.SolidBrush ShadowBrush = null;
System.Drawing.Drawing2D.GraphicsPath ShadowPath = null;
if(this.ShadowControl)
{
ShadowBrush = new SolidBrush(this.ShadowColor);
ShadowPath = new System.Drawing.Drawing2D.GraphicsPath();
ShadowPath.AddArc(ArcX1+this.ShadowThickness, ArcY1+this.ShadowThickness,
ArcWidth, ArcHeight, 180, GroupBoxConstants.SweepAngle);
ShadowPath.AddArc(ArcX2+this.ShadowThickness, ArcY1+this.ShadowThickness,
ArcWidth, ArcHeight, 270, GroupBoxConstants.SweepAngle);
ShadowPath.AddArc(ArcX2+this.ShadowThickness, ArcY2+this.ShadowThickness,
ArcWidth, ArcHeight, 360, GroupBoxConstants.SweepAngle);
ShadowPath.AddArc(ArcX1+this.ShadowThickness, ArcY2+this.ShadowThickness,
ArcWidth, ArcHeight, 90, GroupBoxConstants.SweepAngle);
ShadowPath.CloseAllFigures();
g.FillPath(ShadowBrush, ShadowPath);
}
path.AddArc(ArcX1, ArcY1, ArcWidth, ArcHeight, 180,
GroupBoxConstants.SweepAngle);
path.AddArc(ArcX2, ArcY1, ArcWidth, ArcHeight, 270,
GroupBoxConstants.SweepAngle);
path.AddArc(ArcX2, ArcY2, ArcWidth, ArcHeight, 360,
GroupBoxConstants.SweepAngle);
path.AddArc(ArcX1, ArcY2, ArcWidth, ArcHeight, 90,
GroupBoxConstants.SweepAngle);
path.CloseAllFigures();
if(this.BackgroundGradientMode==GroupBoxGradientMode.None)
{
g.FillPath(BackgroundBrush, path);
}
else
{
BackgroundGradientBrush =
new LinearGradientBrush(new Rectangle(0,0,this.Width,this.Height),
this.BackgroundColor, this.BackgroundGradientColor,
(LinearGradientMode)this.BackgroundGradientMode);
g.FillPath(BackgroundGradientBrush, path);
}
g.DrawPath(BorderPen, path);
if(path!=null){path.Dispose();}
if(BorderBrush!=null){BorderBrush.Dispose();}
if(BorderPen!=null){BorderPen.Dispose();}
if(BackgroundGradientBrush!=null){BackgroundGradientBrush.Dispose();}
if(BackgroundBrush!=null){BackgroundBrush.Dispose();}
if(ShadowBrush!=null){ShadowBrush.Dispose();}
if(ShadowPath!=null){ShadowPath.Dispose();}
}
The PaintBack() method above uses the GraphicsPath() method from the System.Drawing.Drawing2D class to create four arcs starting in the order of Top Left, Top Right, Bottom Right, and Bottom Left. The arcs need to be set to TopLeft: 180, TopRight: 270, BottomRight: 360 and BottomLeft: 90, with a sweep angle of 90. The CloseAllFigures() method of the GraphicsPath closes all of these arcs together for you, creating a rounded rectangle path. All that is left to do is to fill your path, using the FillPath() method. You can also choose from a solid brush or linear gradient brush for the background of the group box. To draw a border around the control, I use the DrawPath() method of the graphics library. By passing the same path to this method with a graphics pen, you can create a line border that follows the same path.
Disposing off Graphic Objects!
So many coders including myself forget to dispose() off the graphics brushes, pens, paths, colors, etc. Leaving unmanaged resources open can cause memory leaks, and will eventually slow your machine down to a dead stop. Make sure you follow these common rules whenever you are using the graphics library:
- Dispose off all graphic objects by calling their
dispose() methods.
- Make sure to check that your graphics objects are not
null before disposing off them.
- If you have common graphics objects among multiple methods, think about declaring them as class variables or constants.
- Don't rely on the garbage collector to auto collect your used graphic resources.
Control Improvements Needed
- The group title bar does not size properly to an increased font size.
- The control needs to be able to shrink to minimum height and width, without drawing over itself.
- The group title bar needs to be able to accept icons bigger than 16 x 16, and expand to the appropriate size.
- Some fonts have an issue reporting exact sizes when measured with the
measurestring() method.
- Option to minimize the group box, and a user button to minimize.
- This has been completed:
a background HatchBrush.
- Custom control designer with preset options.
- Bevel designer.
- Drop shadow in any direction.
- Half gradient background.
- TypeEditor with multi-layer drawing and blending pad.
HatchBrushTypeEditor
I felt the need to design a custom type editor for hatch styles. This will be added as a selection for the Grouper's custom coloring and styles.

Please let me know about any improvements or features you would like to see with the 1.0 version of this control.
History
- Version 1.0
HatchBrushTypeEditor completed - January 23, 2006.
- Version 1.0a Beta - December 17, 2005.
Screenshots

Awards
Terms and Conditions For Use, Copy, Distribution, and Modification
THIS CODE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS CODE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
| You must Sign In to use this message board. |
|
| | Msgs 1 to 25 of 69 (Total in Forum: 69) (Refresh) | FirstPrevNext |
|
 |
|
|
I added some handling so the control could handle different size images and fonts in the group header.
private void PaintGroupText(System.Drawing.Graphics g) {
//CHANGED - Might want just image only in group header //Check if string has something or image has something ------------- if((this.GroupTitle==string.Empty) && (this.GroupImage == null)) { return; } //------------------------------------------
//Set Graphics smoothing mode to Anit-Alias-- g.SmoothingMode = SmoothingMode.AntiAlias; //-------------------------------------------
int imgWidth = (this.GroupImage == null) ? 0 : this.GroupImage.Width; int imgHeight = (this.GroupImage == null) ? 0 : this.GroupImage.Height; int TitleHeight = (this.GroupTitle.Length == 0) ? 0 : this.Font.Height; int TitleWidth = (this.GroupTitle.Length == 0) ? 0 : (int)g.MeasureString(this.GroupTitle, this.Font).Width;
int Shadow = (this.ShadowControl) ? this.ShadowThickness : 0; //Start the header 6 pixels from the left edge, or where the round corner stops Rectangle groupRect = new Rectangle(6 + this.RoundCorners, 0, (imgWidth + TitleWidth + (this.RoundCorners * 2)), Math.Max(imgHeight, TitleHeight) + 2 + Shadow); Point imgLocation = new Point(4 + (this.RoundCorners * 2), ((groupRect.Height - imgHeight) / 2)); Point txtLocation = (this.GroupImage == null) ? new Point(4 + (this.RoundCorners * 2), (((groupRect.Height - Shadow) - TitleHeight) / 2) + 2): new Point(imgLocation.X + imgWidth + 4, (((groupRect.Height - Shadow) - TitleHeight) / 2) + 2); int ArcWidth = this.RoundCorners; int ArcHeight = this.RoundCorners; int ArcX1 = groupRect.X; int ArcX2 = ((groupRect.X + groupRect.Width) - this.RoundCorners); int ArcY1 = groupRect.Y; int ArcY2 = ((groupRect.Y + groupRect.Height) - this.RoundCorners); System.Drawing.Drawing2D.GraphicsPath path = new System.Drawing.Drawing2D.GraphicsPath(); System.Drawing.Brush BorderBrush = new SolidBrush(this.BorderColor); System.Drawing.Pen BorderPen = new Pen(BorderBrush, this.BorderThickness); System.Drawing.Drawing2D.LinearGradientBrush BackgroundGradientBrush = null; System.Drawing.Brush BackgroundBrush = (this.PaintGroupBox) ? new SolidBrush(this.CustomGroupBoxColor) : new SolidBrush(this.BackgroundColor); System.Drawing.SolidBrush TextColorBrush = new SolidBrush(this.ForeColor); System.Drawing.SolidBrush ShadowBrush = null; System.Drawing.Drawing2D.GraphicsPath ShadowPath = null; //-----------------------------------
//Check if shadow is needed---------- if(this.ShadowControl) { ShadowBrush = new SolidBrush(this.ShadowColor); ShadowPath = new System.Drawing.Drawing2D.GraphicsPath(); ShadowPath.AddArc(ArcX1+(this.ShadowThickness-1), ArcY1+(this.ShadowThickness-1), ArcWidth, ArcHeight, 180, GroupBoxConstants.SweepAngle); // Top Left ShadowPath.AddArc(ArcX2+(this.ShadowThickness-1), ArcY1+(this.ShadowThickness-1), ArcWidth, ArcHeight, 270, GroupBoxConstants.SweepAngle); //Top Right ShadowPath.AddArc(ArcX2+(this.ShadowThickness-1), ArcY2+(this.ShadowThickness-1), ArcWidth, ArcHeight, 360, GroupBoxConstants.SweepAngle); //Bottom Right ShadowPath.AddArc(ArcX1+(this.ShadowThickness-1), ArcY2+(this.ShadowThickness-1), ArcWidth, ArcHeight, 90, GroupBoxConstants.SweepAngle); //Bottom Left ShadowPath.CloseAllFigures();
//Paint Rounded Rectangle------------ g.FillPath(ShadowBrush, ShadowPath); //----------------------------------- } //-----------------------------------
//Create Rounded Rectangle Path------ path.AddArc(ArcX1, ArcY1, ArcWidth, ArcHeight, 180, GroupBoxConstants.SweepAngle); // Top Left path.AddArc(ArcX2, ArcY1, ArcWidth, ArcHeight, 270, GroupBoxConstants.SweepAngle); //Top Right path.AddArc(ArcX2, ArcY2, ArcWidth, ArcHeight, 360, GroupBoxConstants.SweepAngle); //Bottom Right path.AddArc(ArcX1, ArcY2, ArcWidth, ArcHeight, 90, GroupBoxConstants.SweepAngle); //Bottom Left path.CloseAllFigures(); //-----------------------------------
//Check if Gradient Mode is enabled-- if(this.PaintGroupBox) { //Paint Rounded Rectangle------------ g.FillPath(BackgroundBrush, path); //----------------------------------- } else { if(this.BackgroundGradientMode==GroupBoxGradientMode.None) { //Paint Rounded Rectangle------------ g.FillPath(BackgroundBrush, path); //----------------------------------- } else { BackgroundGradientBrush = new LinearGradientBrush(new Rectangle(0,0,this.Width,this.Height), this.BackgroundColor, this.BackgroundGradientColor, (LinearGradientMode)this.BackgroundGradientMode); //Paint Rounded Rectangle------------ g.FillPath(BackgroundGradientBrush, path); //----------------------------------- } } //-----------------------------------
//Paint Borded----------------------- g.DrawPath(BorderPen, path); //-----------------------------------
//Paint Text------------------------- if (this.GroupTitle.Length > 0) { g.DrawString(this.GroupTitle, this.Font, TextColorBrush, txtLocation.X, txtLocation.Y); } //-----------------------------------
//Draw GroupImage if there is one---- if(this.GroupImage!=null) { g.DrawImage(this.GroupImage, imgLocation.X, imgLocation.Y, imgWidth, imgHeight); } //-----------------------------------
//Destroy Graphic Objects------------ if(path!=null){path.Dispose();} if(BorderBrush!=null){BorderBrush.Dispose();} if(BorderPen!=null){BorderPen.Dispose();} if(BackgroundGradientBrush!=null){BackgroundGradientBrush.Dispose();} if(BackgroundBrush!=null){BackgroundBrush.Dispose();} if(TextColorBrush!=null){TextColorBrush .Dispose();} if(ShadowBrush!=null){ShadowBrush.Dispose();} if(ShadowPath!=null){ShadowPath.Dispose();} //----------------------------------- }
/// <summary>This method will paint the control.</summary> /// <param name="g">The paint event graphics object.</param> private void PaintBack(System.Drawing.Graphics g) { //Set Graphics smoothing mode to Anit-Alias-- g.SmoothingMode = SmoothingMode.AntiAlias; //-------------------------------------------
//Declare Variables------------------ int ArcWidth = this.RoundCorners * 2; int ArcHeight = this.RoundCorners * 2; int ArcX1 = 0; int ArcX2 = (this.ShadowControl) ? (this.Width - (ArcWidth + 1))-this.ShadowThickness : this.Width - (ArcWidth + 1); int ArcY1 = 10; int ArcY2 = (this.ShadowControl) ? (this.Height - (ArcHeight + 1))-this.ShadowThickness : this.Height - (ArcHeight + 1); System.Drawing.Drawing2D.GraphicsPath path = new System.Drawing.Drawing2D.GraphicsPath(); System.Drawing.Brush BorderBrush = new SolidBrush(this.BorderColor); System.Drawing.Pen BorderPen = new Pen(BorderBrush, this.BorderThickness); System.Drawing.Drawing2D.LinearGradientBrush BackgroundGradientBrush = null; System.Drawing.Brush BackgroundBrush = new SolidBrush(this.BackgroundColor); System.Drawing.SolidBrush ShadowBrush = null; System.Drawing.Drawing2D.GraphicsPath ShadowPath = null; //-----------------------------------
//Check if shadow is needed---------- if(this.ShadowControl) { ShadowBrush = new SolidBrush(this.ShadowColor); ShadowPath = new System.Drawing.Drawing2D.GraphicsPath(); ShadowPath.AddArc(ArcX1+this.ShadowThickness, ArcY1+this.ShadowThickness, ArcWidth, ArcHeight, 180, GroupBoxConstants.SweepAngle); // Top Left ShadowPath.AddArc(ArcX2+this.ShadowThickness, ArcY1+this.ShadowThickness, ArcWidth, ArcHeight, 270, GroupBoxConstants.SweepAngle); //Top Right ShadowPath.AddArc(ArcX2+this.ShadowThickness, ArcY2+this.ShadowThickness, ArcWidth, ArcHeight, 360, GroupBoxConstants.SweepAngle); //Bottom Right ShadowPath.AddArc(ArcX1+this.ShadowThickness, ArcY2+this.ShadowThickness, ArcWidth, ArcHeight, 90, GroupBoxConstants.SweepAngle); //Bottom Left ShadowPath.CloseAllFigures();
//Paint Rounded Rectangle------------ g.FillPath(ShadowBrush, ShadowPath); //----------------------------------- } //-----------------------------------
//Create Rounded Rectangle Path------ path.AddArc(ArcX1, ArcY1, ArcWidth, ArcHeight, 180, GroupBoxConstants.SweepAngle); // Top Left path.AddArc(ArcX2, ArcY1, ArcWidth, ArcHeight, 270, GroupBoxConstants.SweepAngle); //Top Right path.AddArc(ArcX2, ArcY2, ArcWidth, ArcHeight, 360, GroupBoxConstants.SweepAngle); //Bottom Right path.AddArc(ArcX1, ArcY2, ArcWidth, ArcHeight, 90, GroupBoxConstants.SweepAngle); //Bottom Left path.CloseAllFigures(); //-----------------------------------
//Check if Gradient Mode is enabled-- if(this.BackgroundGradientMode==GroupBoxGradientMode.None) { //Paint Rounded Rectangle------------ g.FillPath(BackgroundBrush, path); //----------------------------------- } else { BackgroundGradientBrush = new LinearGradientBrush(new Rectangle(0,0,this.Width,this.Height), this.BackgroundColor, this.BackgroundGradientColor, (LinearGradientMode)this.BackgroundGradientMode); //Paint Rounded Rectangle------------ g.FillPath(BackgroundGradientBrush, path); //----------------------------------- } //-----------------------------------
//Paint Borded----------------------- g.DrawPath(BorderPen, path); //-----------------------------------
//Destroy Graphic Objects------------ if(path!=null){path.Dispose();} if(BorderBrush!=null){BorderBrush.Dispose();} if(BorderPen!=null){BorderPen.Dispose();} if(BackgroundGradientBrush!=null){BackgroundGradientBrush.Dispose();} if(BackgroundBrush!=null){BackgroundBrush.Dispose();} if(ShadowBrush!=null){ShadowBrush.Dispose();} if(ShadowPath!=null){ShadowPath.Dispose();} //----------------------------------- }
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Very nice !
Just a very small suggestion, you should add the "Localizable(true)" attribute to the GroupTitle property. That way we could change the title according to the current culture. Thanks a lot for this control !
Delphine
|
| Sign In·View Thread·PermaLink | 5.00/5 (1 vote) |
|
|
|
 |
|
|
I already made a topic but i don't see it so i'll try again.
First, this is my new groupbox, because it's a great control with many options to make it suitable for lots. I'll end up using this on all my apps from now on.
Second, i have an idea to make this control even better. I was wondering if you could add a toolstrip that was docked to the buttom of the grouper (optional). For a simple example you can look at AIM's buddy list.
I'd appreciate this very much or even a runthrough on how i can do it myself.
Thank you, VectorX.
|
| Sign In·View Thread·PermaLink | 2.00/5 (1 vote) |
|
|
|
 |
|
|
Hello,
I hope Vector X, or someone else can respond.
First, wonderful, wonderful control. I'm using it extensively, and everyone loves it.
I have a dialog, for instance, with 4 of your RoundedGroupBoxes with several fields in each. I need the user to be able to tab through them all. For some reason, on the last field in a particular Box, it refuses to continue to the next tabbed field in the Index (in another Grouper). Just to make sure this wasn't a GroupBox in general problem, I tried it with regular .NET C# Visual Studio group boxes and it worked fine.
What do I need to do to solve this problem?
Thanks, and please email the answer directly, as I may not be checking this forum very often.
Thanks!!!
...and great Box...but I need HELP!
-Brian briansmith@sunnuclear.com
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
 |
|
|
Well I found out the resizing issue is not really in this control. An Initialize Component method is needed for some resizers to handle custom controls. Larcom and Young's control cannot handle the missing Initialize in the Grouper. Another superb resizer from: http://www.fengarisoftware.com/ can handle the missing Initialize, and it handles many of the Code Projects custom controls. The big surprise was that Larcom and Young refused to even consider adapting their resizer to accommodate custom/user controls. I'm not making a sales pitch for either company and I have no affiliation with either one, but if you need to resize a control, well I just know what works and what is being pawned off as working. If you use the http://www.fengarisoftware.com resizer, and want to try out the demo, just add the code: this.height = this.height, this.width = this.width to the Initialize area. The demo does not seems to initialize the minimize and maximize buttons. Other than that it works great on custom controls. I've tried around 8 so far and all resize as expected.
|
| Sign In·View Thread·PermaLink | 1.00/5 (1 vote) |
|
|
|
 |
|
|
To hide the group title I just don't put in text into the "GroupTitle" property.
But the control still allocates space at the top of the control. Is there a way, when the GroupTitle is not shown, to have the grouper simply fill to the edge at the top.
Hope that makes sense.
GREAT tool!
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Found it.
In the PaintBack(), change the initializer for the ArcY1 = 10; to this:
//Fill complete area if there is no group title text set int ArcY1 = 10; if (string.IsNullOrEmpty(this.GroupTitle)) ArcY1 = 0;
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
 |
|
|
First I'd like to say this is a great control and up to now I've never had any problems with it. The issue I'm having now is that other controls placed on the groupbox will not resize. We have bought a control from Larcom & Young called ReSize .NET 4.1 to make resizing the form a breeze. The resize control resizes the Groupbox itself just fine, however the controls placed inside the groupbox do not resize. Is there a setting on the groupbox control I've overlooked? Did I miss a setting somewhere? I'm using the control in a VB.NET app with Visual Studio 2005. Thanks Steve.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
 |
|
|
This is an excellent tool. I'd already written a groupbox control that I was having some problems with. Your example fixed most of the problems I had. Really the only remaining problem I've got is i haven't figured out how to restrict the client space for the sub control. In both my and your cases you can move the child controls into the title area. If you've figured out a way to fix that let me know. Oh and you mentioned that you wanted to be able to resize the group based off the font. My control already did that so here's a snippet of logic that may[or may not] be of use to you. private void DrawGroupBarText(System.Drawing.Graphics graphics, GraphicsExtender ge) { if (Text.Length == 0) return;
if (Height < 8 || Width < 8) return;
SizeF layoutArea = new SizeF(Width, Height); SizeF itemSize; PointF cPoint; StringFormat drawFormat; Brush titleBarBrush = new SolidBrush(TitleBarColor);
drawFormat = new System.Drawing.StringFormat(); itemSize = graphics.MeasureString(Text, base.Font, layoutArea, drawFormat); int titleBarHeight = (int)(itemSize.Height + TITLEBAR_PAD * 2); cPoint = new PointF((layoutArea.Width - itemSize.Width) / 2, TITLEBAR_PAD); if (UseBackgroundGradientInTitle == false) ge.FillRoundRectangle(titleBarBrush, 1, 1, Width - 2, itemSize.Height + TITLEBAR_PAD * 2, 4);
titleBarBrush.Dispose();
Brush textBrush = new SolidBrush(base.ForeColor); graphics.DrawString(Text, base.Font, textBrush, cPoint, drawFormat); textBrush.Dispose();
}
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
 |
|
|
It is very very nice...
Completly change look of my application.. I appreciate your work..
Thank you very much again
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
 |
|
|
Hi,
I'm really interested in this very good control but there still are some small bugs in the current beta so I would to know when you have in planning to release the final 1.0 version. Thank you
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
First, great control!
I just noticed that when I restored a minimized app that had your control on it that it would fail in PaintBack() when trying to create a gradient brush with a height of 0. A simple, brute-force way of handling this is shown below.
protected override void OnPaint(PaintEventArgs e) { if (this.Width < 1 || this.Height < 1) return;
PaintBack(e.Graphics); PaintGroupText(e.Graphics); }
Just thought I'd share
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
This extension of the group control is great, easy to implement, lightweight and does what it says on the tin. Now help sort the awful TabControl 
Thank you. 5/5
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
 |
|
|
Everyone can use this control in their apps for free, including commercial apps. My only restriction is that you dont claim the control as yours and you dont try to sell the control as yours.
|
| Sign In·View Thread·PermaLink | 3.33/5 (2 votes) |
|
|
|
 |
|
|
ok, thank you very much!
----- Geert
Need an advanced auto-update feature for your software? Try Updater, it's free! Visit my website: | | | | | |