Border Color of GroupBox Control - c#

How can I change the border color of a GroupBox control in a windows application?

The windows groupbox doesnt have a border color property, so this means you will have to create a new class inheriting from groupbox and create your own border color property. here is the code you will need;
public class MyGroupBox : GroupBox
{
private Color _borderColor = Color.Black;
public Color BorderColor
{
get { return this._borderColor; }
set { this._borderColor = value; }
}
protected override void OnPaint(PaintEventArgs e)
{
//get the text size in groupbox
Size tSize = TextRenderer.MeasureText(this.Text, this.Font);
Rectangle borderRect = e.ClipRectangle;
borderRect.Y = (borderRect.Y + (tSize.Height / 2));
borderRect.Height = (borderRect.Height - (tSize.Height / 2));
ControlPaint.DrawBorder(e.Graphics, borderRect, this._borderColor, ButtonBorderStyle.Solid);
Rectangle textRect = e.ClipRectangle;
textRect.X = (textRect.X + 6);
textRect.Width = tSize.Width;
textRect.Height = tSize.Height;
e.Graphics.FillRectangle(new SolidBrush(this.BackColor), textRect);
e.Graphics.DrawString(this.Text, this.Font, new SolidBrush(this.ForeColor), textRect);
}
}
after adding this code to your project click build solution, then MyGroupBox will appear in your toolbox to be able to use

Related

UI glitch when writing own group box

in my program i have a group box, i didnt like that the groupbx provided in visual studio doesnt have a border colour property so i used this code to create my own group box.
public class MyGroupBox : GroupBox
{
private Color _borderColor = Color.Black;
public Color BorderColor
{
get { return this._borderColor; }
set { this._borderColor = value; }
}
protected override void OnPaint(PaintEventArgs e)
{
//get the text size in groupbox
Size tSize = TextRenderer.MeasureText(this.Text, this.Font);
Rectangle borderRect = e.ClipRectangle;
borderRect.Y = (borderRect.Y + (tSize.Height / 2));
borderRect.Height = (borderRect.Height - (tSize.Height / 2));
ControlPaint.DrawBorder(e.Graphics, borderRect, this._borderColor, ButtonBorderStyle.Solid);
Rectangle textRect = e.ClipRectangle;
textRect.X = (textRect.X + 6);
textRect.Width = tSize.Width;
textRect.Height = tSize.Height;
e.Graphics.FillRectangle(new SolidBrush(this.BackColor), textRect);
e.Graphics.DrawString(this.Text, this.Font, new SolidBrush(this.ForeColor), textRect);
}
}
which works "fine", i got myself a black border group box instead of grey, except when the window is moved the group box glitches out like so,
is there a fix for this or will i have to use the visual studio group box to prevent this issue? i am using C# winforms
The documentation for PaintEventArgs.ClipRectangle is misleading - Gets the rectangle in which to paint.. Actually this property represents the invalidated rectangle of the window, which is not always the full rectangle. It can be used to skip painting of elements that are outside that rectangle, but not as base for painting.
But the base rectangle for all painting should be the ClientRectangle property of the control being painted. So simply replace e.ClipRectangle with this.ClientRectangle.

Custom GroupBox with custom TextColor, BorderColor and Transparent BackColor

I'm using WinForms. In my form I have a GroupBox. This is a custom group box. I wanted a transparent background for the groupbox. I'm having issues creating a transparent background for the groupbox The problem with this code is i keep on getting an error when i set the group box backcolor to transparent.
Error: Control does not support transparent background colors.
g.Clear(BackColor = Color.Transparent); (This is the line that is giving me the problem)
private void DrawGroupBox(GroupBox box, Graphics g, Color textColor, Color borderColor)
{
if (box != null)
{
Brush textBrush = new SolidBrush(textColor);
Brush borderBrush = new SolidBrush(borderColor);
Pen borderPen = new Pen(borderBrush);
SizeF strSize = g.MeasureString(box.Text, box.Font);
Rectangle rect = new Rectangle(box.ClientRectangle.X,
box.ClientRectangle.Y + (int)(strSize.Height / 2),
box.ClientRectangle.Width - 1,
box.ClientRectangle.Height - (int)(strSize.Height / 2) - 1);
// Clear text and border
g.Clear(BackColor = Color.Transparent);
// Draw text
g.DrawString(box.Text, box.Font, textBrush, box.Padding.Left, 0);
// Drawing Border
//Left
g.DrawLine(borderPen, rect.Location, new Point(rect.X, rect.Y + rect.Height));
//Right
g.DrawLine(borderPen, new Point(rect.X + rect.Width, rect.Y), new Point(rect.X + rect.Width, rect.Y + rect.Height));
//Bottom
g.DrawLine(borderPen, new Point(rect.X, rect.Y + rect.Height), new Point(rect.X + rect.Width, rect.Y + rect.Height));
//Top1
g.DrawLine(borderPen, new Point(rect.X, rect.Y), new Point(rect.X + box.Padding.Left, rect.Y));
//Top2
g.DrawLine(borderPen, new Point(rect.X + box.Padding.Left + (int)(strSize.Width), rect.Y), new Point(rect.X + rect.Width, rect.Y));
}
}
private void groupBox1_Paint(object sender, PaintEventArgs e)
{
GroupBox box = sender as GroupBox;
DrawGroupBox(box, e.Graphics, Color.Red, Color.Blue);
}
g.Clear(groupBox1.BackColor = Color.Transparent);
If i do this i get:
This example consists of a Panel with a dice image inside the panel,
and the custom Groupbox.
The GroupBox control supports transparent background unless you use System as FlatStyle, but for the border color, you need to paint the group box yourself.
You can inherit from GroupBox and then because GroupBox supports Transparent background, so you can simply override the OnPaint and render your group box without doing any thing about background.
Code
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;
using System.Windows.Forms.VisualStyles;
public class GroupBoxEx : GroupBox
{
private Color borderColor = Color.Black;
[DefaultValue(typeof(Color), "Black")]
public Color BorderColor
{
get { return borderColor; }
set { borderColor = value; this.Invalidate(); }
}
private Color textColor = Color.Black;
[DefaultValue(typeof(Color), "Black")]
public Color TextColor
{
get { return textColor; }
set { textColor = value; this.Invalidate(); }
}
protected override void OnPaint(PaintEventArgs e)
{
GroupBoxState state = base.Enabled ? GroupBoxState.Normal :
GroupBoxState.Disabled;
TextFormatFlags flags = TextFormatFlags.PreserveGraphicsTranslateTransform |
TextFormatFlags.PreserveGraphicsClipping | TextFormatFlags.TextBoxControl |
TextFormatFlags.WordBreak;
Color titleColor = this.TextColor;
if (!this.ShowKeyboardCues)
flags |= TextFormatFlags.HidePrefix;
if (this.RightToLeft == RightToLeft.Yes)
flags |= TextFormatFlags.RightToLeft | TextFormatFlags.Right;
if (!this.Enabled)
titleColor = SystemColors.GrayText;
DrawUnthemedGroupBoxWithText(e.Graphics, new Rectangle(0, 0, base.Width,
base.Height), this.Text, this.Font, titleColor, flags, state);
RaisePaintEvent(this, e);
}
private void DrawUnthemedGroupBoxWithText(Graphics g, Rectangle bounds,
string groupBoxText, Font font, Color titleColor,
TextFormatFlags flags, GroupBoxState state)
{
Rectangle rectangle = bounds;
rectangle.Width -= 8;
Size size = TextRenderer.MeasureText(g, groupBoxText, font,
new Size(rectangle.Width, rectangle.Height), flags);
rectangle.Width = size.Width;
rectangle.Height = size.Height;
if ((flags & TextFormatFlags.Right) == TextFormatFlags.Right)
rectangle.X = (bounds.Right - rectangle.Width) - 8;
else
rectangle.X += 8;
TextRenderer.DrawText(g, groupBoxText, font, rectangle, titleColor, flags);
if (rectangle.Width > 0)
rectangle.Inflate(2, 0);
using (var pen = new Pen(this.BorderColor))
{
int num = bounds.Top + (font.Height / 2);
g.DrawLine(pen, bounds.Left, num - 1, bounds.Left, bounds.Height - 2);
g.DrawLine(pen, bounds.Left, bounds.Height - 2, bounds.Width - 1,
bounds.Height - 2);
g.DrawLine(pen, bounds.Left, num - 1, rectangle.X - 3, num - 1);
g.DrawLine(pen, rectangle.X + rectangle.Width + 2, num - 1,
bounds.Width - 2, num - 1);
g.DrawLine(pen, bounds.Width - 2, num - 1, bounds.Width - 2,
bounds.Height - 2);
}
}
}
Screenshot
Some note about the control
The GroupBox control supports transparent background unless you use System as FlatStyle.
You can also inherit from Panel because is is a container control and also supports transparent back color.
If you need to make a custom control that inherits form Control to support transparent background, you should add SetStyle(ControlStyles.SupportsTransparentBackColor, true); in constructor.
Above code is based on drawing code of original GroupBox and I made some changes to fit your requirements and also remains like original GroupBox.
BorderColor property added to support custom border color.
Using ForeColor property of GroupBox to render the title of control may be annoying because ForeColor is an ambient property and will be inherited by child controls. So I created another property like TextColor for this purpose. (Children of group box will use fore color of group box by default, unless you change their fore color property.)
Try this tweak:
inside the form's constructor:
this.TransparencyKey = Color.Red;
then in your code:
g.Clear(groupBox1.TransparencyKey = Color.Red);
Have you tried SetStyle?
public partial class myGroupBox : GroupBox
{
public TranspBackground()
{
SetStyle(ControlStyles.SupportsTransparentBackColor, true);
}
}

Windows Forms C# TabControl ImageList Alignment?

Is it possible to align the image icon from on a TabControl's ImageList to the right of the text?
Right now, the image icon gets put on the left, and the text is to the right of that. I would prefer the text to be on the left, and the icon to the right of that. Is this possible?
You can not do that unless you Draw the TabPage yourself. To do that you need to set the DrawMode property of the TabControl to OwnerDrawFixed and then handle the DrawItem Event.
This is a very simple example to do that, you can add some code to change the background color of the selected tab if you wish, to know which tab is selected just check the e.State value:
private void tabControl1_DrawItem(object sender, System.Windows.Forms.DrawItemEventArgs e)
{
// values
TabControl tabCtrl = (TabControl)sender;
Brush fontBrush = Brushes.Black;
string title = tabCtrl.TabPages[e.Index].Text;
StringFormat sf = new StringFormat();
sf.Alignment = StringAlignment.Near;
sf.LineAlignment = StringAlignment.Center;
int indent = 3;
Rectangle rect = new Rectangle(e.Bounds.X, e.Bounds.Y + indent, e.Bounds.Width, e.Bounds.Height - indent);
// draw title
e.Graphics.DrawString(title, tabCtrl.Font, fontBrush, rect, sf);
// draw image if available
if (tabCtrl.TabPages[e.Index].ImageIndex >= 0)
{
Image img = tabCtrl.ImageList.Images[tabCtrl.TabPages[e.Index].ImageIndex];
float _x = (rect.X + rect.Width) - img.Width - indent;
float _y = ((rect.Height - img.Height) / 2.0f) + rect.Y;
e.Graphics.DrawImage(img, _x, _y);
}
}

Set TabPage Header Color

Greetings,
I have a tab control and I want to have 1 of the tabs have it's text color changed on a event.
I've found answers like C# - TabPage Color event
and C# Winform: How to set the Base Color of a TabControl (not the tabpage)
but using these sets all colors instead of one.
So I was hoping there is a way to implement this with the tab I wish to change as a method instead of a event?
Something like:
public void SetTabPageHeaderColor(TabPage page, Color color)
{
//Text Here
}
If you want to color the tabs, try the following code:
this.tabControl1.DrawMode = TabDrawMode.OwnerDrawFixed;
this.tabControl1.DrawItem += new System.Windows.Forms.DrawItemEventHandler(this.tabControl1_DrawItem);
private Dictionary<TabPage, Color> TabColors = new Dictionary<TabPage, Color>();
private void SetTabHeader(TabPage page, Color color)
{
TabColors[page] = color;
tabControl1.Invalidate();
}
private void tabControl1_DrawItem(object sender, DrawItemEventArgs e)
{
//e.DrawBackground();
using (Brush br = new SolidBrush (TabColors[tabControl1.TabPages[e.Index]]))
{
e.Graphics.FillRectangle(br, e.Bounds);
SizeF sz = e.Graphics.MeasureString(tabControl1.TabPages[e.Index].Text, e.Font);
e.Graphics.DrawString(tabControl1.TabPages[e.Index].Text, e.Font, Brushes.Black, e.Bounds.Left + (e.Bounds.Width - sz.Width) / 2, e.Bounds.Top + (e.Bounds.Height - sz.Height) / 2 + 1);
Rectangle rect = e.Bounds;
rect.Offset(0, 1);
rect.Inflate(0, -1);
e.Graphics.DrawRectangle(Pens.DarkGray, rect);
e.DrawFocusRectangle();
}
}
For WinForms users reading this - This ONLY works if you set your tab control's DrawMode to OwnerDrawFixed - the DrawItem event never fires if it's set to Normal.
To add to Fun Mun Pieng's answer which works beautifully on Horizontal tabs, if you were to use Vertical tabs (like I was) then you would need something like this:
private void tabControl2_DrawItem(object sender, DrawItemEventArgs e)
{
using (Brush br = new SolidBrush(tabColorDictionary[tabControl2.TabPages[e.Index]]))
{
// Color the Tab Header
e.Graphics.FillRectangle(br, e.Bounds);
// swap our height and width dimensions
var rotatedRectangle = new Rectangle(0, 0, e.Bounds.Height, e.Bounds.Width);
// Rotate
e.Graphics.ResetTransform();
e.Graphics.RotateTransform(-90);
// Translate to move the rectangle to the correct position.
e.Graphics.TranslateTransform(e.Bounds.Left, e.Bounds.Bottom, System.Drawing.Drawing2D.MatrixOrder.Append);
// Format String
var drawFormat = new System.Drawing.StringFormat();
drawFormat.Alignment = StringAlignment.Center;
drawFormat.LineAlignment = StringAlignment.Center;
// Draw Header Text
e.Graphics.DrawString(tabControl2.TabPages[e.Index].Text, e.Font, Brushes.Black, rotatedRectangle, drawFormat);
}
}
I will echo the point that ROJO1969 made, if this is in WinForms - then you must set DrawMode to OwnerDrawFixed.
Special thanks goes out to this wonderful blog entry which described how to do a rotation of text on a form.
private void MainForm_Load(object sender, EventArgs e)
{
...
this.tabControl1.DrawMode = TabDrawMode.OwnerDrawFixed;
this.tabControl1.DrawItem += new System.Windows.Forms.DrawItemEventHandler(this.tabControl1_DrawItem);
...
}
private void tabControl1_DrawItem(object sender, DrawItemEventArgs e)
{
try
{
// Draw the background of the control for each item.
//e.DrawBackground();
if (e.Index == this.tabControl1.SelectedIndex)
{
Brush _BackBrush = new SolidBrush(tabControl1.TabPages[e.Index].BackColor);
Rectangle rect = e.Bounds;
e.Graphics.FillRectangle(_BackBrush, (rect.X) + 4, rect.Y, (rect.Width) - 4, rect.Height);
SizeF sz = e.Graphics.MeasureString(tabControl1.TabPages[e.Index].Text, e.Font);
e.Graphics.DrawString(tabControl1.TabPages[e.Index].Text, e.Font, Brushes.Black,
e.Bounds.Left + (e.Bounds.Width - sz.Width) / 2,
e.Bounds.Top + (e.Bounds.Height - sz.Height) / 2 + 1);
}
else
{
// 파스톤계 배경색 없앨려면 FromArgb 를 없애면 된다.
Brush _BackBrush = new SolidBrush(Color.FromArgb(50, tabControl1.TabPages[e.Index].BackColor));
Rectangle rect = e.Bounds;
e.Graphics.FillRectangle(_BackBrush, rect.X, (rect.Y)-0, rect.Width, (rect.Height)+6);
SizeF sz = e.Graphics.MeasureString(tabControl1.TabPages[e.Index].Text, e.Font);
e.Graphics.DrawString(tabControl1.TabPages[e.Index].Text, e.Font, Brushes.Black,
e.Bounds.Left + (e.Bounds.Width - sz.Width) / 2,
e.Bounds.Top + 5);
}
}
catch (Exception Ex)
{
MessageBox.Show(Ex.Message, "Error Occured", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
}
If any one need to put color for tab header use try this. My tab name tabControl
tabControl.DrawMode = TabDrawMode.OwnerDrawFixed;
tabControl.DrawItem += tabControl1_DrawItem;
declear this under main class
then,
private void tabControl1_DrawItem(object sender, DrawItemEventArgs e)
{
e.DrawBackground();
Color tabTextColor = Color.FromArgb(0x000001);
var color = Color.FromArgb(tabTextColor.R, tabTextColor.G, tabTextColor.B);
TextRenderer.DrawText(e.Graphics, tabControl.TabPages[e.Index].Text, e.Font, e.Bounds, color);
}
declare this function it will generate output
final out

Extracting an Event (tabControl_DrawItem) to Class Library

I have the following code under a TabConttrols DrawItem event that I am trying to extract into a class file. I am having trouble since it is tied to an event. Any hints or pointers would be greatly appreciated.
private void tabCaseNotes_DrawItem(object sender, DrawItemEventArgs e)
{
TabPage currentTab = tabCaseNotes.TabPages[e.Index];
Rectangle itemRect = tabCaseNotes.GetTabRect(e.Index);
SolidBrush fillBrush = new SolidBrush(Color.Linen);
SolidBrush textBrush = new SolidBrush(Color.Black);
StringFormat sf = new StringFormat
{
Alignment = StringAlignment.Center,
LineAlignment = StringAlignment.Center
};
//If we are currently painting the Selected TabItem we'll
//change the brush colors and inflate the rectangle.
if (System.Convert.ToBoolean(e.State & DrawItemState.Selected))
{
fillBrush.Color = Color.LightSteelBlue;
textBrush.Color = Color.Black;
itemRect.Inflate(2, 2);
}
//Set up rotation for left and right aligned tabs
if (tabCaseNotes.Alignment == TabAlignment.Left || tabCaseNotes.Alignment == TabAlignment.Right)
{
float rotateAngle = 90;
if (tabCaseNotes.Alignment == TabAlignment.Left)
rotateAngle = 270;
PointF cp = new PointF(itemRect.Left + (itemRect.Width / 2), itemRect.Top + (itemRect.Height / 2));
e.Graphics.TranslateTransform(cp.X, cp.Y);
e.Graphics.RotateTransform(rotateAngle);
itemRect = new Rectangle(-(itemRect.Height / 2), -(itemRect.Width / 2), itemRect.Height, itemRect.Width);
}
//Next we'll paint the TabItem with our Fill Brush
e.Graphics.FillRectangle(fillBrush, itemRect);
//Now draw the text.
e.Graphics.DrawString(currentTab.Text, e.Font, textBrush, (RectangleF)itemRect, sf);
//Reset any Graphics rotation
e.Graphics.ResetTransform();
//Finally, we should Dispose of our brushes.
fillBrush.Dispose();
textBrush.Dispose();
}
Depends on what you're trying to achieve. You could always sub class TabControl or you could encapsulate the drawing code in a class that you pass a TabControl to.
public class TabRenderer
{
private TabControl _tabControl;
public TabRenderer(TabControl tabControl)
{
_tabControl = tabControl;
_tabControl.DrawMode = TabDrawMode.OwnerDrawFixed;
_tabControl.DrawItem += TabControlDrawItem;
}
private void TabControlDrawItem(object sender, DrawItemEventArgs e)
{
// Your drawing code...
}
}

Categories

Resources