Here you hava a CustomTabControl class that allows you to have disabled tab pages:
Code:
using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
namespace org.mmakers.controls {
/// <summary>
/// Custom tab control that allows its tab pages to be enabled/disabled
/// </summary>
public class CustomTabControl : TabControl {
/// <summary>
/// Default constructor
/// </summary>
public CustomTabControl() : base() {
// Set the draw mode property to owner draw
DrawMode = TabDrawMode.OwnerDrawFixed;
}
/// <summary>
/// Called whenever the control is going to be drawn
/// </summary>
/// <param name="e">The event arguments</param>
protected override void OnDrawItem(DrawItemEventArgs e) {
base.OnDrawItem(e);
TabPage tabPage = TabPages[e.Index];
Rectangle tabRectangle = GetTabRect(e.Index);
if (Alignment == TabAlignment.Left || Alignment == TabAlignment.Right) {
float rotateAngle = 90;
if (Alignment == TabAlignment.Left) {rotateAngle = 270;}
PointF cp = new PointF(tabRectangle.Left + (tabRectangle.Width / 2),tabRectangle.Top + (tabRectangle.Height / 2));
e.Graphics.TranslateTransform(cp.X,cp.Y);
e.Graphics.RotateTransform(rotateAngle);
tabRectangle = new Rectangle(-(tabRectangle.Height / 2),-(tabRectangle.Width / 2),tabRectangle.Height,tabRectangle.Width);
}
using (SolidBrush foreBrush = new SolidBrush(tabPage.ForeColor)) {
using (SolidBrush backBrush = new SolidBrush(tabPage.BackColor)) {
if (!tabPage.Enabled) {foreBrush.Color = SystemColors.GrayText;}
e.Graphics.FillRectangle(backBrush,tabRectangle);
using (StringFormat stringFormat = new StringFormat()) {
stringFormat.Alignment = StringAlignment.Center;
stringFormat.LineAlignment = StringAlignment.Center;
e.Graphics.DrawString(tabPage.Text,e.Font,foreBrush,tabRectangle,stringFormat);
}
}
}
e.Graphics.ResetTransform();
}
/// <summary>
/// Called whenever a tab page is going to be selected
/// </summary>
/// <param name="e">The event arguments</param>
protected override void OnSelecting(TabControlCancelEventArgs e) {
base.OnSelecting(e);
// If tab page is disabled, cancel the event
if (!e.TabPage.Enabled) {e.Cancel = true;}
}
/// <summary>
/// Called whenever a tab page is added to the tab control
/// </summary>
/// <param name="e">The event arguments</param>
protected override void OnControlAdded(ControlEventArgs e) {
// Add a enabled-changed listener to the tab page so we can repaint the tab control
TabPage tabPage = e.Control as TabPage;
if (tabPage != null) {tabPage.EnabledChanged += new EventHandler(tabPage_EnabledChanged);}
base.OnControlAdded(e);
}
/// <summary>
/// Called whenever a tab page is removed from the tab control
/// </summary>
/// <param name="e">The event arguments</param>
protected override void OnControlRemoved(ControlEventArgs e) {
// Remove the enabled-changed listener
TabPage tabPage = e.Control as TabPage;
if (tabPage != null) {tabPage.EnabledChanged -= new EventHandler(tabPage_EnabledChanged);}
base.OnControlRemoved(e);
}
/// <summary>
/// Called whenever the enabled property of a tab page changes
/// </summary>
/// <param name="sender">The event sender object</param>
/// <param name="e">The event arguments</param>
private void tabPage_EnabledChanged(object sender,EventArgs e) {
// Invalidate the tab page title so it's redrawn again
TabPage tabPage = sender as TabPage;
TabControl tabControl = tabPage.Parent as TabControl;
tabControl.Invalidate(tabPage.ClientRectangle);
}
}
}
Maybe it's optimizable in some points, but it works and that was all I needed. When used from the windows designer, I always put the DrawMode property to OwnerDrawFixed (because the WFD will overwrite the property setted at the constructor), but maybe it's not necessary. As maybe it's not necessary to call the base class method in the OnDrawItem() override. When I have some time I will test it.
Any sugerences would be appreciated! ;)