using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.Windows.Forms;
using Storm.TextEditor.Core;
using Storm.TextEditor.Win32;
using Storm.TextEditor.Win32.Enums;
namespace Storm.TextEditor.Drawing
{
/// <summary>
/// Represents a sealed class holding several methods for drawing.
/// </summary>
public sealed class DrawingTools
{
#region Methods
#region Public
/// <summary>
/// Resets the given Graphics variable.
/// </summary>
/// <param name="g">Graphics to reset.</param>
public static void ResetGraphics(Graphics g)
{
g.ReleaseHdc(g.GetHdc());
}
/// <summary>
/// Mixes the given colors and returns the new color.
/// </summary>
/// <param name="c1">First color to mix.</param>
/// <param name="c2">Second color to mix.</param>
/// <param name="mix">Factor of the mixing.</param>
/// <returns>The mixed color.</returns>
public static Color MixColors(Color c1, Color c2, double mix)
{
return Color.FromArgb((int)(c1.R * (1 - mix) + c2.R * mix), (int)(c1.G *
(1 - mix) + c2.G * mix), (int)(c1.B * (1 - mix) + c2.B * mix));
}
/// <summary>
/// Draws a border depending on the given ControlBorderStyle with specific color at the given Rectangle.
/// </summary>
/// <param name="style">ControlBorderStyle that holds how the method should draw the border.</param>
/// <param name="borderColor">Color of the drawn border.</param>
/// <param name="g">Graphics to use when drawing.</param>
/// <param name="r">Rectangle to draw the border at.</param>
public static void DrawBorder(ControlBorderStyle style, Color borderColor, Graphics g, Rectangle r)
{
switch (style)
{
case ControlBorderStyle.Dotted:
{
r.Width--;
r.Height--;
g.DrawRectangle(new Pen(SystemColors.Control), r);
Pen p = new Pen(borderColor);
p.DashStyle = DashStyle.Dot;
g.DrawRectangle(p, r);
break;
}
case ControlBorderStyle.Dashed:
{
r.Width--;
r.Height--;
g.DrawRectangle(new Pen(SystemColors.Control), r);
Pen p = new Pen(borderColor);
p.DashStyle = DashStyle.Dash;
g.DrawRectangle(p, r);
break;
}
case ControlBorderStyle.Sunken:
{
if (borderColor == Color.Black)
borderColor = SystemColors.Control;
DrawingTools.DrawBorder(Border3DStyle.Sunken, borderColor, g, r);
break;
}
case ControlBorderStyle.FixedSingle:
{
r.Width--;
r.Height--;
g.DrawRectangle(new Pen(borderColor), r);
break;
}
case ControlBorderStyle.FixedDouble:
{
g.DrawRectangle(new Pen(borderColor), r.Left, r.Top, r.Width - 1, r.Height - 1);
g.DrawRectangle(new Pen(borderColor), r.Left + 1, r.Top + 1, r.Width - 3, r.Height - 3);
break;
}
case ControlBorderStyle.Raised:
{
if (borderColor == Color.Black)
borderColor = SystemColors.Control;
DrawingTools.DrawBorder(Border3DStyle.Raised, borderColor, g, r);
break;
}
case ControlBorderStyle.RaisedThin:
{
if (borderColor == Color.Black)
{
borderColor = Color.FromArgb(SystemColors.Control.R,
SystemColors.Control.G, SystemColors.Control.B);
}
DrawingTools.DrawBorder(Border3DStyle.RaisedInner,
borderColor, g, r);
break;
}
case ControlBorderStyle.SunkenThin:
{
if (borderColor == Color.Black)
{
borderColor = Color.FromArgb(SystemColors.Control.R,
SystemColors.Control.G, SystemColors.Control.B);
}
DrawingTools.DrawBorder(Border3DStyle.SunkenOuter,
borderColor, g, r);
break;
}
case ControlBorderStyle.Etched:
{
if (borderColor == Color.Black)
borderColor = SystemColors.Control;
ControlPaint.DrawBorder3D(g, r,
Border3DStyle.Etched);
break;
}
case ControlBorderStyle.Bump:
{
if (borderColor == Color.Black)
borderColor = SystemColors.Control;
SolidBrush b = new SolidBrush(borderColor);
g.FillRectangle(b, r.Left, r.Top, r.Width, 4);
g.FillRectangle(b, r.Left, r.Bottom - 4, r.Width, 4);
g.FillRectangle(b, r.Left, r.Top, 4, r.Height);
g.FillRectangle(b, r.Right - 4, r.Top, 4, r.Height);
b.Dispose();
DrawingTools.DrawBorder(Border3DStyle.Raised, borderColor, g, r);
DrawingTools.DrawBorder(Border3DStyle.Sunken, borderColor, g,
new Rectangle(r.Left + 4, r.Top + 4, r.Width - 8,
r.Height - 8));
break;
}
case ControlBorderStyle.Column:
{
SolidBrush normal = new SolidBrush(borderColor);
SolidBrush light = new SolidBrush(MixColors(borderColor,
Color.White, 1));
SolidBrush dark = new SolidBrush(MixColors(borderColor,
Color.Black, 0.4));
SolidBrush darkdark = new SolidBrush(Color.FromArgb
(borderColor.A, System.Windows.Forms.ControlPaint.
DarkDark(borderColor)));
g.FillRectangle(light, r.Left, r.Top, r.Width, 1);
g.FillRectangle(light, r.Left, r.Top + 3, 1, r.Height - 1 - 6);
g.FillRectangle(dark, r.Right - 1, r.Top + 3, 1, r.Height - 6);
g.FillRectangle(dark, r.Left, r.Bottom - 1, r.Width, 1);
break;
}
case ControlBorderStyle.Row:
{
SolidBrush normal = new SolidBrush(borderColor);
SolidBrush light = new SolidBrush(MixColors(borderColor,
Color.White, 1));
SolidBrush dark = new SolidBrush(MixColors(borderColor,
Color.Black, 0.4));
SolidBrush darkdark = new SolidBrush(Color.FromArgb
(borderColor.A, System.Windows.Forms.ControlPaint.DarkDark
(borderColor)));
g.FillRectangle(light, r.Left + 3, r.Top, r.Width - 6, 1);
g.FillRectangle(light, r.Left, r.Top, 1, r.Height - 1);
g.FillRectangle(dark, r.Right - 1, r.Top, 1, r.Height);
g.FillRectangle(dark, r.Left + 3, r.Bottom - 1, r.Width - 6, 1);
break;
}
}
}
/// <summary>
/// Draws a line at the given coordinates.
/// </summary>
/// <param name="g">Graphics to use when drawing.</param>
/// <param name="x1">Start x coordinate.</param>
/// <param name="y1">Start y coordinate.</param>
/// <param name="x2">End x coordinate.</param>
/// <param name="y2">End y coordinate.</param>
public static void DrawDesignTimeLine(Graphics g, int x1, int y1, int x2, int y2)
{
Pen p = new Pen(SystemColors.ControlDarkDark);
p.DashOffset = 10;
p.DashStyle = DashStyle.Dash;
g.DrawLine(p, x1, y1, x2, y2);
p.Dispose();
}
/// <summary>
/// Draws the given image as a gray version.
/// </summary>
/// <param name="g">Graphics to use when drawing.</param>
/// <param name="image">Image to draw.</param>
/// <param name="x">X coordinate to draw the image at.</param>
/// <param name="y">Y coordinate to draw the image at.</param>
/// <param name="transparencyFactor">Factor of the transparency.</param>
public static void DrawGrayImage(Graphics g, Image image, int x, int y, float transparencyFactor)
{
ColorMatrix cm = new ColorMatrix();
ImageAttributes ia = new ImageAttributes();
cm.Matrix33 = transparencyFactor;
cm.Matrix00 = 0.33333334F;
cm.Matrix01 = 0.33333334F;
cm.Matrix02 = 0.33333334F;
cm.Matrix10 = 0.33333334F;
cm.Matrix11 = 0.33333334F;
cm.Matrix12 = 0.33333334F;
cm.Matrix20 = 0.33333334F;
cm.Matrix21 = 0.33333334F;
cm.Matrix22 = 0.33333334F;
ia.SetColorMatrix(cm);
g.DrawImage(image, new Rectangle(x, y, image.Width, image.Height), 0, 0,
image.Width, image.Height, GraphicsUnit.Pixel, ia);
}
/// <summary>
/// Draws the given image as a transparent version.
/// </summary>
/// <param name="g">Graphics to use when drawing.</param>
/// <param name="image">Image to draw.</param>
/// <param name="x">X coordinate to draw the image at.</param>
/// <param name="y">Y coordinate to draw the image at.</param>
/// <param name="transparencyFactor">Factor of the transparency.</param>
public static void DrawTransparentImage(Graphics g, Image image, int x, int y, float transparencyFactor)
{
ImageAttributes ia = new ImageAttributes();
ColorMatrix cm = new ColorMatrix();
cm.Matrix33 = transparencyFactor;
cm.Matrix00 = 1.0F;
cm.Matrix11 = 1.0F;
cm.Matrix22 = 1.0F;
ia.SetColorMatrix(cm);
g.DrawImage(image, new Rectangle(x, y, image.Width, image.Height), 0, 0,
image.Width, image.Height, GraphicsUnit.Pixel, ia);
}
/// <summary>
/// Draws a border using DashStyle.Dash at the given Rectangle.
/// </summary>
/// <param name="g">Graphics to use when drawing.</param>
/// <param name="rect">Rectangle to draw the border at.</param>
public static void DrawDesignTimeBorder(Graphics g, Rectangle rect)
{
rect.Width--;
rect.Height--;
Pen p = new Pen(SystemColors.ControlDarkDark);
p.DashStyle = DashStyle.Dash;
g.DrawRectangle(p, rect);
p.Dispose();
}
public static void DrawInsertIndicatorH(int x, int y, int width, Graphics g, Color c)
{
y -= 3;
x -= 2;
ControlPaint.FillReversibleRectangle(new Rectangle(x, y, 2, 7), c);
ControlPaint.FillReversibleRectangle(new Rectangle(x + 2, y + 1, width, 5), c);
ControlPaint.FillReversibleRectangle(new Rectangle(width + 2 + x, y, 2, 7), c);
}
public static void DrawInsertIndicatorV(int x, int y, int height, Graphics g, Color c)
{
x -= 3;
y -= 2;
ControlPaint.FillReversibleRectangle(new Rectangle(x, y, 7, 2), c);
ControlPaint.FillReversibleRectangle(new Rectangle(x + 1, y + 2, 5, height), c);
ControlPaint.FillReversibleRectangle(new Rectangle(x, height + 2 + y, 7, 2), c);
}
/// <summary>
/// Draws the given Control.
/// </summary>
/// <param name="control">Control to draw.</param>
/// <returns>Bitmap created from the given Control.</returns>
public static Bitmap DrawControl(Control control)
{
Bitmap b = new Bitmap(control.Width, control.Height);
Graphics g = Graphics.FromImage(b);
IntPtr hdc = g.GetHdc();
int i = NativeUser32Api.SendMessage(control.Handle,
(int)WindowMessage.WM_PRINT, (int)hdc,
(int)(WMPrintFlags.PRF_CLIENT |
WMPrintFlags.PRF_ERASEBKGND));
g.ReleaseHdc(hdc);
g.Dispose();
return b;
}
/// <summary>
/// Draws the given Control.
/// </summary>
/// <param name="control">Control to draw.</param>
/// <param name="b">Bitmap to create graphics from.</param>
/// <returns>Whether the drawing was succesful.</returns>
public static bool DrawControl(Control control, Bitmap b)
{
Graphics g = Graphics.FromImage(b);
IntPtr hdc = g.GetHdc();
int result = NativeUser32Api.SendMessage(control.Handle, (int)WindowMessage.WM_PRINT, (int)hdc,
(int)(WMPrintFlags.PRF_CLIENT | WMPrintFlags.PRF_ERASEBKGND));
g.ReleaseHdc(hdc);
g.Dispose();
return result != 0;
}
public static void DrawSortArrow(int x, int y, Graphics g, bool ascending)
{
Color c1 = Color.FromArgb(220, 255, 255, 255);
Color c2 = Color.FromArgb(140, 0, 0, 0);
Pen p1 = new Pen(c1);
Pen p2 = new Pen(c2);
if (ascending == true)
{
g.DrawLine(p1, x, y + 6, x + 7, y + 6);
g.DrawLine(p2, x + 3, y, x, y + 6);
g.DrawLine(p1, x + 4, y, x + 7, y + 6);
}
else
{
g.DrawLine(p2, x, y, x + 7, y);
g.DrawLine(p2, x, y, x + 3, y + 6);
g.DrawLine(p1, x + 7, y, x + 4, y + 6);
}
}
#endregion
#region Private
private static void DrawBorder(Border3DStyle Style, Color BorderColor, Graphics g, Rectangle r)
{
SolidBrush normal = new SolidBrush(BorderColor);
SolidBrush light;
if (BorderColor.GetBrightness() > 0.6)
light = new SolidBrush(MixColors(BorderColor, Color.White, 1));
else
light = new SolidBrush(MixColors(BorderColor, Color.White, 0.5));
SolidBrush dark;
SolidBrush darkdark;
if (BorderColor.GetBrightness() < 0.5)
{
dark = new SolidBrush(MixColors(BorderColor, Color.Black, 0.7));
darkdark = new SolidBrush(MixColors(BorderColor, Color.Black, 1));
}
else
{
dark = new SolidBrush(MixColors(BorderColor, Color.Black, 0.4));
darkdark = new SolidBrush(MixColors(BorderColor, Color.Black, 0.6));
}
switch (Style)
{
case Border3DStyle.Sunken:
{
g.FillRectangle(dark, r.Left, r.Top, r.Width, 1);
g.FillRectangle(dark, r.Left, r.Top, 1, r.Height);
g.FillRectangle(darkdark, r.Left + 1, r.Top + 1, r.Width - 2, 1);
g.FillRectangle(darkdark, r.Left + 1, r.Top + 1, 1, r.Height - 2);
g.FillRectangle(light, r.Right - 1, r.Top + 1, 1, r.Height - 1);
g.FillRectangle(light, r.Left + 1, r.Bottom - 1, r.Width - 1, 1);
g.FillRectangle(normal, r.Right - 2, r.Top + 2, 1, r.Height - 3);
g.FillRectangle(normal, r.Left + 2, r.Bottom - 2, r.Width - 3, 1);
break;
}
case Border3DStyle.Raised:
{
g.FillRectangle(normal, r.Left, r.Top, r.Width - 1, 1);
g.FillRectangle(normal, r.Left, r.Top, 1, r.Height - 1);
g.FillRectangle(light, r.Left + 1, r.Top + 1, r.Width - 2, 1);
g.FillRectangle(light, r.Left + 1, r.Top + 1, 1, r.Height - 2);
g.FillRectangle(darkdark, r.Right - 1, r.Top, 1, r.Height);
g.FillRectangle(darkdark, r.Left, r.Bottom - 1, r.Width, 1);
g.FillRectangle(dark, r.Right - 2, r.Top + 1, 1, r.Height - 2);
g.FillRectangle(dark, r.Left + 1, r.Bottom - 2, r.Width - 2, 1);
break;
}
case Border3DStyle.RaisedInner:
{
g.FillRectangle(light, r.Left, r.Top, r.Width - 1, 1);
g.FillRectangle(light, r.Left, r.Top, 1, r.Height - 1);
g.FillRectangle(dark, r.Right - 1, r.Top, 1, r.Height);
g.FillRectangle(dark, r.Left, r.Bottom - 1, r.Width, 1);
break;
}
case Border3DStyle.SunkenOuter:
{
g.FillRectangle(dark, r.Left, r.Top, r.Width, 1);
g.FillRectangle(dark, r.Left, r.Top, 1, r.Height);
g.FillRectangle(light, r.Right - 1, r.Top + 1, 1, r.Height - 1);
g.FillRectangle(light, r.Left + 1, r.Bottom - 1, r.Width - 1, 1);
break;
}
case Border3DStyle.Etched:
break;
default:
break;
}
normal.Dispose();
light.Dispose();
dark.Dispose();
darkdark.Dispose();
}
#endregion
#endregion
/// <summary>
/// Initializes a new instance of DrawingTools.
/// </summary>
private DrawingTools()
{
}
}
}