using System;
using System.Collections;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Data;
using System.Windows.Forms;
using System.Drawing.Design;
using System.ComponentModel.Design;
using System.Runtime.InteropServices;
using System.Diagnostics;
using System.IO;
using Toolbox.Library.Forms;
using System.Windows.Forms;
namespace FlatTabControl
{
///
/// Summary description for FlatTabControl.
///
[ToolboxBitmap(typeof(System.Windows.Forms.TabControl))] //,
//Designer(typeof(Designers.FlatTabControlDesigner))]
public class FlatTabControl : System.Windows.Forms.TabControl
{
///
/// Required designer variable.
///
private System.ComponentModel.Container components = null;
private SubClass scUpDown = null;
private bool bUpDown; // true when the button UpDown is required
private ImageList leftRightImages = null;
private const int nMargin = 5;
private Color mBackColor = Color.Empty;
private Color mShadowColor = Color.Empty;
public FlatTabControl()
{
myBackColor = FormThemes.BaseTheme.FormBackColor;
// This call is required by the Windows.Forms Form Designer.
InitializeComponent();
// double buffering
this.SetStyle(ControlStyles.UserPaint, true);
this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
this.SetStyle(ControlStyles.DoubleBuffer, true);
this.SetStyle(ControlStyles.ResizeRedraw, true);
this.SetStyle(ControlStyles.SupportsTransparentBackColor, true);
bUpDown = false;
this.ControlAdded += new ControlEventHandler(FlatTabControl_ControlAdded);
this.ControlRemoved += new ControlEventHandler(FlatTabControl_ControlRemoved);
this.SelectedIndexChanged += new EventHandler(FlatTabControl_SelectedIndexChanged);
leftRightImages = new ImageList();
//leftRightImages.ImageSize = new Size(16, 16); // default
System.Resources.ResourceManager resources = new System.Resources.ResourceManager(typeof(FlatTabControl));
Bitmap updownImage = ((System.Drawing.Bitmap)(resources.GetObject("TabIcons.bmp")));
if (updownImage != null)
{
updownImage.MakeTransparent(Color.White);
leftRightImages.Images.AddStrip(updownImage);
}
Refresh();
}
protected override void OnSizeChanged(EventArgs e)
{
FindUpDown();
UpdateUpDown();
base.OnSizeChanged(e);
}
///
/// Clean up any resources being used.
///
protected override void Dispose( bool disposing )
{
if( disposing )
{
if(components != null)
{
components.Dispose();
}
leftRightImages.Dispose();
}
base.Dispose( disposing );
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
DrawControl(e.Graphics);
}
internal void DrawControl(Graphics g)
{
if (!Visible)
return;
Rectangle TabControlArea = this.ClientRectangle;
Rectangle TabArea = this.DisplayRectangle;
//----------------------------
// fill client area
Brush br = new SolidBrush(mBackColor); //(SystemColors.Control); UPDATED
g.FillRectangle(br, TabControlArea);
br.Dispose();
//----------------------------
//----------------------------
// draw border
int nDelta = SystemInformation.Border3DSize.Width;
Pen border = new Pen(mShadowColor);
TabArea.Inflate(nDelta, nDelta);
g.DrawRectangle(border, TabArea);
border.Dispose();
//----------------------------
//----------------------------
// clip region for drawing tabs
Region rsaved = g.Clip;
Rectangle rreg;
int nWidth = TabArea.Width + nMargin;
if (bUpDown)
{
// exclude updown control for painting
if (Win32.IsWindowVisible(scUpDown.Handle))
{
Rectangle rupdown = new Rectangle();
Win32.GetWindowRect(scUpDown.Handle, ref rupdown);
Rectangle rupdown2 = this.RectangleToClient(rupdown);
nWidth = rupdown2.X;
}
}
rreg = new Rectangle(TabArea.Left, TabControlArea.Top, nWidth - nMargin, TabControlArea.Height);
g.SetClip(rreg);
// draw tabs
for (int i = 0; i < this.TabCount; i++)
DrawTab(g, this.TabPages[i], i);
g.Clip = rsaved;
//----------------------------
//----------------------------
// draw background to cover flat border areas
if (this.SelectedTab != null)
{
TabPage tabPage = this.SelectedTab;
tabPage.BackColor = Toolbox.Library.Forms.FormThemes.BaseTheme.TabPageActive;
Color color = tabPage.BackColor;
border = new Pen(color);
TabArea.Offset(1, 1);
TabArea.Width -= 2;
TabArea.Height -= 2;
g.DrawRectangle(border, TabArea);
TabArea.Width -= 1;
TabArea.Height -= 1;
g.DrawRectangle(border, TabArea);
border.Dispose();
}
//----------------------------
}
private const int WM_SETREDRAW = 11;
[DllImport("user32.dll")]
public static extern int SendMessage(IntPtr hWnd, Int32 wMsg, bool wParam, Int32 lParam);
private void UpdateTabColor()
{
foreach (TabPage tpCheck in TabPages)
{
tpCheck.BackColor = Toolbox.Library.Forms.FormThemes.BaseTheme.TabPageInactive;
tpCheck.ForeColor = Toolbox.Library.Forms.FormThemes.BaseTheme.DisabledItemColor;
}
if (SelectedTab != null)
{
SelectedTab.BackColor = Toolbox.Library.Forms.FormThemes.BaseTheme.TabPageActive;
SelectedTab.ForeColor = Toolbox.Library.Forms.FormThemes.BaseTheme.TextForeColor;
}
this.Refresh();
}
internal void DrawTab(Graphics g, TabPage tabPage, int nIndex)
{
Rectangle recBounds = this.GetTabRect(nIndex);
RectangleF tabTextArea = (RectangleF)this.GetTabRect(nIndex);
bool bSelected = (this.SelectedIndex == nIndex);
Point[] pt = new Point[7];
if (this.Alignment == TabAlignment.Top)
{
pt[0] = new Point(recBounds.Left, recBounds.Bottom);
pt[1] = new Point(recBounds.Left, recBounds.Top + 3);
pt[2] = new Point(recBounds.Left + 3, recBounds.Top);
pt[3] = new Point(recBounds.Right - 3, recBounds.Top);
pt[4] = new Point(recBounds.Right, recBounds.Top + 3);
pt[5] = new Point(recBounds.Right, recBounds.Bottom);
pt[6] = new Point(recBounds.Left, recBounds.Bottom);
}
else
{
pt[0] = new Point(recBounds.Left, recBounds.Top);
pt[1] = new Point(recBounds.Right, recBounds.Top);
pt[2] = new Point(recBounds.Right, recBounds.Bottom - 3);
pt[3] = new Point(recBounds.Right - 3, recBounds.Bottom);
pt[4] = new Point(recBounds.Left + 3, recBounds.Bottom);
pt[5] = new Point(recBounds.Left, recBounds.Bottom - 3);
pt[6] = new Point(recBounds.Left, recBounds.Top);
}
//----------------------------
// fill this tab with background color
Brush br = new SolidBrush(tabPage.BackColor);
g.FillPolygon(br, pt);
br.Dispose();
//----------------------------
//----------------------------
// draw border
//g.DrawRectangle(SystemPens.ControlDark, recBounds);
g.DrawPolygon(new Pen(Color.FromArgb(30,30,30)), pt);
if (bSelected)
{
//----------------------------
// clear bottom lines
Pen pen = new Pen(tabPage.BackColor);
switch (this.Alignment)
{
case TabAlignment.Top:
g.DrawLine(pen, recBounds.Left + 1, recBounds.Bottom, recBounds.Right - 1, recBounds.Bottom);
g.DrawLine(pen, recBounds.Left + 1, recBounds.Bottom+1, recBounds.Right - 1, recBounds.Bottom+1);
break;
case TabAlignment.Bottom:
g.DrawLine(pen, recBounds.Left + 1, recBounds.Top, recBounds.Right - 1, recBounds.Top);
g.DrawLine(pen, recBounds.Left + 1, recBounds.Top-1, recBounds.Right - 1, recBounds.Top-1);
g.DrawLine(pen, recBounds.Left + 1, recBounds.Top-2, recBounds.Right - 1, recBounds.Top-2);
break;
}
pen.Dispose();
//----------------------------
}
//----------------------------
//----------------------------
// draw tab's icon
if ((tabPage.ImageIndex >= 0) && (ImageList != null) && (ImageList.Images[tabPage.ImageIndex] != null))
{
int nLeftMargin = 8;
int nRightMargin = 2;
Image img = ImageList.Images[tabPage.ImageIndex];
Rectangle rimage = new Rectangle(recBounds.X + nLeftMargin, recBounds.Y + 1, img.Width, img.Height);
// adjust rectangles
float nAdj = (float)(nLeftMargin + img.Width + nRightMargin);
rimage.Y += (recBounds.Height - img.Height) / 2;
tabTextArea.X += nAdj;
tabTextArea.Width -= nAdj;
// draw icon
g.DrawImage(img, rimage);
}
//----------------------------
//----------------------------
// draw string
StringFormat stringFormat = new StringFormat();
stringFormat.Alignment = StringAlignment.Center;
stringFormat.LineAlignment = StringAlignment.Center;
br = new SolidBrush(tabPage.ForeColor);
g.DrawString(tabPage.Text, Font, br, tabTextArea, stringFormat);
//----------------------------
}
internal void DrawIcons(Graphics g)
{
if ((leftRightImages == null) || (leftRightImages.Images.Count != 4))
return;
//----------------------------
// calc positions
Rectangle TabControlArea = this.ClientRectangle;
Rectangle r0 = new Rectangle();
Win32.GetClientRect(scUpDown.Handle, ref r0);
Brush br = new SolidBrush(mBackColor);
g.FillRectangle(br, r0);
br.Dispose();
Pen border = new Pen(mShadowColor);
Rectangle rborder = r0;
rborder.Inflate(-1, -1);
g.DrawRectangle(border, rborder);
border.Dispose();
int nMiddle = (r0.Width / 2);
int nTop = (r0.Height - 16) / 2;
int nLeft = (nMiddle - 16) / 2;
Rectangle r1 = new Rectangle(nLeft, nTop, 16, 16);
Rectangle r2 = new Rectangle(nMiddle+nLeft, nTop, 16, 16);
//----------------------------
//----------------------------
// draw buttons
Image img = leftRightImages.Images[1];
if (img != null)
{
if (this.TabCount > 0)
{
Rectangle r3 = this.GetTabRect(0);
if (r3.Left < TabControlArea.Left)
g.DrawImage(img, r1);
else
{
img = leftRightImages.Images[3];
if (img != null)
g.DrawImage(img, r1);
}
}
}
img = leftRightImages.Images[0];
if (img != null)
{
if (this.TabCount > 0)
{
Rectangle r3 = this.GetTabRect(this.TabCount - 1);
if (r3.Right > (TabControlArea.Width - r0.Width))
g.DrawImage(img, r2);
else
{
img = leftRightImages.Images[2];
if (img != null)
g.DrawImage(img, r2);
}
}
}
//----------------------------
}
protected override void OnCreateControl()
{
base.OnCreateControl();
FindUpDown();
}
private void FlatTabControl_ControlAdded(object sender, ControlEventArgs e)
{
FindUpDown();
UpdateUpDown();
UpdateTabColor();
}
private void FlatTabControl_ControlRemoved(object sender, ControlEventArgs e)
{
FindUpDown();
UpdateUpDown();
}
private void FlatTabControl_SelectedIndexChanged(object sender, EventArgs e)
{
UpdateUpDown();
Invalidate(); // we need to update border and background colors
}
private void FindUpDown()
{
bool bFound = false;
// find the UpDown control
IntPtr pWnd = Win32.GetWindow(this.Handle, Win32.GW_CHILD);
while (pWnd != IntPtr.Zero)
{
//----------------------------
// Get the window class name
char[] className = new char[33];
int length = Win32.GetClassName(pWnd, className, 32);
string s = new string(className, 0, length);
//----------------------------
if (s == "msctls_updown32")
{
bFound = true;
if (!bUpDown)
{
//----------------------------
// Subclass it
this.scUpDown = new SubClass(pWnd, true);
this.scUpDown.SubClassedWndProc += new SubClass.SubClassWndProcEventHandler(scUpDown_SubClassedWndProc);
//----------------------------
bUpDown = true;
}
break;
}
pWnd = Win32.GetWindow(pWnd, Win32.GW_HWNDNEXT);
}
if ((!bFound) && (bUpDown))
bUpDown = false;
}
private void UpdateUpDown()
{
if (bUpDown)
{
if (Win32.IsWindowVisible(scUpDown.Handle))
{
Rectangle rect = new Rectangle();
Win32.GetClientRect(scUpDown.Handle, ref rect);
Win32.InvalidateRect(scUpDown.Handle, ref rect, true);
}
}
}
#region scUpDown_SubClassedWndProc Event Handler
private int scUpDown_SubClassedWndProc(ref Message m)
{
switch (m.Msg)
{
case Win32.WM_PAINT:
{
//------------------------
// redraw
IntPtr hDC = Win32.GetWindowDC(scUpDown.Handle);
Graphics g = Graphics.FromHdc(hDC);
DrawIcons(g);
g.Dispose();
Win32.ReleaseDC(scUpDown.Handle, hDC);
//------------------------
// return 0 (processed)
m.Result = IntPtr.Zero;
//------------------------
// validate current rect
Rectangle rect = new Rectangle();
Win32.GetClientRect(scUpDown.Handle, ref rect);
Win32.ValidateRect(scUpDown.Handle, ref rect);
//------------------------
}
return 1;
}
return 0;
}
#endregion
#region Component Designer generated code
///
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
///
private void InitializeComponent()
{
this.SuspendLayout();
//
// FlatTabControl
//
this.Selected += new System.Windows.Forms.TabControlEventHandler(this.FlatTabControl_Selected);
this.ResumeLayout(false);
}
#endregion
#region Properties
[Editor(typeof(TabpageExCollectionEditor), typeof(UITypeEditor))]
public new TabPageCollection TabPages
{
get
{
return base.TabPages;
}
}
new public TabAlignment Alignment
{
get {return base.Alignment;}
set {
TabAlignment ta = value;
if ((ta != TabAlignment.Top) && (ta != TabAlignment.Bottom))
ta = TabAlignment.Top;
base.Alignment = ta;}
}
[Browsable(false)]
new public bool Multiline
{
get {return base.Multiline;}
set {base.Multiline = false;}
}
[Browsable(true)]
new public Color myBackColor
{
get {return mBackColor;}
set {mBackColor = value; this.Invalidate();}
}
#endregion
#region TabpageExCollectionEditor
internal class TabpageExCollectionEditor : CollectionEditor
{
public TabpageExCollectionEditor(System.Type type): base(type)
{
}
protected override Type CreateCollectionItemType()
{
return typeof(TabPage);
}
}
#endregion
private void FlatTabControl_Selected(object sender, TabControlEventArgs e)
{
foreach (TabPage tpCheck in TabPages)
{
tpCheck.BackColor = Toolbox.Library.Forms.FormThemes.BaseTheme.TabPageInactive;
tpCheck.ForeColor = Toolbox.Library.Forms.FormThemes.BaseTheme.DisabledItemColor;
}
if (SelectedTab != null)
{
SelectedTab.BackColor = Toolbox.Library.Forms.FormThemes.BaseTheme.TabPageActive;
SelectedTab.ForeColor = Toolbox.Library.Forms.FormThemes.BaseTheme.TextForeColor;
}
}
}
//#endregion
}