Windows Forms C# TabControl ImageList Alignment? - c#

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);
}
}

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.

C# Winform: How to set the Base Color of a TabControl (not the tabpage) AND use an icon

I applied the solution provided by an user to solve the problem, but it's happening another problem. Previously I owned an icon along with the text, but after I used the code described here, my icon no longer appears. What can it be?
And how can I use the icon while using a different color other than the default on tab header?
The solution I used is:
private void tabControl1_DrawItem(object sender, System.Windows.Forms.DrawItemEventArgs e)
{
TabPage CurrentTab = tabControl1.TabPages[e.Index];
Rectangle ItemRect = tabControl1.GetTabRect(e.Index);
SolidBrush FillBrush = new SolidBrush(Color.Red);
SolidBrush TextBrush = new SolidBrush(Color.White);
StringFormat sf = new StringFormat();
sf.Alignment = StringAlignment.Center;
sf.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.White;
TextBrush.Color = Color.Red;
ItemRect.Inflate(2, 2);
}
//Set up rotation for left and right aligned tabs
if (tabControl1.Alignment == TabAlignment.Left || tabControl1.Alignment == TabAlignment.Right)
{
float RotateAngle = 90;
if (tabControl1.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();
}
You need to paint the Icon yourself also. An example would be to add something like the following after the painting of the tabs Background in you code (i assume that an image list was used here)
int imageLeftOffset = 4;
Point imagePos = new Point(imageLeftOffset, ItemRect.Top + (ItemRect.Height - tabControl1.ImageList.ImageSize.Height + 1) / 2);
tabControl1.ImageList.Draw(e.Graphics, imagePos, CurrentTab.ImageIndex);
You may need to reajust the drawing of the Text so that text and image aren't overlapping.

Is it possible to remove the dotted rectangle and visual style on the selected tab in TabControl?

I am having a problem on my extendedtabcontol class, I cannot get rid of the dotted box or the visual style box on the selected tab. I have my own DrawItem (see below), I have overridden several methods from the tabcontrol and I have even overridden the WM_SETFOCUS and WM_PAINT in WndProc but the box and highlight will not go away. Is there anyway to turn them off (the box or visual style) or a simple way to draw over them / stop them drawing?
The user can tell which tab is selected because it is drawn in black when the others are grey.
protected void OnDrawItem(object sender, DrawItemEventArgs e)
{
// VisualStyleRenderer renderer =
// new VisualStyleRenderer(VisualStyleElement.Tab.TabItem.Disabled);
DrawItemState ds = e.State;
SolidBrush mybrush = new SolidBrush(Color.FromArgb(255, 151, 0, 11));
Rectangle tabArea2 = new Rectangle(0, 0, this.Size.Width+10, this.Size.Height+10);
//renderer.DrawBackground(e.Graphics, tabArea2);
e.Graphics.FillRectangle(mybrush, tabArea2);
int i = 0;
foreach (TabPage tb in this.TabPages)
{
Rectangle tabArea = this.GetTabRect(i);
Point newp = new Point(tabArea.Location.X,tabArea.Location.Y + 2);
tabArea.Location = newp;
if (this.SelectedIndex != i)
{
RectangleF tabTextArea = (RectangleF)this.GetTabRect(i);
e.Graphics.DrawImage(global::Config.Properties.Resources.Tab2, tabArea.Location);
}
else
{
e.Graphics.DrawImage(global::Config.Properties.Resources.Tab1, tabArea.Location);
}
SizeF size = e.Graphics.MeasureString(tb.Name.ToString().Trim(), drawFont);
PointF pf = new PointF();
pf.X = tabArea.X + (tabArea.Width / 2) - (size.Width/2);
pf.Y = tabArea.Y + (tabArea.Height / 2) - (size.Height/2);
e.Graphics.DrawString(tb.Name.ToString().Trim(), drawFont, drawBrush, pf);
i++;
}
}
I would post an image but I don't have the reputation.
Similar question for example:
Can I remove the dotted focus rectangle over tabs on a TabControl?

Graphics DrawString to Exactly Place Text on a System.Label

I have overridden the OnPaint method of my Label control in VS2008:
void Label_OnPaint(object sender, PaintEventArgs e) {
base.OnPaint(e);
dim lbl = sender as Label;
if (lbl != null) {
string Text = lbl.Text;
e.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
if (myShowShadow) { // draw the shadow first!
e.Graphics.DrawString(Text, lbl.Font, new SolidBrush(myShadowColor), myShadowOffset, StringFormat.GenericDefault);
}
e.Graphics.DrawString(Text, lbl.Font, new SolidBrush(lbl.ForeColor), 0, 0, StringFormat.GenericDefault);
}
}
This works, but I really want to find out how to center the text both vertically and horizontally. I've heard of the MeasureString() method, but my "Text" complicates matters because it could include page breaks.
Could someone guide me with how to do this?
Alternatively you can create your own StringFormat object and pass it in using an overload of DrawString that supports a RectangleF:
StringFormat formatter = new StringFormat();
formatter.LineAlignment = StringAlignment.Center;
formatter.Alignment = StringAlignment.Center;
RectangleF rectangle = new RectangleF(0, 0, lbl.Width, lbl.Height);
e.Graphics.DrawString(Text, lbl.Font, new SolidBrush(lbl.ForeColor), rectangle, formatter);
You can call TextRenderer.DrawText with the HorizontalCenter and VerticalCenter flags.
Here is the code i'm using at the moment,
SizeF size;
string text = "Text goes here";
size = e.Graphics.MeasureString(text, font);
x = (lineWidth / 2) - (size.Width / 2);
y = top;
e.Graphics.DrawString(text, font, Brushes.Black, x, y);
I just wanted to add (a year later) a tool I created because StringAlignment turned out to be not very dependable. It turns out to be very similar to Neo's version.
The code below does an excellent job of centering the text both vertically and horizontally. Also, I wrote it with various overloads so that different options could be supplied to make this control behave exactly like I want.
Here are my overloads:
private static void DrawCenter(Label label, Graphics graphics) {
DrawCenter(label.Text, label, label.Location, label.ForeColor, graphics);
}
private void DrawCenter(string text, Label label, Graphics graphics) {
DrawCenter(text, label, label.Location, label.ForeColor, graphics);
}
private static void DrawCenter(string text, Label label, Point location, Graphics graphics) {
DrawCenter(text, label, location, label.ForeColor, graphics);
}
private static void DrawCenter(string text, Label label, Point location, Color fontColor, Graphics graphics) {
Rectangle rect = new Rectangle(location, label.Size);
SizeF lSize = graphics.MeasureString(text, label.Font, rect.Width);
PointF lPoint = new PointF(rect.X + (rect.Width - lSize.Width) / 2, rect.Y + (rect.Height - lSize.Height) / 2);
graphics.DrawString(text, label.Font, new SolidBrush(fontColor), lPoint);
}
To use these for the Label's OnPaint event, simply modify my original code in the question to following:
private void Label_OnPaint(object sender, PaintEventArgs e) {
base.OnPaint(e);
Label lbl = sender as Label;
if (lbl != null) {
string txt = lbl.Text;
e.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
if (myShowShadow) { // draw the shadow first!
Point offset = new Point(lbl.Location.X - 1, lbl.Location.Y - 1)
DrawCenter(txt, lbl, offset, myShadowColor, e.Graphics);
}
DrawCenter(lbl, e.Graphics);
}
}
For a Print_Document event, I have a version that will also print a box around the label if there is already a box around it in the designer:
private static void DrawCenter(string text, Label label, Point location, Color fontColor, Graphics graphics) {
Rectangle rect = new Rectangle(location, label.Size);
SizeF lSize = graphics.MeasureString(text, label.Font, rect.Width);
PointF lPoint = new PointF((rect.Width - lSize.Width) / 2, (rect.Height - lSize.Height) / 2);
graphics.DrawString(text, label.Font, new SolidBrush(fontColor), lPoint);
if (label.BorderStyle != BorderStyle.None) {
using (Pen p = new Pen(Color.Black)) {
graphics.DrawRectangle(p, rect);
}
}
}
If you find this at all useful, give me a +1.
~Joe

Border Color of GroupBox Control

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

Categories

Resources