المساعد الشخصي الرقمي

مشاهدة النسخة كاملة : Owner drawn TabControl doesn't act as I want it



C# Programming
10-18-2009, 12:50 AM
Hey guys.

So, my owner drawn TabControl, inheriting from the TabControl in System.Windows.Forms, doesn't want to give me a transparent background. (Or I simply don't know how) It's also giving me these weird gaps, and somehow it's not filling out all the space in my Panel parent.

Here's a screenshot: http://tinypic.com/r/1tou9h/4

using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Design;
using System.IO;
using System.Linq;
using System.Runtime;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows.Forms;

using Storm;
using Storm.Docking;
using Storm.Docking.Controls;
using Storm.Docking.Visual;
using Storm.Docking.Visual.Drawing;
using Storm.Docking.Visual.Glyphs;
using Storm.Docking.Win32;

namespace Storm.Docking.Visual
{
#region TabMouseEventArgs

///
/// Class containing information about a Tab mouse event.
///
public class TabMouseEventArgs
: EventArgs
{
#region Fields

private TabPage _tabPage = null;

#endregion

#region Properties

///
/// Gets or sets the TabPage associated with the TabMouseEventArgs.
///
[Browsable(false)]
[Description("Gets or sets the TabPage associated with the TabMouseEventArgs.")]
public TabPage TabPage
{
get { return _tabPage; }
set { _tabPage = value; }
}

#endregion

///
/// Initializes a new instance of TabMouseEventArgs.
///
public TabMouseEventArgs()
{
}

///
/// Initializes a new instance of TabMouseEventArgs.
///
/// TabPage associated with the TabMouseEventArgs.
public TabMouseEventArgs(TabPage page)
{
this.TabPage = page;
}
}

#endregion

///
/// Represents a TabControl in which the visible Form can be
/// changed by changing the SelectedTab.
///
public class DockTab
: TabControl
{
#region Fields

private int _hoverIndex = -1;
private StringFormat _stringFormat = null;

private DockRenderer _renderer = null;
private DockPanel _dockPanel = null;
private DockPane _dockPane = null;

#region Events

///
/// Occurs when the user's mouse enters a Tab.
///
public event TabMouseEventHandler TabMouseEnter;

///
/// Occurs when the user's mouse leaves a Tab.
///
public event TabMouseEventHandler TabMouseLeave;

#endregion

#region Delegates

///
/// Represents the method that will handle the TabMouseEnter
/// event or the TabMouseLeave event.
///
/// Sender object.
/// TabMouseEventArgs.
public delegate void TabMouseEventHandler(object sender, TabMouseEventArgs e);

#endregion

#endregion

#region Properties

///
/// Gets or sets the DockRenderer of the DockTab.
///
[Browsable(false)]
[Description("Gets or sets the DockRenderer of the DockTab.")]
public DockRenderer Renderer
{
get { return _renderer; }
set
{
_renderer = value;
this.Invalidate();
}
}

///
/// Gets the index of the tab the user is currently hovering
/// over with the mouse.
///
[Browsable(false)]
[Description("Gets the index of the tab the user is currently hovering over with the mouse.")]
public int HoverIndex
{
get { return _hoverIndex; }
}

///
/// Gets the StringFormat used to draw the TabPages' text.
///
[Browsable(false)]
[Description("Gets the StringFormat used to draw the TabPages' text.")]
public StringFormat StringFormat
{
get { return _stringFormat; }
}

///
/// Gets or sets the parent DockPanel.
///
[Browsable(true)]
[Description("Gets or sets the parent DockPanel.")]
public DockPanel DockPanel
{
get { return _dockPanel; }
set
{
_dockPanel = value;

// Update the DockPanel/DockPane fields of the
// DockCaption to make sure the DockCaption is
// where it should be.

_dockPanel.Controls.Add(this);
this.Parent = _dockPanel;

if (_dockPanel.DockPane != null)
_dockPane = _dockPanel.DockPane;
}
}

///
/// Gets the parent DockPane.
///
[Browsable(false)]
[Description("Gets the parent DockPane.")]
public DockPane DockPane
{
get { return _dockPane; }
}

#endregion

#region Methods

#region Internal

///
/// Calls InvokePaint and InvokePaintBackground.
///
/// Control for the invokes.
/// PaintEventArgs for the invokes.
internal void InvokePaintAll(Control c, PaintEventArgs e)
{
this.InvokePaint(c, e);
this.InvokePaintBackground(c, e);
}

#endregion

#region Protected

protected override void OnPaint(PaintEventArgs e)
{
this.Renderer.TabPaintBackground(this, e.Graphics);
for (int i = 0; i < this.TabCount; i++)
{
this.Renderer.TabDrawTab(this, e.Graphics,
this.TabPages[i], i);
}

base.OnPaint(e);
}

protected override void OnPaintBackground(PaintEventArgs pevent)
{
this.Renderer.TabPaintBackground(this,
pevent.Graphics);
}

protected override void OnMouseMove(MouseEventArgs e)
{
bool foundItem = false;
int index = -1;
foreach (TabPage page in this.TabPages)
{
index++;
if (this.GetTabRect(index).Contains
(e.********) == true)
{
_hoverIndex = index;
this.Invalidate();
foundItem = true;

if (this.TabMouseEnter != null)
{
TabMouseEventArgs tabArgs = new TabMouseEventArgs();
tabArgs.TabPage = page;

this.TabMouseEnter(this, tabArgs);
}
}
else if (foundItem == false)
{
_hoverIndex = -1;
this.Invalidate();

if (this.TabMouseLeave != null)
{
TabMouseEventArgs tabArgs = new TabMouseEventArgs();
tabArgs.TabPage = page;

this.TabMouseLeave(this, tabArgs);
}
}
}

base.OnMouseMove(e);
}

protected override void OnMouseLeave(EventArgs e)
{
_hoverIndex = -1; // Reset HoverIndex.
this.Invalidate();

if (this.TabMouseLeave != null)
{
TabMouseEventArgs tabArgs = new TabMouseEventArgs();
tabArgs.TabPage = null;

this.TabMouseLeave(this, tabArgs);
}

base.OnMouseLeave(e);
}

#endregion

#endregion

///
/// Initializes a new instance of DockTab.
///
public DockTab()
{
_renderer = new DockRenderer();

// Call SetStyle multiple times to prevent flickering.

this.SetStyle(ControlStyles.UserPaint, true);
this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
this.SetStyle(ControlStyles.ResizeRedraw, true);
this.SetStyle(ControlStyles.SupportsTransparentBackColor, true);

// Setup the settings of the base TabControl.
this.Dock = DockStyle.Fill;
this.BackColor = this.Renderer.DockColorTable.TabBodyBackColor;
this.Font = this.Renderer.DockColorTable.PaneFont;
this.Alignment = TabAlignment.Bottom;

// Initialize the StringFormat that we use for drawing
// text on the tabs.

_stringFormat = new StringFormat();
_stringFormat.Alignment = StringAlignment.Center;
_stringFormat.LineAlignment = StringAlignment.Center;
}
}
}


using System;
using System.Collections;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Design;
using System.Linq;
using System.Text;
using System.Windows.Forms;

using Storm;
using Storm.Docking;
using Storm.Docking.Controls;
using Storm.Docking.Visual;
using Storm.Docking.Visual.Drawing;
using Storm.Docking.Visual.Glyphs;
using Storm.Docking.Win32;

namespace Storm.Docking.Visual.Drawing
{
///
/// Class used for drawing all Controls in a DockPane.
///
public class DockRenderer
{
#region Fields

private DockColorTable _colorTable = null;

#endregion

#region Properties

///
/// Gets or sets the color table of the DockRenderer.
///
public virtual DockColorTable DockColorTable
{
get { return _colorTable; }
set { _colorTable = value; }
}

#endregion

#region Methods

#region Public

#region DockCaption

public virtual void CaptionDrawBar(DockCaption c, Graphics g)
{
Color startColor = DockColorTable.CaptionNormalColorStart;
Color endColor = DockColorTable.CaptionNormalColorEnd;
Color textColor = DockColorTable.CaptionNormalTextForeColor;

if (c.Focused == true)
{
startColor = DockColorTable.CaptionFocusColorStart;
endColor = DockColorTable.CaptionFocusColorEnd;
textColor = DockColorTable.CaptionFocusTextForeColor;
}

LinearGradientBrush brush = new LinearGradientBrush
(c.Bounds.********, new Point(c.Bounds.
********.X, c.Bounds.********.Y +
c.Size.Height), startColor, endColor);

float diameter = DockColorTable.CaptionRadius * 2.0F;
SizeF sizeF = new SizeF(diameter, diameter);

GraphicsPath path = new GraphicsPath();
RectangleF arc = new RectangleF(new PointF
(c.********.X, c.********.Y), sizeF);

// We have created our arc Rectangle - start
// creating the GraphicsPath.

// Top left arc.

path.AddArc(arc, 180, 90);

// Top right arc.

arc.X = c.Bounds.Right - diameter;
path.AddArc(arc, 270, 90);

// Base rectangle.

path.AddRectangle(new Rectangle(new Point((int)path.
PathPoints[0].X, (int)path.PathPoints[0].Y),
c.Size));

// Finally close the path and draw it.

path.CloseFigure();

g.FillPath(brush, path);
g.DrawPath(BrushStack.GetPen(DockColorTable
.CaptionBorderColor), path);

// We will then draw our text. We use Graphics
// drawing for this instead of a Label because
// Labels block MouseDown events.

// First calculate the place that the text
// should be placed - we want the text to
// be placed in the left side of the
// DockCaption, so position it there.

PointF textPoint = new PointF(c.********.X + 1,
c.********.Y + (c.Size.Height / 2)
- (c.Font.GetHeight() / 2));

g.DrawString(c.CaptionText, c.Font,
BrushStack.GetBrush(textColor), textPoint);
}

#endregion

#region DockTab

public virtual void TabPaintBackground(DockTab t, Graphics g)
{
t.ClientRectangle.Offset(t.********);
PaintEventArgs e = new PaintEventArgs(g, t.ClientRectangle);
GraphicsState state = g.Save();
g.SmoothingMode = SmoothingMode.AntiAlias;

try
{
g.TranslateTransform((float)-t.********.X,
(float)-t.********.Y);

t.InvokePaintAll(t.Parent, e);
}
finally
{
g.Restore(state);
t.ClientRectangle.Offset(-t.********.X, -t.********.Y);
}
}

public virtual void TabDrawTab(DockTab t, Graphics g, TabPage tabPage, int index)
{
Rectangle recBounds = t.GetTabRect(index);
RectangleF tabTextArea = (RectangleF)t.GetTabRect(index);
RectangleF tabArea = tabTextArea;

Color tabColorStart = DockColorTable.TabNormalBackColorStart;
Color tabColorEnd = DockColorTable.TabNormalBackColorEnd;
Color tabBorderColor = DockColorTable.TabNormalBorderColor;
Color textColor = DockColorTable.TabNormalForeColor;

bool selected = t.SelectedIndex == index;
bool hovering = t.HoverIndex == index && selected == false;
if (selected == true)
{
// Update the earlier specified Colors to match that
// the tab is focused instead of normal.

tabColorStart = DockColorTable.TabFocusBackColorStart;
tabColorEnd = DockColorTable.TabFocusBackColorEnd;
tabBorderColor = DockColorTable.TabFocusBorderColor;
textColor = DockColorTable.TabFocusForeColor;
}

if (hovering == true)
{
// Update the earlier specified Colors to match that
// the tab is hovered over instead of normal.

tabColorStart = DockColorTable.TabHoverBackColorStart;
tabColorEnd = DockColorTable.TabHoverBackColorEnd;
tabBorderColor = DockColorTable.TabHoverBorderColor;
textColor = DockColorTable.TabHoverForeColor;
}

// Now that our Colors has been setup, we will start
// drawing the tab.

Rectangle rect = new Rectangle(new Point((int)tabArea.X,
(int)tabArea.Y), new Size((int)tabArea.Size.Width - 1,
(int)tabArea.Size.Height - 4));

LinearGradientBrush brush = new LinearGradientBrush
(rect, tabColorStart, tabColorEnd, 90f);

g.FillRoundedRectangle(brush, rect, (int)DockColorTable.
TabRadius, RectangleEdgeFilter.BottomLeft |
RectangleEdgeFilter.BottomRight);

g.DrawRoundedRectangle(BrushStack.GetPen(tabBorderColor),
rect, (int)DockColorTable.TabRadius,
RectangleEdgeFilter.BottomLeft | RectangleEdgeFilter.
BottomRight);

if ((tabPage.ImageIndex >= 0) && (t.ImageList != null) &&
(t.ImageList.Images[tabPage.ImageIndex] != null))
{
int leftMargin = 8;
int rightMargin = 2;

Image image = t.ImageList.Images[tabPage.ImageIndex];
Rectangle imageBounds = new Rectangle(recBounds.X +
leftMargin, recBounds.Y + 1,
image.Width, image.Height);

float adjust = (float)(leftMargin + image.Width +
rightMargin);

imageBounds.Y += (recBounds.Height - image.Height) / 2;
tabArea.X += adjust;
tabArea.Width -= adjust;

g.DrawImage(image, imageBounds);
}

Brush textBrush = BrushStack.GetBrush(textColor);
g.DrawString(tabPage.Text, t.Font, textBrush,
tabTextArea, t.StringFormat);
}

#endregion

#region Glyph

///
/// Draws the Glyph as if the cursor was hovering over it.
///
/// Graphics to draw with.
public virtual void GlyphDrawHover(Glyph glyph, Graphics g)
{
Color penColor = DockColorTable.GlyphNormalBorderColor;
Color fillColorStart = DockColorTable.GlyphNormalFillColorStart;
Color fillColorEnd = DockColorTable.GlyphNormalFillColorEnd;
int radius = 2;

if (glyph.DockCaption.Focused == true)
{
penColor = DockColorTable.GlyphHoverBorderColor;
fillColorStart = DockColorTable.GlyphHoverFillColorStart;
fillColorEnd = DockColorTable.GlyphHoverFillColorEnd;
}

LinearGradientBrush brush = new LinearGradientBrush(glyph.GlyphRect,
fillColorStart, fillColorEnd, LinearGradientMode.Vertical);

g.SmoothingMode = SmoothingMode.HighQuality;
g.FillRoundedRectangle(brush, glyph.GlyphRect, radius);
Rectangle borderRect = glyph.GlyphRect;

borderRect.Width--;
borderRect.Height--;

g.DrawRoundedRectangle(BrushStack.GetPen(penColor),
borderRect, radius);
}

///
/// Draws the Glyph as if the mouse had clicked it.
///
/// Graphics to draw with.
public virtual void GlyphDrawPressed(Glyph glyph, Graphics g)
{
Color penColor = DockColorTable.GlyphPressedBorderColor;
Color fillColorStart = DockColorTable.GlyphPressedFillColorStart;
Color fillColorEnd = DockColorTable.GlyphPressedFillColorEnd;
int radius = 2;

LinearGradientBrush brush = new LinearGradientBrush(glyph.GlyphRect,
fillColorStart, fillColorEnd, LinearGradientMode.Vertical);

g.SmoothingMode = SmoothingMode.HighQuality;
g.FillRoundedRectangle(brush, glyph.GlyphRect, radius);
Rectangle borderRect = glyph.GlyphRect;

borderRect.Width--;
borderRect.Height--;

g.DrawRoundedRectangle(BrushStack.GetPen(penColor),
borderRect, radius);
}

#endregion

#endregion

#endregion

///
/// Initializes a new instance of DockRenderer.
///
public DockRenderer()
{
_colorTable = new DockColorTable();
}
}
}