C# 使用GDI+绘制漂亮的ToolStrip和StatusStrip皮肤(转载)
原文地址:http://www.csharpwin.com/csharpresource/9168r2278.shtml
在文章的开始先感谢John(杨剑)为我写了这篇文章,因为我写好代码后忙得没时间写文章了:)。
在上一篇文章《C# 使用GDI+绘制漂亮的MenuStrip和ContextMenuStrip皮肤》中,只实现了MenuStrip和ContextMenuStrip菜单的美化,这篇文章接着介绍ToolStrip系列控件的另两个控件:工具栏控件(ToolStrip)和状态栏控件(StatusStrip)的美化。
前面介绍和实现了菜单的换肤,通过重写抽象类ToolStripRenderer中提供的函数,然后在Form中设置System.Windows.Forms.ToolStripManager.Renderer = new ProfessionalToolStripRendererEx();即可完成对Form中所有Strip对象的重绘。如果仅仅需重绘某个Strip对象,只需单独设置其Renderer属性即可。而重绘ToolStrip和StatusStrip与其类似,只需在ProfessionalToolStripRendererEx中多重写几个函数即可。还是先看下美化后的效果:
工具栏控件(ToolStrip)和状态栏控件(StatusStrip)的美化比菜单的美化主要是需要对ToolStripButton,ToolStripDropDwonButton和ToolStripSplitButton的美化,主要重载ToolStripRenderer中的几个相应的函数就行了。下面就来介绍相应的函数:
(1)实现对ToolStripButton的美化,主要是针对背景图像、Check状态以及鼠标进入、按下和离开时绘制不同的显示效果。看下具体绘制的方法:
protected override void OnRenderButtonBackground(
ToolStripItemRenderEventArgs e)
{
ToolStrip toolStrip = e.ToolStrip;
ToolStripButton item = e.Item as ToolStripButton;
Graphics g = e.Graphics;
if (item != null)
{
LinearGradientMode mode =
toolStrip.Orientation == Orientation.Horizontal ?
LinearGradientMode.Vertical : LinearGradientMode.Horizontal;
SmoothingModeGraphics sg = new SmoothingModeGraphics(g);
Rectangle bounds = new Rectangle(Point.Empty, item.Size);
if (item.BackgroundImage != null)
{
Rectangle clipRect = item.Selected ? item.ContentRectangle : bounds;
ControlPaintEx.DrawBackgroundImage(
g,
item.BackgroundImage,
ColorTable.BackNormal,
item.BackgroundImageLayout,
bounds,
clipRect);
}
if (item.CheckState == CheckState.Unchecked)
{
if (item.Selected)
{
Color color = ColorTable.BackHover;
if (item.Pressed)
{
color = ColorTable.BackPressed;
}
RenderHelper.RenderBackgroundInternal(
g,
bounds,
color,
ColorTable.Border,
ColorTable.BackNormal,
RoundStyle.All,
true,
true,
mode);
}
else
{
if (toolStrip is ToolStripOverflow)
{
using (Brush brush = new SolidBrush(ColorTable.BackHover))
{
g.FillRectangle(brush, bounds);
}
}
}
}
else
{
Color color = ControlPaint.Light(ColorTable.BackHover);
if (item.Selected)
{
color = ColorTable.BackHover;
}
if (item.Pressed)
{
color = ColorTable.BackPressed;
}
RenderHelper.RenderBackgroundInternal(
g,
bounds,
color,
ColorTable.Border,
ColorTable.BackNormal,
RoundStyle.All,
true,
true,
mode);
}
sg.Dispose();
}
}
(2)对ToolStripDropDownButton、ToolStripSliptButton的重绘与ToolStripButton类似,代码如下:
protected override void OnRenderDropDownButtonBackground(
ToolStripItemRenderEventArgs e)
{
ToolStrip toolStrip = e.ToolStrip;
ToolStripDropDownItem item = e.Item as ToolStripDropDownItem;
if (item != null)
{
LinearGradientMode mode =
toolStrip.Orientation == Orientation.Horizontal ?
LinearGradientMode.Vertical : LinearGradientMode.Horizontal;
Graphics g = e.Graphics;
SmoothingModeGraphics sg = new SmoothingModeGraphics(g);
Rectangle bounds = new Rectangle(Point.Empty, item.Size);
if (item.Pressed && item.HasDropDownItems)
{
RenderHelper.RenderBackgroundInternal(
g,
bounds,
ColorTable.BackPressed,
ColorTable.Border,
ColorTable.BackNormal,
RoundStyle.All,
true,
true,
mode);
}
else if (item.Selected)
{
RenderHelper.RenderBackgroundInternal(
g,
bounds,
ColorTable.BackHover,
ColorTable.Border,
ColorTable.BackNormal,
RoundStyle.All,
true,
true,
mode);
}
else if (toolStrip is ToolStripOverflow)
{
using (Brush brush = new SolidBrush(ColorTable.BackNormal))
{
g.FillRectangle(brush, bounds);
}
}
else
{
base.OnRenderDropDownButtonBackground(e);
}
sg.Dispose();
}
}
protected override void OnRenderSplitButtonBackground(
ToolStripItemRenderEventArgs e)
{
ToolStrip toolStrip = e.ToolStrip;
ToolStripSplitButton item = e.Item as ToolStripSplitButton;
if (item != null)
{
Graphics g = e.Graphics;
LinearGradientMode mode =
toolStrip.Orientation == Orientation.Horizontal ?
LinearGradientMode.Vertical : LinearGradientMode.Horizontal;
Rectangle bounds = new Rectangle(Point.Empty, item.Size);
SmoothingModeGraphics sg = new SmoothingModeGraphics(g);
Color arrowColor = toolStrip.Enabled ?
ColorTable.Fore : SystemColors.ControlDark;
if (item.BackgroundImage != null)
{
Rectangle clipRect = item.Selected ? item.ContentRectangle : bounds;
ControlPaintEx.DrawBackgroundImage(
g,
item.BackgroundImage,
ColorTable.BackNormal,
item.BackgroundImageLayout,
bounds,
clipRect);
}
if (item.ButtonPressed)
{
Rectangle buttonBounds = item.ButtonBounds;
Padding padding = (item.RightToLeft == RightToLeft.Yes) ?
new Padding(0, 1, 1, 1) : new Padding(1, 1, 0, 1);
buttonBounds = LayoutUtils.DeflateRect(buttonBounds, padding);
RenderHelper.RenderBackgroundInternal(
g,
bounds,
ColorTable.BackHover,
ColorTable.Border,
ColorTable.BackNormal,
RoundStyle.All,
true,
true,
mode);
buttonBounds.Inflate(-1, -1);
g.SetClip(buttonBounds);
RenderHelper.RenderBackgroundInternal(
g,
buttonBounds,
ColorTable.BackPressed,
ColorTable.Border,
ColorTable.BackNormal,
RoundStyle.Left,
false,
true,
mode);
g.ResetClip();
using (Pen pen = new Pen(ColorTable.Border))
{
g.DrawLine(
pen,
item.SplitterBounds.Left,
item.SplitterBounds.Top,
item.SplitterBounds.Left,
item.SplitterBounds.Bottom);
}
base.DrawArrow(
new ToolStripArrowRenderEventArgs(
g,
item,
item.DropDownButtonBounds,
arrowColor,
ArrowDirection.Down));
return;
}
if (item.Pressed || item.DropDownButtonPressed)
{
RenderHelper.RenderBackgroundInternal(
g,
bounds,
ColorTable.BackPressed,
ColorTable.Border,
ColorTable.BackNormal,
RoundStyle.All,
true,
true,
mode);
base.DrawArrow(
new ToolStripArrowRenderEventArgs(
g,
item,
item.DropDownButtonBounds,
arrowColor,
ArrowDirection.Down));
return;
}
if (item.Selected)
{
RenderHelper.RenderBackgroundInternal(
g,
bounds,
ColorTable.BackHover,
ColorTable.Border,
ColorTable.BackNormal,
RoundStyle.All,
true,
true,
mode);
using (Pen pen = new Pen(ColorTable.Border))
{
g.DrawLine(
pen,
item.SplitterBounds.Left,
item.SplitterBounds.Top,
item.SplitterBounds.Left,
item.SplitterBounds.Bottom);
}
base.DrawArrow(
new ToolStripArrowRenderEventArgs(
g,
item,
item.DropDownButtonBounds,
arrowColor,
ArrowDirection.Down));
return;
}
base.DrawArrow(
new ToolStripArrowRenderEventArgs(
g,
item,
item.DropDownButtonBounds,
arrowColor,
ArrowDirection.Down));
return;
}
base.OnRenderSplitButtonBackground(e);
}
(3)下面介绍对ToolStrip手柄(Grip)的绘制。当ToolStrip的GripStyle属性设置为ToolStripGripStyle.Visible时,根据不同的ToolStripGripDisplayStyle绘制横向或纵向的Grip。主要是通过API函数SetPixel在指定的场景中设置一个像素的RGB值。当然可能某些设备不支持SetPixel函数,可用GetDeviceCaps判断设备是否支持这个函数。以下是绘制Grip的代码:
protected override void OnRenderGrip(
ToolStripGripRenderEventArgs e)
{
if (e.GripStyle == ToolStripGripStyle.Visible)
{
Rectangle bounds = e.GripBounds;
bool vert = e.GripDisplayStyle == ToolStripGripDisplayStyle.Vertical;
ToolStrip toolStrip = e.ToolStrip;
Graphics g = e.Graphics;
if (vert)
{
bounds.X = e.AffectedBounds.X;
bounds.Width = e.AffectedBounds.Width;
if (toolStrip is MenuStrip)
{
if (e.AffectedBounds.Height > e.AffectedBounds.Width)
{
vert = false;
bounds.Y = e.AffectedBounds.Y;
}
else
{
toolStrip.GripMargin = new Padding(0, 2, 0, 2);
bounds.Y = e.AffectedBounds.Y;
bounds.Height = e.AffectedBounds.Height;
}
}
else
{
toolStrip.GripMargin = new Padding(2, 2, 4, 2);
bounds.X++;
bounds.Width++;
}
}
else
{
bounds.Y = e.AffectedBounds.Y;
bounds.Height = e.AffectedBounds.Height;
}
DrawDottedGrip(
g,
bounds,
vert,
false,
ColorTable.BackNormal,
ControlPaint.Dark(ColorTable.Base, 0.3F));
}
}
private void DrawDottedGrip(
Graphics g,
Rectangle bounds,
bool vertical,
bool largeDot,
Color innerColor,
Color outerColor)
{
bounds.Height -= 3;
Point position = new Point(bounds.X, bounds.Y);
int sep;
Rectangle posRect = new Rectangle(0, 0, 2, 2);
using (SmoothingModeGraphics sg = new SmoothingModeGraphics(g))
{
IntPtr hdc;
if (vertical)
{
sep = bounds.Height;
position.Y += 8;
for (int i = 0; position.Y > 4; i += 4)
{
position.Y = sep - (2 + i);
if (largeDot)
{
posRect.Location = position;
DrawCircle(
g,
posRect,
outerColor,
innerColor);
}
else
{
int innerWin32Corlor = ColorTranslator.ToWin32(innerColor);
int outerWin32Corlor = ColorTranslator.ToWin32(outerColor);
hdc = g.GetHdc();
SetPixel(
hdc,
position.X,
position.Y,
innerWin32Corlor);
SetPixel(
hdc,
position.X + 1,
position.Y,
outerWin32Corlor);
SetPixel(
hdc,
position.X,
position.Y + 1,
outerWin32Corlor);
SetPixel(
hdc,
position.X + 3,
position.Y,
innerWin32Corlor);
SetPixel(
hdc,
position.X + 4,
position.Y,
outerWin32Corlor);
SetPixel(
hdc,
position.X + 3,
position.Y + 1,
outerWin32Corlor);
g.ReleaseHdc(hdc);
}
}
}
else
{
bounds.Inflate(-2, 0);
sep = bounds.Width;
position.X += 2;
for (int i = 1; position.X > 0; i += 4)
{
position.X = sep - (2 + i);
if (largeDot)
{
posRect.Location = position;
DrawCircle(g, posRect, outerColor, innerColor);
}
else
{
int innerWin32Corlor = ColorTranslator.ToWin32(innerColor);
int outerWin32Corlor = ColorTranslator.ToWin32(outerColor);
hdc = g.GetHdc();
SetPixel(
hdc,
position.X,
position.Y,
innerWin32Corlor);
SetPixel(
hdc,
position.X + 1,
position.Y,
outerWin32Corlor);
SetPixel(
hdc,
position.X,
position.Y + 1,
outerWin32Corlor);
SetPixel(
hdc,
position.X + 3,
position.Y,
innerWin32Corlor);
SetPixel(
hdc,
position.X + 4,
position.Y,
outerWin32Corlor);
SetPixel(
hdc,
position.X + 3,
position.Y + 1,
outerWin32Corlor);
g.ReleaseHdc(hdc);
}
}
}
}
}
(4)绘制状态栏Grip时,我们采用了DrawLine方法,以下是具体绘制方法。看下面的代码就知道,我们绘一批直线,内、外侧直线采用不同画笔,依次间隔。每条直线起点处纵坐标一致,横坐标递增一个像素长度;终点处横坐标一致,纵坐标递增一个像素宽度。这样很轻松就完成了对StatusStrip手柄的绘制。
protected override void OnRenderStatusStripSizingGrip(
ToolStripRenderEventArgs e)
{
DrawSolidStatusGrip(
e.Graphics,
e.AffectedBounds,
ColorTable.BackNormal,
ControlPaint.Dark(ColorTable.Base, 0.3f));
}
private void DrawSolidStatusGrip(
Graphics g,
Rectangle bounds,
Color innerColor,
Color outerColor
)
{
using (SmoothingModeGraphics sg = new SmoothingModeGraphics(g))
{
using (Pen innerPen = new Pen(innerColor),
outerPen = new Pen(outerColor))
{
//outer line
g.DrawLine(
outerPen,
new Point(bounds.Width - 14, bounds.Height - 6),
new Point(bounds.Width - 4, bounds.Height - 16));
g.DrawLine(
innerPen,
new Point(bounds.Width - 13, bounds.Height - 6),
new Point(bounds.Width - 4, bounds.Height - 15));
// line
g.DrawLine(
outerPen,
new Point(bounds.Width - 12, bounds.Height - 6),
new Point(bounds.Width - 4, bounds.Height - 14));
g.DrawLine(
innerPen,
new Point(bounds.Width - 11, bounds.Height - 6),
new Point(bounds.Width - 4, bounds.Height - 13));
// line
g.DrawLine(
outerPen,
new Point(bounds.Width - 10, bounds.Height - 6),
new Point(bounds.Width - 4, bounds.Height - 12));
g.DrawLine(
innerPen,
new Point(bounds.Width - 9, bounds.Height - 6),
new Point(bounds.Width - 4, bounds.Height - 11));
// line
g.DrawLine(
outerPen,
new Point(bounds.Width - 8, bounds.Height - 6),
new Point(bounds.Width - 4, bounds.Height - 10));
g.DrawLine(
innerPen,
new Point(bounds.Width - 7, bounds.Height - 6),
new Point(bounds.Width - 4, bounds.Height - 9));
// inner line
g.DrawLine(
outerPen,
new Point(bounds.Width - 6, bounds.Height - 6),
new Point(bounds.Width - 4, bounds.Height - 8));
g.DrawLine(
innerPen,
new Point(bounds.Width - 5, bounds.Height - 6),
new Point(bounds.Width - 4, bounds.Height - 7));
}
}
}
到此为止,ToolStrip系列控件的美化就完成了,希望对你学习美化ToolStrip控件有所帮助。
声明:
本文版权归作者和CS 程序员之窗所有,欢迎转载,转载必须保留以下版权信息,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
作者:Starts_2000
出处:CS 程序员之窗 http://www.csharpwin.com。
你可以免费使用或修改提供的源代码,但请保留源代码中的版权信息,详情请查看:
CS程序员之窗开源协议 http://www.csharpwin.com/csol.html。
posted on 2013-05-20 11:36 程序员—Ritchie 阅读(1242) 评论(0) 编辑 收藏 举报