2017-01-16 20:59:50 +01:00
|
|
|
|
/* Copyright (c) Citrix Systems, Inc.
|
2013-06-24 13:41:48 +02:00
|
|
|
|
* All rights reserved.
|
|
|
|
|
*
|
|
|
|
|
* Redistribution and use in source and binary forms,
|
|
|
|
|
* with or without modification, are permitted provided
|
|
|
|
|
* that the following conditions are met:
|
|
|
|
|
*
|
|
|
|
|
* * Redistributions of source code must retain the above
|
|
|
|
|
* copyright notice, this list of conditions and the
|
|
|
|
|
* following disclaimer.
|
|
|
|
|
* * Redistributions in binary form must reproduce the above
|
|
|
|
|
* copyright notice, this list of conditions and the
|
|
|
|
|
* following disclaimer in the documentation and/or other
|
|
|
|
|
* materials provided with the distribution.
|
|
|
|
|
*
|
|
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
|
|
|
|
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
|
|
|
|
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
|
|
|
|
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
|
|
|
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
|
|
|
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
|
|
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
|
|
|
|
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
|
|
|
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
|
|
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
|
|
|
|
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
|
|
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
|
|
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
|
|
|
* SUCH DAMAGE.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
using System;
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.Text;
|
|
|
|
|
using System.Drawing;
|
|
|
|
|
using System.Drawing.Imaging;
|
|
|
|
|
using System.Runtime.InteropServices;
|
|
|
|
|
using System.Drawing.Text;
|
|
|
|
|
using System.Windows.Forms;
|
|
|
|
|
|
|
|
|
|
namespace XenAdmin.Core
|
|
|
|
|
{
|
|
|
|
|
class Drawing
|
|
|
|
|
{
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// The color of URLs.
|
|
|
|
|
/// </summary>
|
|
|
|
|
// Feel free to improve this definition if you can think of a nicer way
|
|
|
|
|
// (it doesn't seem to be one of the SystemColors, nor helpfully provided in LinkLabel)
|
|
|
|
|
public static readonly Color LinkColor = Color.Blue;
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// The color of tooltip backgrounds in XP.
|
|
|
|
|
/// </summary>
|
|
|
|
|
public static readonly Color ToolTipColor = Color.FromArgb(255, 255, 225);
|
|
|
|
|
|
|
|
|
|
public static readonly Color XPBorderColor = Color.FromArgb(123, 158, 189);
|
|
|
|
|
public static readonly Pen XPBorderPen = new Pen(XPBorderColor, 1);
|
|
|
|
|
|
|
|
|
|
private static readonly ColorMatrix GreyScaleColorMatrix = new ColorMatrix(new float[][]
|
|
|
|
|
{
|
|
|
|
|
new float[] {0.2125f, 0.2125f, 0.2125f, 0, 0},
|
|
|
|
|
new float[] {0.2577f, 0.2577f, 0.2577f, 0, 0},
|
|
|
|
|
new float[] {0.0361f, 0.0361f, 0.0361f, 0, 0},
|
|
|
|
|
new float[] {0, 0, 0, 1, 0},
|
|
|
|
|
new float[] {0.38f, 0.38f, 0.38f, 0, 1}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
private static readonly ColorMatrix AlphaColorMatrix = new ColorMatrix(new float[][]
|
|
|
|
|
{
|
|
|
|
|
new float[] {1, 0, 0, 0, 0},
|
|
|
|
|
new float[] {0, 1, 0, 0, 0},
|
|
|
|
|
new float[] {0, 0, 1, 0, 0},
|
|
|
|
|
new float[] {0, 0, 0, .75f, 0},
|
|
|
|
|
new float[] {0, 0, 0, 0, 1}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
public static readonly ImageAttributes GreyScaleAttributes = new ImageAttributes();
|
|
|
|
|
public static readonly ImageAttributes AlphaAttributes = new ImageAttributes();
|
|
|
|
|
static Drawing()
|
|
|
|
|
{
|
|
|
|
|
GreyScaleAttributes.SetColorMatrix(GreyScaleColorMatrix);
|
|
|
|
|
AlphaAttributes.SetColorMatrix(AlphaColorMatrix);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Kerpow!
|
|
|
|
|
/// </summary>
|
|
|
|
|
public static void QuickDraw(Graphics gTarget, Bitmap buffer)
|
|
|
|
|
{
|
|
|
|
|
QuickDraw(gTarget, buffer, new Point(0, 0), new Rectangle(0, 0, buffer.Width, buffer.Height));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Kerpow!
|
|
|
|
|
/// </summary>
|
|
|
|
|
public static void QuickDraw(Graphics gTarget, Bitmap buffer, Point source, Rectangle dest)
|
|
|
|
|
{
|
|
|
|
|
IntPtr pTarget = gTarget.GetHdc();
|
|
|
|
|
IntPtr pSource = CreateCompatibleDC(pTarget);
|
|
|
|
|
IntPtr pNew = buffer.GetHbitmap();
|
|
|
|
|
SelectObject(pSource, pNew);
|
|
|
|
|
BitBlt(pTarget, dest.X, dest.Y, dest.Width, dest.Height, pSource, source.X, source.Y, TernaryRasterOperations.SRCCOPY);
|
|
|
|
|
DeleteObject(pNew);
|
|
|
|
|
DeleteDC(pSource);
|
|
|
|
|
gTarget.ReleaseHdc(pTarget);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[DllImport("gdi32.dll", SetLastError = true)]
|
|
|
|
|
public static extern bool BitBlt(IntPtr hObject, int nXDest, int nYDest, int nWidth,
|
|
|
|
|
int nHeight, IntPtr hObjSource, int nXSrc, int nYSrc, TernaryRasterOperations dwRop);
|
|
|
|
|
|
|
|
|
|
[DllImport("gdi32.dll", ExactSpelling = true, SetLastError = true)]
|
|
|
|
|
public static extern IntPtr CreateCompatibleDC(IntPtr hdc);
|
|
|
|
|
|
|
|
|
|
[DllImport("gdi32.dll", ExactSpelling = true, SetLastError = true)]
|
|
|
|
|
public static extern bool DeleteDC(IntPtr hdc);
|
|
|
|
|
|
|
|
|
|
[DllImport("gdi32.dll", ExactSpelling = true, SetLastError = true)]
|
|
|
|
|
public static extern IntPtr SelectObject(IntPtr hdc, IntPtr hgdiobj);
|
|
|
|
|
|
|
|
|
|
[DllImport("gdi32.dll", ExactSpelling = true, SetLastError = true)]
|
|
|
|
|
public static extern bool DeleteObject(IntPtr hObject);
|
|
|
|
|
|
|
|
|
|
public enum TernaryRasterOperations : uint
|
|
|
|
|
{
|
|
|
|
|
SRCCOPY = 0x00CC0020,
|
|
|
|
|
SRCPAINT = 0x00EE0086,
|
|
|
|
|
SRCAND = 0x008800C6,
|
|
|
|
|
SRCINVERT = 0x00660046,
|
|
|
|
|
SRCERASE = 0x00440328,
|
|
|
|
|
NOTSRCCOPY = 0x00330008,
|
|
|
|
|
NOTSRCERASE = 0x001100A6,
|
|
|
|
|
MERGECOPY = 0x00C000CA,
|
|
|
|
|
MERGEPAINT = 0x00BB0226,
|
|
|
|
|
PATCOPY = 0x00F00021,
|
|
|
|
|
PATPAINT = 0x00FB0A09,
|
|
|
|
|
PATINVERT = 0x005A0049,
|
|
|
|
|
DSTINVERT = 0x00550009,
|
|
|
|
|
BLACKNESS = 0x00000042,
|
|
|
|
|
WHITENESS = 0x00FF0062
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static TextRenderingHint TextRenderingHint
|
|
|
|
|
{
|
|
|
|
|
get
|
|
|
|
|
{
|
|
|
|
|
return TextRenderingHint.SystemDefault;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// CA-23037: & character in name, custom field (anything on general panel)
|
|
|
|
|
// renders as a keyboard shortcut
|
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
public static void DrawText(IDeviceContext dc, String text, Font font,
|
|
|
|
|
Point point, Color color)
|
|
|
|
|
{
|
|
|
|
|
TextRenderer.DrawText(dc, text, font, point, color, TextFormatFlags.NoPrefix);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static void DrawText(IDeviceContext dc, String text, Font font,
|
|
|
|
|
Point point, Color color, Color backColor)
|
|
|
|
|
{
|
|
|
|
|
DrawText(dc, text, font, point, color, backColor, TextFormatFlags.NoPrefix);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static void DrawText(IDeviceContext dc, String text, Font font,
|
|
|
|
|
Point point, Color color, Color backColor, TextFormatFlags flags)
|
|
|
|
|
{
|
|
|
|
|
TextRenderer.DrawText(dc, text, font, point, color, backColor, flags | TextFormatFlags.NoPrefix);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static void DrawText(IDeviceContext dc, String text, Font font,
|
|
|
|
|
Rectangle bounds, Color color)
|
|
|
|
|
{
|
|
|
|
|
DrawText(dc, text, font, bounds, color, TextFormatFlags.NoPrefix);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static void DrawText(IDeviceContext dc, String text, Font font,
|
|
|
|
|
Rectangle bounds, Color color, TextFormatFlags textFormatFlags)
|
|
|
|
|
{
|
|
|
|
|
TextRenderer.DrawText(dc, text, font, bounds, color, textFormatFlags | TextFormatFlags.NoPrefix);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static void DrawText(IDeviceContext dc, String text, Font font,
|
|
|
|
|
Rectangle bounds, Color foreColor, Color backColor)
|
|
|
|
|
{
|
|
|
|
|
DrawText(dc, text, font, bounds, foreColor, backColor, TextFormatFlags.NoPrefix);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static void DrawText(IDeviceContext dc, String text, Font font,
|
|
|
|
|
Rectangle bounds, Color foreColor, Color backColor, TextFormatFlags flags)
|
|
|
|
|
{
|
|
|
|
|
TextRenderer.DrawText(dc, text, font, bounds, foreColor, backColor, flags | TextFormatFlags.NoPrefix);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static Size MeasureText(String text, Font font)
|
|
|
|
|
{
|
|
|
|
|
return MeasureText(text, font, new Size(Int32.MaxValue, Int32.MaxValue), TextFormatFlags.NoPrefix);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static Size MeasureText(String text, Font font, Size proposedSize, TextFormatFlags flags)
|
|
|
|
|
{
|
|
|
|
|
return TextRenderer.MeasureText(text, font, proposedSize, flags | TextFormatFlags.NoPrefix);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static Size MeasureText(IDeviceContext dc, String text, Font font)
|
|
|
|
|
{
|
|
|
|
|
return MeasureText(dc, text, font, new Size(Int32.MaxValue, Int32.MaxValue), TextFormatFlags.NoPrefix);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static Size MeasureText(IDeviceContext dc, String text, Font font, TextFormatFlags flags)
|
|
|
|
|
{
|
|
|
|
|
return MeasureText(dc, text, font, new Size(Int32.MaxValue, Int32.MaxValue), flags);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static Size MeasureText(IDeviceContext dc, String text, Font font, Size proposedSize, TextFormatFlags flags)
|
|
|
|
|
{
|
|
|
|
|
return TextRenderer.MeasureText(dc, text, font, proposedSize, flags | TextFormatFlags.NoPrefix);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Draw me a progress bar. Copes with visual styles being on or off
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="g">Graphics to draw to</param>
|
|
|
|
|
/// <param name="r">where to draw the progress bar</param>
|
|
|
|
|
/// <param name="progress">how much progress (0.0-1.0)</param>
|
|
|
|
|
///
|
|
|
|
|
public static void DrawProgressBar(Graphics g, Rectangle r, double progress)
|
|
|
|
|
{
|
|
|
|
|
if (Application.RenderWithVisualStyles)
|
|
|
|
|
{
|
|
|
|
|
ProgressBarRenderer.DrawHorizontalBar(g, r);
|
|
|
|
|
|
|
|
|
|
Rectangle s = new Rectangle(
|
|
|
|
|
r.X + 4,
|
|
|
|
|
r.Y + 3,
|
|
|
|
|
(int)((r.Width - 8) * progress),
|
|
|
|
|
r.Height - 5);
|
|
|
|
|
|
|
|
|
|
ProgressBarRenderer.DrawHorizontalChunks(g, s);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
g.FillRectangle(SystemBrushes.ButtonShadow, r);
|
|
|
|
|
|
|
|
|
|
Rectangle s = new Rectangle(
|
|
|
|
|
r.X + 1,
|
|
|
|
|
r.Y + 1,
|
|
|
|
|
r.Width - 1,
|
|
|
|
|
r.Height - 1);
|
|
|
|
|
|
|
|
|
|
g.FillRectangle(SystemBrushes.ButtonHighlight, s);
|
|
|
|
|
|
|
|
|
|
Rectangle t = new Rectangle(
|
|
|
|
|
r.X + 1,
|
|
|
|
|
r.Y + 1,
|
|
|
|
|
r.Width - 2,
|
|
|
|
|
r.Height - 2);
|
|
|
|
|
|
|
|
|
|
g.FillRectangle(SystemBrushes.ButtonFace, t);
|
|
|
|
|
|
|
|
|
|
int barwidth = (int)(progress * (r.Width - 4));
|
|
|
|
|
int chunkwidth = 7;
|
|
|
|
|
int chunkgap = 2;
|
|
|
|
|
int progleft = 0;
|
|
|
|
|
while (progleft + chunkwidth + chunkgap < barwidth)
|
|
|
|
|
{
|
|
|
|
|
Rectangle u = new Rectangle(
|
|
|
|
|
r.X + 2 + progleft,
|
|
|
|
|
r.Y + 2,
|
|
|
|
|
chunkwidth,
|
|
|
|
|
13);
|
|
|
|
|
|
|
|
|
|
g.FillRectangle(SystemBrushes.ActiveCaption, u);
|
|
|
|
|
progleft += chunkwidth + chunkgap;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Rectangle v = new Rectangle(
|
|
|
|
|
r.X + 2 + progleft,
|
|
|
|
|
r.Y + 2,
|
|
|
|
|
chunkwidth - progleft,
|
|
|
|
|
13);
|
|
|
|
|
|
|
|
|
|
g.FillRectangle(SystemBrushes.ActiveCaption, v);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public enum SimpleProgressBarColor { Green, Red, Blue };
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Draws a simple progress bar (just the chunks with a grey 1 pixel border). Changes the color to
|
|
|
|
|
/// red if the <see cref="changeColor"/> value is greater than the changeColorProgress value.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="g">The device context used for drawing.</param>
|
|
|
|
|
/// <param name="r">The rectangle that specifies where it should be drawn.</param>
|
|
|
|
|
/// <param name="progress">The value of the progress. Should be between 0.0 and 1.0.</param>
|
|
|
|
|
/// <param name="color">The color of the progress bar.</param>
|
|
|
|
|
public static void DrawSimpleProgressBar(Graphics g, Rectangle r, double progress, SimpleProgressBarColor color)
|
|
|
|
|
{
|
2013-09-26 09:29:11 +02:00
|
|
|
|
using (Bitmap bitmap = new Bitmap(r.Width, r.Height))
|
2013-06-24 13:41:48 +02:00
|
|
|
|
{
|
2013-09-26 09:29:11 +02:00
|
|
|
|
using (Graphics gg = Graphics.FromImage(bitmap))
|
2013-06-24 13:41:48 +02:00
|
|
|
|
{
|
2013-09-26 09:29:11 +02:00
|
|
|
|
//fill background in white
|
|
|
|
|
gg.FillRectangle(Brushes.White, new Rectangle(0, 0, r.Width, r.Height));
|
|
|
|
|
Rectangle chunks = new Rectangle(0, 0, (int)(r.Width * progress), r.Height);
|
2013-06-24 13:41:48 +02:00
|
|
|
|
|
2013-09-26 09:29:11 +02:00
|
|
|
|
if (Application.RenderWithVisualStyles)
|
2013-06-24 13:41:48 +02:00
|
|
|
|
{
|
2013-09-26 09:29:11 +02:00
|
|
|
|
ProgressBarRenderer.DrawHorizontalChunks(gg, chunks);
|
2013-06-24 13:41:48 +02:00
|
|
|
|
}
|
2013-09-26 09:29:11 +02:00
|
|
|
|
else
|
2013-06-24 13:41:48 +02:00
|
|
|
|
{
|
2013-09-26 09:29:11 +02:00
|
|
|
|
var brush = Brushes.LightGreen;
|
|
|
|
|
|
|
|
|
|
if (color == SimpleProgressBarColor.Red)
|
|
|
|
|
{
|
|
|
|
|
brush = Brushes.Red;
|
|
|
|
|
}
|
|
|
|
|
else if (color == SimpleProgressBarColor.Blue)
|
|
|
|
|
{
|
|
|
|
|
brush = Brushes.Blue;
|
|
|
|
|
}
|
2013-06-24 13:41:48 +02:00
|
|
|
|
|
2013-09-26 09:29:11 +02:00
|
|
|
|
gg.FillRectangle(brush, chunks);
|
|
|
|
|
}
|
2013-06-24 13:41:48 +02:00
|
|
|
|
}
|
|
|
|
|
|
2013-09-26 09:29:11 +02:00
|
|
|
|
if (Application.RenderWithVisualStyles && color != SimpleProgressBarColor.Green)
|
2013-06-24 13:41:48 +02:00
|
|
|
|
{
|
2013-09-26 09:29:11 +02:00
|
|
|
|
for (int i = 0; i < bitmap.Width * progress; i++)
|
2013-06-24 13:41:48 +02:00
|
|
|
|
{
|
2013-09-26 09:29:11 +02:00
|
|
|
|
for (int j = 0; j < bitmap.Height; j++)
|
2013-06-24 13:41:48 +02:00
|
|
|
|
{
|
2013-09-26 09:29:11 +02:00
|
|
|
|
Color c = bitmap.GetPixel(i, j);
|
|
|
|
|
|
|
|
|
|
if (color == SimpleProgressBarColor.Blue)
|
|
|
|
|
{
|
|
|
|
|
bitmap.SetPixel(i, j, Color.FromArgb(c.R, c.B, c.G));
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
//red
|
|
|
|
|
bitmap.SetPixel(i, j, Color.FromArgb(c.G, c.R, c.B));
|
|
|
|
|
}
|
2013-06-24 13:41:48 +02:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2013-09-26 09:29:11 +02:00
|
|
|
|
// draw progress bar
|
|
|
|
|
g.DrawImage(bitmap, r);
|
2013-06-24 13:41:48 +02:00
|
|
|
|
|
2013-09-26 09:29:11 +02:00
|
|
|
|
// draw rectangle around progress bar.
|
|
|
|
|
g.DrawRectangle(SystemPens.ControlDark, r);
|
|
|
|
|
}
|
2013-06-24 13:41:48 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Converts input image to grey scale using Drawing.GreyScaleAttributes
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="source">Image to convert</param>
|
|
|
|
|
/// <returns>Image converted to grey scale</returns>
|
|
|
|
|
public static Image ConvertToGreyScale(Image source)
|
|
|
|
|
{
|
2013-11-01 12:14:26 +01:00
|
|
|
|
var bitmap = new Bitmap(source.Width, source.Height);
|
|
|
|
|
|
|
|
|
|
using (Graphics graphics = Graphics.FromImage(bitmap))
|
2013-06-24 13:41:48 +02:00
|
|
|
|
{
|
2013-11-01 12:14:26 +01:00
|
|
|
|
var rectangle = new Rectangle(0, 0, source.Width, source.Height);
|
|
|
|
|
graphics.DrawImage(source, rectangle, 0, 0, source.Width, source.Height, GraphicsUnit.Pixel,
|
|
|
|
|
Drawing.GreyScaleAttributes);
|
|
|
|
|
return bitmap;
|
2013-06-24 13:41:48 +02:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|