I've played around with OwnerDrawFixed and it works. The problem is I
want my code to run after the original DrawItem, not instead of it.
Otherwise I have to deal with text alignment, rotation, yuck.
Below is what I have so far. I still need to rotate the text on
left-aligned tabs by 180 degrees and don't know how to do that.
public class myTC: TabControl
{
public myTC()
{
DrawMode = TabDrawMode.OwnerDrawFixed;
DrawItem += new DrawItemEventHandler(myTC_DrawItem);
MouseUp += new MouseEventHandler(myTC_MouseUp);
Padding += new Size(10,0);
}
private Rectangle buttonRect(Rectangle r)
{
switch(Alignment)
{
case(TabAlignment.Top):
case(TabAlignment.Bottom):
return new Rectangle(r.X + r.Width-12, r.Y + 5, 10, 10);
case(TabAlignment.Right):
case(TabAlignment.Left):
return new Rectangle(r.X + 5, r.Y + r.Height-12, 10, 10);
default:
System.Diagnostics.Debug.Fail("bad TabAlignment");
return new Rectangle(-1,-1,-1,-1);
}
}
private void myTC_DrawItem(object sender, DrawItemEventArgs e)
{
int index = e.Index;
TabPage tp = TabPages[index];
Rectangle r = GetTabRect(index);
StringFormat sf = StringFormat.GenericDefault;
if(Alignment == TabAlignment.Right || Alignment == TabAlignment.Left)
sf.FormatFlags |= StringFormatFlags.DirectionVertical;
e.Graphics.DrawString(tp.Text, Font, new SolidBrush(tp.ForeColor), r,
sf);
ControlPaint.DrawButton(e.Graphics, buttonRect(r), ButtonState.Pushed);
}
private void myTC_MouseUp(object sender, MouseEventArgs e)
{
for(int p=0; p<TabPages.Count; p++)
{
Rectangle r = GetTabRect(p);
if(buttonRect(r).Contains(e.X, e.Y))
TabPages.RemoveAt(p);
}
}
}
Uri,
If you want the button on the tab itself, then you probably will need to use
the 'owner draw' facility. Override the OnDrawItem method or handle the
DrawItem event.
You can use the System.Windows.Forms.ControlPaint to actually draw a button,
there are different methods to draw different kinds of buttons.
However I do not have a clear example of using Owner Draw with a tab
control.
Hope this helps
Jay
Thanks for the input, Jay.
I can't seem to put a button on the tab - I mean the actual tab, not the
page attached to it. To make myself clear: If there are 5 pages on a tab
control, I want to see 5 close buttons.
I'm currently toying with code like this, although I really don't want
to (for obvious reasons):
public class Class1 : TabPage
{
protected override void InitLayout()
{
base.InitLayout ();
Button b = new Button();
b.Text = "a";
b.Location = new Point(15,15);
this.Parent.Parent.Controls.Add(b);
b.BringToFront();
}
}
I also tried handling OnClick, assuming I could somehow draw over the
tab (GDI+), but that event is only triggered when the page, not the tab,
is clicked.
Jay B. Harlow [MVP - Outlook] wrote:
Uri,
Do you mean you have a tab control with 5 pages. There is a button on
each
page that when clicked that page closes (disappears)?
I would inherit from TabPage and put a button on it. The click event of
the
button would remove the tab page from the parents (tabcontrol) tabpages
collection, as the TabPage.Visible property doesn't actually do
anything.
Hope this helps
Jay
Hi,
Maybe it's just me, but I think my application needs TabPages which can
each be closed by clicking a "X" (close) button on the tab itself. The
thing is, I couldn't find such a TabPage - not by tweaking the tabpage
styles and not by looking for a 3rd part library.
Does anyone know of such a component? Or have an idea on how to write
one (extending TabControl?)
thx
Uri