c# tabControl background color [duplicate] - c#

I have these visual glitches on every tabControls when I am changing its tabPages BackColor and the BackColor of the form, as illustrated on the following images:
At the top of the tabPage, there is an interior one-pixel white border.
At the left of the tabPage, there is an interior three-pixels white border.
At the bottom of the tabPage, there is an interior one-pixel white border and an exterior two-pixels white border.
At the right of the tabPage, there is an interior one-pixel white border and an exterior two-pixels white border.
Is there a way I can get rid of those white borders?

Here's my attempted hack. I used a NativeWindow to draw over the TabControl to fill in those "white" spaces. I won't claim it's perfect:
public class TabPadding : NativeWindow {
private const int WM_PAINT = 0xF;
private TabControl tabControl;
public TabPadding(TabControl tc) {
tabControl = tc;
tabControl.Selected += new TabControlEventHandler(tabControl_Selected);
AssignHandle(tc.Handle);
}
void tabControl_Selected(object sender, TabControlEventArgs e) {
tabControl.Invalidate();
}
protected override void WndProc(ref Message m) {
base.WndProc(ref m);
if (m.Msg == WM_PAINT) {
using (Graphics g = Graphics.FromHwnd(m.HWnd)) {
//Replace the outside white borders:
if (tabControl.Parent != null) {
g.SetClip(new Rectangle(0, 0, tabControl.Width - 2, tabControl.Height - 1), CombineMode.Exclude);
using (SolidBrush sb = new SolidBrush(tabControl.Parent.BackColor))
g.FillRectangle(sb, new Rectangle(0,
tabControl.ItemSize.Height + 2,
tabControl.Width,
tabControl.Height - (tabControl.ItemSize.Height + 2)));
}
//Replace the inside white borders:
if (tabControl.SelectedTab != null) {
g.ResetClip();
Rectangle r = tabControl.SelectedTab.Bounds;
g.SetClip(r, CombineMode.Exclude);
using (SolidBrush sb = new SolidBrush(tabControl.SelectedTab.BackColor))
g.FillRectangle(sb, new Rectangle(r.Left - 3,
r.Top - 1,
r.Width + 4,
r.Height + 3));
}
}
}
}
}
And to hook it up:
public Form1() {
InitializeComponent();
var tab = new TabPadding(tabControl1);
}
My end result:

you can inherit from control
public class TabControlEx : TabControl
{
protected override void WndProc(ref Message m)
{
if (m.Msg == 0x1300 + 40)
{
RECT rc = (RECT)m.GetLParam(typeof(RECT));
rc.Left -= 0;
rc.Right += 3;
rc.Top -= 0;
rc.Bottom += 3;
Marshal.StructureToPtr(rc, m.LParam, true);
}
base.WndProc(ref m);
}
}
internal struct RECT { public int Left, Top, Right, Bottom; }

I recently ran into this problem and never found a good simple solution. That's when I thought about simply adjusting the control's clipping region. This seemed to work just fine with no noticeable side-effects. The 2 extra white pixels on the right side and the one extra white pixel at the bottom are no longer visible.
class TabControlEx : TabControl
{
protected override void WndProc(ref Message m)
{
if (m.Msg == 0x0005) // WM_SIZE
{
int Width = unchecked((short)m.LParam);
int Height = unchecked((short)((uint)m.LParam >> 16));
// Remove the annoying white pixels on the outside of the tab control
// by adjusting the control's clipping region to exclude the 2 pixels
// on the right and one pixel on the bottom.
Region = new Region(new Rectangle(0, 0, Width - 2, Height - 1));
}
base.WndProc(ref m);
}
}

Related

ScrollableControl draw border around entire control

I'm building custom user control that is based on ScrollableControl.
Right now I'm trying to add border around my control (similar to border that DataGridView has)
I'm able to draw border using:
e.Graphics.TranslateTransform(AutoScrollPosition.X*-1, AutoScrollPosition.Y*-1);
ControlPaint.DrawBorder(e.Graphics, ClientRectangle, Color.DarkBlue, ButtonBorderStyle.Dashed);
but this draws border around ClientRectangle, not around whole control:
As you can see in the above picture, border isn't surrounding scrollbars as it does in DataGridView.
Can I draw border around entire control so that scrollbars get included in area surrounded by border?
EDIT:
Based on Textbox custom onPaint I am able to draw custom border, by overriding WndProc but I get this weird looking border flickering:
Here is full code I have so far:
internal class TestControl : ScrollableControl
{
private int _tileWidth = 100;
private int _tileHeight = 100;
private int _tilesX = 20;
private int _tilesY = 20;
public TestControl()
{
SetStyle(ControlStyles.ResizeRedraw, true);
SetStyle(ControlStyles.UserPaint, true);
SetStyle(ControlStyles.AllPaintingInWmPaint, true);
SetStyle(ControlStyles.Opaque, true);
SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
UpdateStyles();
ResizeRedraw = true;
AutoScrollMinSize = new Size(_tilesX*_tileWidth, _tilesY*_tileHeight);
}
private bool _test = true;
[DefaultValue(true)]
public bool Test
{
get { return _test; }
set
{
if(_test==value) return;
_test = value;
Update();
}
}
[DllImport("user32")]
private static extern IntPtr GetWindowDC(IntPtr hwnd);
struct RECT
{
public int left, top, right, bottom;
}
struct NCCALSIZE_PARAMS
{
public RECT newWindow;
public RECT oldWindow;
public RECT clientWindow;
IntPtr windowPos;
}
int clientPadding = 1;
int actualBorderWidth = 1;
Color borderColor = Color.Black;
protected override void WndProc(ref Message m)
{
//We have to change the clientsize to make room for borders
//if not, the border is limited in how thick it is.
if (m.Msg == 0x83 && _test) //WM_NCCALCSIZE
{
if (m.WParam == IntPtr.Zero)
{
RECT rect = (RECT)Marshal.PtrToStructure(m.LParam, typeof(RECT));
rect.left += clientPadding;
rect.right -= clientPadding;
rect.top += clientPadding;
rect.bottom -= clientPadding;
Marshal.StructureToPtr(rect, m.LParam, false);
}
else
{
NCCALSIZE_PARAMS rects = (NCCALSIZE_PARAMS)Marshal.PtrToStructure(m.LParam, typeof(NCCALSIZE_PARAMS));
rects.newWindow.left += clientPadding;
rects.newWindow.right -= clientPadding;
rects.newWindow.top += clientPadding;
rects.newWindow.bottom -= clientPadding;
Marshal.StructureToPtr(rects, m.LParam, false);
}
}
if (m.Msg == 0x85 && _test) //WM_NCPAINT
{
base.WndProc(ref m);
IntPtr wDC = GetWindowDC(Handle);
using (Graphics g = Graphics.FromHdc(wDC))
{
ControlPaint.DrawBorder(g, new Rectangle(0, 0, Size.Width, Size.Height), borderColor, actualBorderWidth, ButtonBorderStyle.Solid,
borderColor, actualBorderWidth, ButtonBorderStyle.Solid, borderColor, actualBorderWidth, ButtonBorderStyle.Solid,
borderColor, actualBorderWidth, ButtonBorderStyle.Solid);
}
return;
}
base.WndProc(ref m);
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
e.Graphics.FillRectangle(new SolidBrush(BackColor), ClientRectangle);
e.Graphics.TranslateTransform(AutoScrollPosition.X, AutoScrollPosition.Y);
e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
var offsetX = (AutoScrollPosition.X*-1)/_tileWidth;
var offsetY = (AutoScrollPosition.Y*-1)/_tileHeight;
var visibleX = Width/_tileWidth + 2;
var visibleY = Height/_tileHeight + 2;
var x = Math.Min(visibleX + offsetX, _tilesX);
var y = Math.Min(visibleY + offsetY, _tilesY);
for (var i = offsetX; i < x; i++)
{
for (var j = offsetY; j < y; j++)
{
e.Graphics.FillRectangle(Brushes.Beige, new Rectangle(i*_tileWidth, j*_tileHeight, _tileWidth, _tileHeight));
e.Graphics.DrawString(string.Format("{0}:{1}", i, j), Font, Brushes.Black, new Rectangle(i*_tileWidth, j*_tileHeight, _tileWidth, _tileHeight));
}
}
using (var p = new Pen(Color.Black))
{
for (var i = offsetX + 1; i < x; i++)
{
e.Graphics.DrawLine(p, i*_tileWidth, 0, i*_tileWidth, y*_tileHeight);
}
for (var i = offsetY + 1; i < y; i++)
{
e.Graphics.DrawLine(p, 0, i*_tileHeight, x*_tileWidth, i*_tileHeight);
}
}
e.Graphics.FillRectangle(Brushes.White, AutoScrollPosition.X*-1 + 10, AutoScrollPosition.Y*-1 + 10, 35, 14);
e.Graphics.DrawString("TEST", DefaultFont, new SolidBrush(Color.Red), AutoScrollPosition.X*-1 + 10, AutoScrollPosition.Y*-1 + 10);
e.Graphics.TranslateTransform(AutoScrollPosition.X*-1, AutoScrollPosition.Y*-1);
ControlPaint.DrawBorder(e.Graphics, ClientRectangle, Color.Red, actualBorderWidth, ButtonBorderStyle.None,
Color.Red, actualBorderWidth, ButtonBorderStyle.None, Color.Red, actualBorderWidth, ButtonBorderStyle.Solid,
Color.Red, actualBorderWidth, ButtonBorderStyle.Solid);
}
protected override void OnScroll(ScrollEventArgs e)
{
if (DesignMode)
{
base.OnScroll(e);
return;
}
if (e.Type == ScrollEventType.First)
{
LockWindowUpdate(Handle);
}
else
{
LockWindowUpdate(IntPtr.Zero);
Update();
if (e.Type != ScrollEventType.Last) LockWindowUpdate(Handle);
}
}
protected override void OnMouseWheel(MouseEventArgs e)
{
if (VScroll && (ModifierKeys & Keys.Shift) == Keys.Shift)
{
VScroll = false;
LockWindowUpdate(Handle);
base.OnMouseWheel(e);
LockWindowUpdate(IntPtr.Zero);
Update();
VScroll = true;
}
else
{
LockWindowUpdate(Handle);
base.OnMouseWheel(e);
LockWindowUpdate(IntPtr.Zero);
Update();
}
}
[DllImport("user32.dll", SetLastError = true)]
private static extern bool LockWindowUpdate(IntPtr hWnd);
}
Can this flickering be fixed?
I was able to solve my problem by overriding CreateParams:
protected override CreateParams CreateParams
{
[SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)]
get
{
CreateParams cp = base.CreateParams;
cp.ExStyle |= NativeMethods.WS_EX_CONTROLPARENT;
cp.ExStyle &= (~NativeMethods.WS_EX_CLIENTEDGE);
cp.Style &= (~NativeMethods.WS_BORDER);
cp.Style |= NativeMethods.WS_BORDER;
return cp;
}
}
and here is required NativeMethods class:
internal static class NativeMethods
{
public const int WS_EX_CONTROLPARENT = 0x00010000;
public const int WS_EX_CLIENTEDGE = 0x00000200;
public const int WS_BORDER = 0x00800000;
}
below is the result:
You can simply derive from UserControl. It has built-in support for showing scrollbars and also has built-in support for showing borders.
All of built-in features of UserControl can be added to your control which is derived from ScrollableControl but with some additional try and error effort or taking look at source code of UserControl. But using UserControl class you can simply have those features.
Show Border
To show border, it's enough to set its BorderStyle to FixedSingle to get desired feature:
Show Scrollbars
To gain scroll feature, it's enough to set its AutoScroll to true and also set a suitable AutoScrollMinSize for control. Then when the width or height of the control is less than width or height of given size, the suitable scrollbar will be shown.
Custom Border Color
I also suppose you want to have different border color for the control, then it's enough to override WndProc and handle WM_NCPAINT and draw custom border for the control like this:
In above example, I've used the same technique which I used for Changing BorderColor of TextBox with a small change, here I checked if the BorderStyle equals to FixedSingle the I drew the border with desired color.
Enable the designer to act like a Parent Control at design time
If you want to enable it's designer to be able to drop some controls onto your UserControl, it's enough to decorate it with [Designer(typeof(ParentControlDesigner))]. This way, when you drop your UserControl on form, it can host other controls like a panel control. If you don't like this feature, just don't decorate it with that attribute and it will use Control designer by default which doesn't act like a parent control.

c# RichTextBox Border Color

I'm trying to create a custom RichTextBox with border color, but i have a problem...
My border color not showing
Here's my code :
public partial class AlXRichTextBox : RichTextBox
{
private RichTextBox textBox;
private Color borderColor;
public AlXRichTextBox()
{
InitializeComponent();
}
public Color BorderColor
{
get { return borderColor; }
set { borderColor = value; Invalidate(); }
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
Pen p = new Pen(borderColor);
Graphics g = e.Graphics;
int variance = 3;
//g.DrawRectangle(p, new Rectangle(base.Location.X - variance, base.Location.Y - variance, base.Width + variance, base.Height + variance));
ControlPaint.DrawBorder(e.Graphics, base.ClientRectangle, borderColor, ButtonBorderStyle.Solid);
}
private void InitializeComponent()
{
this.textBox = new System.Windows.Forms.RichTextBox();
this.SuspendLayout();
//
// richTextBox1
//
this.textBox.Location = new System.Drawing.Point(0, 0);
this.textBox.Name = "richTextBox1";
this.textBox.Size = new System.Drawing.Size(100, 96);
this.textBox.TabIndex = 0;
this.textBox.Text = "";
this.textBox.Multiline = true;
this.textBox.BorderStyle = BorderStyle.None;
//
// AlXRichTextBox
//
this.Size = new System.Drawing.Size(278, 123);
this.ResumeLayout(false);
}
}
What's problem with this ?
Referring to MSDN article :
Overriding OnPaint will not allow you to modify the appearance of all controls. Those controls that have all of their painting done by Windows (for example, TextBox) never call their OnPaint method, and thus will never use the custom code. Refer to the Help documentation for the particular control you want to modify to see if the OnPaint method is available. For a list of all the Windows Form Controls, see Controls to Use on Windows Forms. If a control does not have OnPaint listed as a member method, you cannot alter its appearance by overriding this method. For more information about custom painting, see Custom Control Painting and Rendering.
However there is a "hack", You can achieve calling the Paint method by calling following code:
private const int WM_PAINT = 15;
protected override void WndProc(ref System.Windows.Forms.Message m)
{
base.WndProc(ref m);
if (m.Msg == WM_PAINT && !inhibitPaint)
{
// raise the paint event
using (Graphics graphic = base.CreateGraphics())
OnPaint(new PaintEventArgs(graphic,
base.ClientRectangle));
}
}
private bool inhibitPaint = false;
public bool InhibitPaint
{
set { inhibitPaint = value; }
}
Src: RichTextBox and UserPaint
Other point is that You cannot draw outside of the Rectangle (which is total size of Your RichTB component. So You actually want to provide him with different Coords (smaller inner ones) and You will draw to the outside.
Your class will look like:
public partial class AlXRichTextBox : RichTextBox
{
private Color borderColor = Color.Red;
public Color BorderColor
{
get { return borderColor; }
set { borderColor = value; Invalidate(); }
}
protected override void OnPaint(PaintEventArgs e)
{
int variance = 3;
e = new PaintEventArgs(e.Graphics, new Rectangle(e.ClipRectangle.X + variance, e.ClipRectangle.Y + variance, e.ClipRectangle.Width - variance, e.ClipRectangle.Height - variance));
base.OnPaint(e);
Pen p = new Pen(borderColor, variance);
Graphics g = e.Graphics;
g.DrawRectangle(p, new Rectangle(e.ClipRectangle.X, e.ClipRectangle.Y, e.ClipRectangle.Width, e.ClipRectangle.Height));
}
private const int WM_PAINT = 15;
protected override void WndProc(ref System.Windows.Forms.Message m)
{
base.WndProc(ref m);
if (m.Msg == WM_PAINT && !inhibitPaint)
{
// raise the paint event
using (Graphics graphic = base.CreateGraphics())
OnPaint(new PaintEventArgs(graphic,
base.ClientRectangle));
}
}
private bool inhibitPaint = false;
public bool InhibitPaint
{
set { inhibitPaint = value; }
}
}
IMPORTANT
As it is not expected for this control to be changed by Paint, You will get "not nice" behavior in regards to the drawing changes like border, new elements etc.. If You would like to use such element, consider using WPF - Windows Presentation Foundation. They are much more nicer to templating the items and modifying design.
A little late answer, but I was on same path as you these days and It got me to this solution, It works for me:
using System;
using System.Drawing;
using System.Windows.Forms;
public class MyRichTextBox : RichTextBox
{
private const UInt32 WM_PAINT = 0x000F;
private const UInt32 WM_USER = 0x0400;
private const UInt32 EM_SETBKGNDCOLOR = (WM_USER + 67);
private const UInt32 WM_KILLFOCUS = 0x0008;
public MyRichTextBox()
{
this.BorderStyle = System.Windows.Forms.BorderStyle.None;
}
protected override void WndProc(ref System.Windows.Forms.Message m)
{
base.WndProc(ref m);
Graphics g = Graphics.FromHwnd(Handle);
Rectangle bounds = new Rectangle(0, 0, Width - 1, Height - 1);
Pen p = new Pen(SystemColors.Highlight, 3);
if (m.Msg == WM_PAINT)
{
if (this.Enabled == true)
{
if (this.Focused)
{
g.DrawRectangle(p, bounds);
}
else
{
g.DrawRectangle(SystemPens.ControlDark, bounds);
}
}
else
{
g.FillRectangle(Brushes.White, bounds);
g.DrawRectangle(SystemPens.Control, bounds);
}
}
if (m.Msg == EM_SETBKGNDCOLOR) //color disabled background
{
Invalidate();
}
if (m.Msg == WM_KILLFOCUS) //set border back to normal on lost focus
{
Invalidate();
}
}
}
This Rich Textbox changes 3 border colors - enabled, focused and disabled with disabled background. As you see the code is simple and short. The only trick is to overide KILL_FOCUS and EM_SETBKGNDCOLOR messages (this one is for changing disabled background), and RichTextbox should be BorderStyle=None. Cheers !

Change ComboBox Border Color in Windows Forms

In My Application i have added Combobox as shown in below picture
i have set the combobox property as
cmbDatefilter.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
And now my question is how to set border style to combobox so that it will look nice.
I verified in below link
Flat style Combo box
My question is different from below link's.
Generic ComboBox in Windows Forms Application
How to override UserControl class to draw a custom border?
You can inherit from ComboBox and override WndProc and handle WM_PAINT message and draw border for your combo box:
using System;
using System.Drawing;
using System.Windows.Forms;
public class FlatCombo : ComboBox
{
private const int WM_PAINT = 0xF;
private int buttonWidth = SystemInformation.HorizontalScrollBarArrowWidth;
Color borderColor = Color.Blue;
public Color BorderColor
{
get { return borderColor; }
set { borderColor = value; Invalidate(); }
}
protected override void WndProc(ref Message m)
{
base.WndProc(ref m);
if (m.Msg == WM_PAINT && DropDownStyle != ComboBoxStyle.Simple)
{
using (var g = Graphics.FromHwnd(Handle))
{
using (var p = new Pen(BorderColor))
{
g.DrawRectangle(p, 0, 0, Width - 1, Height - 1);
var d = FlatStyle == FlatStyle.Popup ? 1 : 0;
g.DrawLine(p, Width - buttonWidth - d,
0, Width - buttonWidth - d, Height);
}
}
}
}
}
Note:
In the above example I used fore color for border, you can add a BorderColor property or use another color.
If you don't like the left border of dropdown button, you can comment that DrawLine method.
You need to draw line when the control is RightToLeft from (0, buttonWidth) to (Height, buttonWidth)
To learn more about how to render a flat combo box, you can take a look at source code of internal ComboBox.FlatComboAdapter class of .Net Framework.
Flat ComboBox
You may also like Flat ComboBox:
CodingGorilla has the right answer, derive your own control from ComboBox and then paint the border yourself.
Here's a working example that paints a 1 pixel wide dark gray border:
class ColoredCombo : ComboBox
{
protected override void OnPaintBackground(PaintEventArgs e)
{
base.OnPaintBackground(e);
using (var brush = new SolidBrush(BackColor))
{
e.Graphics.FillRectangle(brush, ClientRectangle);
e.Graphics.DrawRectangle(Pens.DarkGray, 0, 0, ClientSize.Width - 1, ClientSize.Height - 1);
}
}
}
Normal on the left, my example on the right.
Another option is to draw the border yourself in the Parent control's Paint Event:
Private Sub Panel1_Paint(sender As Object, e As PaintEventArgs) Handles Panel1.Paint
Panel1.CreateGraphics.DrawRectangle(Pens.Black, ComboBox1.Left - 1, ComboBox1.Top - 1, ComboBox1.Width + 1, ComboBox1.Height + 1)
End Sub
-OO-

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?

TabControl and borders visual glitch

I have these visual glitches on every tabControls when I am changing its tabPages BackColor and the BackColor of the form, as illustrated on the following images:
At the top of the tabPage, there is an interior one-pixel white border.
At the left of the tabPage, there is an interior three-pixels white border.
At the bottom of the tabPage, there is an interior one-pixel white border and an exterior two-pixels white border.
At the right of the tabPage, there is an interior one-pixel white border and an exterior two-pixels white border.
Is there a way I can get rid of those white borders?
Here's my attempted hack. I used a NativeWindow to draw over the TabControl to fill in those "white" spaces. I won't claim it's perfect:
public class TabPadding : NativeWindow {
private const int WM_PAINT = 0xF;
private TabControl tabControl;
public TabPadding(TabControl tc) {
tabControl = tc;
tabControl.Selected += new TabControlEventHandler(tabControl_Selected);
AssignHandle(tc.Handle);
}
void tabControl_Selected(object sender, TabControlEventArgs e) {
tabControl.Invalidate();
}
protected override void WndProc(ref Message m) {
base.WndProc(ref m);
if (m.Msg == WM_PAINT) {
using (Graphics g = Graphics.FromHwnd(m.HWnd)) {
//Replace the outside white borders:
if (tabControl.Parent != null) {
g.SetClip(new Rectangle(0, 0, tabControl.Width - 2, tabControl.Height - 1), CombineMode.Exclude);
using (SolidBrush sb = new SolidBrush(tabControl.Parent.BackColor))
g.FillRectangle(sb, new Rectangle(0,
tabControl.ItemSize.Height + 2,
tabControl.Width,
tabControl.Height - (tabControl.ItemSize.Height + 2)));
}
//Replace the inside white borders:
if (tabControl.SelectedTab != null) {
g.ResetClip();
Rectangle r = tabControl.SelectedTab.Bounds;
g.SetClip(r, CombineMode.Exclude);
using (SolidBrush sb = new SolidBrush(tabControl.SelectedTab.BackColor))
g.FillRectangle(sb, new Rectangle(r.Left - 3,
r.Top - 1,
r.Width + 4,
r.Height + 3));
}
}
}
}
}
And to hook it up:
public Form1() {
InitializeComponent();
var tab = new TabPadding(tabControl1);
}
My end result:
you can inherit from control
public class TabControlEx : TabControl
{
protected override void WndProc(ref Message m)
{
if (m.Msg == 0x1300 + 40)
{
RECT rc = (RECT)m.GetLParam(typeof(RECT));
rc.Left -= 0;
rc.Right += 3;
rc.Top -= 0;
rc.Bottom += 3;
Marshal.StructureToPtr(rc, m.LParam, true);
}
base.WndProc(ref m);
}
}
internal struct RECT { public int Left, Top, Right, Bottom; }
I recently ran into this problem and never found a good simple solution. That's when I thought about simply adjusting the control's clipping region. This seemed to work just fine with no noticeable side-effects. The 2 extra white pixels on the right side and the one extra white pixel at the bottom are no longer visible.
class TabControlEx : TabControl
{
protected override void WndProc(ref Message m)
{
if (m.Msg == 0x0005) // WM_SIZE
{
int Width = unchecked((short)m.LParam);
int Height = unchecked((short)((uint)m.LParam >> 16));
// Remove the annoying white pixels on the outside of the tab control
// by adjusting the control's clipping region to exclude the 2 pixels
// on the right and one pixel on the bottom.
Region = new Region(new Rectangle(0, 0, Width - 2, Height - 1));
}
base.WndProc(ref m);
}
}

Categories

Resources