check point

This commit is contained in:
meelstorm
2025-07-14 12:03:59 +02:00
commit d3cb790bd9
431 changed files with 44078 additions and 0 deletions

View File

@@ -0,0 +1,12 @@
namespace MaterialSkin.Animations
{
enum AnimationDirection
{
In, //In. Stops if finished.
Out, //Out. Stops if finished.
InOutIn, //Same as In, but changes to InOutOut if finished.
InOutOut, //Same as Out.
InOutRepeatingIn, // Same as In, but changes to InOutRepeatingOut if finished.
InOutRepeatingOut // Same as Out, but changes to InOutRepeatingIn if finished.
}
}

View File

@@ -0,0 +1,363 @@
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;
namespace MaterialSkin.Animations
{
class AnimationManager
{
public bool InterruptAnimation { get; set; }
public double Increment { get; set; }
public double SecondaryIncrement { get; set; }
public AnimationType AnimationType { get; set; }
public bool Singular { get; set; }
public delegate void AnimationFinished(object sender);
public event AnimationFinished OnAnimationFinished;
public delegate void AnimationProgress(object sender);
public event AnimationProgress OnAnimationProgress;
private readonly List<double> _animationProgresses;
private readonly List<Point> _animationSources;
private readonly List<AnimationDirection> _animationDirections;
private readonly List<object[]> _animationDatas;
private const double MIN_VALUE = 0.00;
private const double MAX_VALUE = 1.00;
private readonly Timer _animationTimer = new Timer { Interval = 5, Enabled = false };
/// <summary>
/// Constructor
/// </summary>
/// <param name="singular">If true, only one animation is supported. The current animation will be replaced with the new one. If false, a new animation is added to the list.</param>
public AnimationManager(bool singular = true)
{
_animationProgresses = new List<double>();
_animationSources = new List<Point>();
_animationDirections = new List<AnimationDirection>();
_animationDatas = new List<object[]>();
Increment = 0.03;
SecondaryIncrement = 0.03;
AnimationType = AnimationType.Linear;
InterruptAnimation = true;
Singular = singular;
if (Singular)
{
_animationProgresses.Add(0);
_animationSources.Add(new Point(0, 0));
_animationDirections.Add(AnimationDirection.In);
}
_animationTimer.Tick += AnimationTimerOnTick;
}
private void AnimationTimerOnTick(object sender, EventArgs eventArgs)
{
for (var i = 0; i < _animationProgresses.Count; i++)
{
UpdateProgress(i);
if (!Singular)
{
if ((_animationDirections[i] == AnimationDirection.InOutIn && _animationProgresses[i] == MAX_VALUE))
{
_animationDirections[i] = AnimationDirection.InOutOut;
}
else if ((_animationDirections[i] == AnimationDirection.InOutRepeatingIn && _animationProgresses[i] == MIN_VALUE))
{
_animationDirections[i] = AnimationDirection.InOutRepeatingOut;
}
else if ((_animationDirections[i] == AnimationDirection.InOutRepeatingOut && _animationProgresses[i] == MIN_VALUE))
{
_animationDirections[i] = AnimationDirection.InOutRepeatingIn;
}
else if (
(_animationDirections[i] == AnimationDirection.In && _animationProgresses[i] == MAX_VALUE) ||
(_animationDirections[i] == AnimationDirection.Out && _animationProgresses[i] == MIN_VALUE) ||
(_animationDirections[i] == AnimationDirection.InOutOut && _animationProgresses[i] == MIN_VALUE))
{
_animationProgresses.RemoveAt(i);
_animationSources.RemoveAt(i);
_animationDirections.RemoveAt(i);
_animationDatas.RemoveAt(i);
}
}
else
{
if ((_animationDirections[i] == AnimationDirection.InOutIn && _animationProgresses[i] == MAX_VALUE))
{
_animationDirections[i] = AnimationDirection.InOutOut;
}
else if ((_animationDirections[i] == AnimationDirection.InOutRepeatingIn && _animationProgresses[i] == MAX_VALUE))
{
_animationDirections[i] = AnimationDirection.InOutRepeatingOut;
}
else if ((_animationDirections[i] == AnimationDirection.InOutRepeatingOut && _animationProgresses[i] == MIN_VALUE))
{
_animationDirections[i] = AnimationDirection.InOutRepeatingIn;
}
}
}
OnAnimationProgress?.Invoke(this);
}
public bool IsAnimating()
{
return _animationTimer.Enabled;
}
public void StartNewAnimation(AnimationDirection animationDirection, object[] data = null)
{
StartNewAnimation(animationDirection, new Point(0, 0), data);
}
public void StartNewAnimation(AnimationDirection animationDirection, Point animationSource, object[] data = null)
{
if (!IsAnimating() || InterruptAnimation)
{
if (Singular && _animationDirections.Count > 0)
{
_animationDirections[0] = animationDirection;
}
else
{
_animationDirections.Add(animationDirection);
}
if (Singular && _animationSources.Count > 0)
{
_animationSources[0] = animationSource;
}
else
{
_animationSources.Add(animationSource);
}
if (!(Singular && _animationProgresses.Count > 0))
{
switch (_animationDirections[_animationDirections.Count - 1])
{
case AnimationDirection.InOutRepeatingIn:
case AnimationDirection.InOutIn:
case AnimationDirection.In:
_animationProgresses.Add(MIN_VALUE);
break;
case AnimationDirection.InOutRepeatingOut:
case AnimationDirection.InOutOut:
case AnimationDirection.Out:
_animationProgresses.Add(MAX_VALUE);
break;
default:
throw new Exception("Invalid AnimationDirection");
}
}
if (Singular && _animationDatas.Count > 0)
{
_animationDatas[0] = data ?? new object[] { };
}
else
{
_animationDatas.Add(data ?? new object[] { });
}
}
_animationTimer.Start();
}
public void UpdateProgress(int index)
{
switch (_animationDirections[index])
{
case AnimationDirection.InOutRepeatingIn:
case AnimationDirection.InOutIn:
case AnimationDirection.In:
IncrementProgress(index);
break;
case AnimationDirection.InOutRepeatingOut:
case AnimationDirection.InOutOut:
case AnimationDirection.Out:
DecrementProgress(index);
break;
default:
throw new Exception("No AnimationDirection has been set");
}
}
private void IncrementProgress(int index)
{
_animationProgresses[index] += Increment;
if (_animationProgresses[index] > MAX_VALUE)
{
_animationProgresses[index] = MAX_VALUE;
for (int i = 0; i < GetAnimationCount(); i++)
{
if (_animationDirections[i] == AnimationDirection.InOutIn) return;
if (_animationDirections[i] == AnimationDirection.InOutRepeatingIn) return;
if (_animationDirections[i] == AnimationDirection.InOutRepeatingOut) return;
if (_animationDirections[i] == AnimationDirection.InOutOut && _animationProgresses[i] != MAX_VALUE) return;
if (_animationDirections[i] == AnimationDirection.In && _animationProgresses[i] != MAX_VALUE) return;
}
_animationTimer.Stop();
OnAnimationFinished?.Invoke(this);
}
}
private void DecrementProgress(int index)
{
_animationProgresses[index] -= (_animationDirections[index] == AnimationDirection.InOutOut || _animationDirections[index] == AnimationDirection.InOutRepeatingOut) ? SecondaryIncrement : Increment;
if (_animationProgresses[index] < MIN_VALUE)
{
_animationProgresses[index] = MIN_VALUE;
for (var i = 0; i < GetAnimationCount(); i++)
{
if (_animationDirections[i] == AnimationDirection.InOutIn) return;
if (_animationDirections[i] == AnimationDirection.InOutRepeatingIn) return;
if (_animationDirections[i] == AnimationDirection.InOutRepeatingOut) return;
if (_animationDirections[i] == AnimationDirection.InOutOut && _animationProgresses[i] != MIN_VALUE) return;
if (_animationDirections[i] == AnimationDirection.Out && _animationProgresses[i] != MIN_VALUE) return;
}
_animationTimer.Stop();
OnAnimationFinished?.Invoke(this);
}
}
public double GetProgress()
{
if (!Singular)
throw new Exception("Animation is not set to Singular.");
if (_animationProgresses.Count == 0)
throw new Exception("Invalid animation");
return GetProgress(0);
}
public double GetProgress(int index)
{
if (!(index < GetAnimationCount()))
throw new IndexOutOfRangeException("Invalid animation index");
switch (AnimationType)
{
case AnimationType.Linear:
return AnimationLinear.CalculateProgress(_animationProgresses[index]);
case AnimationType.EaseInOut:
return AnimationEaseInOut.CalculateProgress(_animationProgresses[index]);
case AnimationType.EaseOut:
return AnimationEaseOut.CalculateProgress(_animationProgresses[index]);
case AnimationType.CustomQuadratic:
return AnimationCustomQuadratic.CalculateProgress(_animationProgresses[index]);
default:
throw new NotImplementedException("The given AnimationType is not implemented");
}
}
public Point GetSource(int index)
{
if (!(index < GetAnimationCount()))
throw new IndexOutOfRangeException("Invalid animation index");
return _animationSources[index];
}
public Point GetSource()
{
if (!Singular)
throw new Exception("Animation is not set to Singular.");
if (_animationSources.Count == 0)
throw new Exception("Invalid animation");
return _animationSources[0];
}
public AnimationDirection GetDirection()
{
if (!Singular)
throw new Exception("Animation is not set to Singular.");
if (_animationDirections.Count == 0)
throw new Exception("Invalid animation");
return _animationDirections[0];
}
public AnimationDirection GetDirection(int index)
{
if (!(index < _animationDirections.Count))
throw new IndexOutOfRangeException("Invalid animation index");
return _animationDirections[index];
}
public object[] GetData()
{
if (!Singular)
throw new Exception("Animation is not set to Singular.");
if (_animationDatas.Count == 0)
throw new Exception("Invalid animation");
return _animationDatas[0];
}
public object[] GetData(int index)
{
if (!(index < _animationDatas.Count))
throw new IndexOutOfRangeException("Invalid animation index");
return _animationDatas[index];
}
public int GetAnimationCount()
{
return _animationProgresses.Count;
}
public void SetProgress(double progress)
{
if (!Singular)
throw new Exception("Animation is not set to Singular.");
if (_animationProgresses.Count == 0)
throw new Exception("Invalid animation");
_animationProgresses[0] = progress;
}
public void SetDirection(AnimationDirection direction)
{
if (!Singular)
throw new Exception("Animation is not set to Singular.");
if (_animationProgresses.Count == 0)
throw new Exception("Invalid animation");
_animationDirections[0] = direction;
}
public void SetData(object[] data)
{
if (!Singular)
throw new Exception("Animation is not set to Singular.");
if (_animationDatas.Count == 0)
throw new Exception("Invalid animation");
_animationDatas[0] = data;
}
}
}

View File

@@ -0,0 +1,53 @@
using System;
namespace MaterialSkin.Animations
{
enum AnimationType
{
Linear,
EaseInOut,
EaseOut,
CustomQuadratic
}
static class AnimationLinear
{
public static double CalculateProgress(double progress)
{
return progress;
}
}
static class AnimationEaseInOut
{
public static double PI = Math.PI;
public static double PI_HALF = Math.PI / 2;
public static double CalculateProgress(double progress)
{
return EaseInOut(progress);
}
private static double EaseInOut(double s)
{
return s - Math.Sin(s * 2 * PI) / (2 * PI);
}
}
public static class AnimationEaseOut
{
public static double CalculateProgress(double progress)
{
return -1 * progress * (progress - 2);
}
}
public static class AnimationCustomQuadratic
{
public static double CalculateProgress(double progress)
{
var kickoff = 0.6;
return 1 - Math.Cos((Math.Max(progress, kickoff) - kickoff) * Math.PI / (2 - (2 * kickoff)));
}
}
}

View File

@@ -0,0 +1,371 @@
using System.Drawing;
namespace MaterialSkin
{
public class ColorScheme
{
public readonly Color PrimaryColor, DarkPrimaryColor, LightPrimaryColor, AccentColor, TextColor;
public readonly Pen PrimaryPen, DarkPrimaryPen, LightPrimaryPen, AccentPen, TextPen;
public readonly Brush PrimaryBrush, DarkPrimaryBrush, LightPrimaryBrush, AccentBrush, TextBrush;
/// <summary>
/// Defines the Color Scheme to be used for all forms.
/// </summary>
/// <param name="primary">The primary color, a -500 color is suggested here.</param>
/// <param name="darkPrimary">A darker version of the primary color, a -700 color is suggested here.</param>
/// <param name="lightPrimary">A lighter version of the primary color, a -100 color is suggested here.</param>
/// <param name="accent">The accent color, a -200 color is suggested here.</param>
/// <param name="textShade">The text color, the one with the highest contrast is suggested.</param>
public ColorScheme(Primary primary, Primary darkPrimary, Primary lightPrimary, Accent accent, TextShade textShade)
{
//Color
PrimaryColor = ((int)primary).ToColor();
DarkPrimaryColor = ((int)darkPrimary).ToColor();
LightPrimaryColor = ((int)lightPrimary).ToColor();
AccentColor = ((int)accent).ToColor();
TextColor = ((int)textShade).ToColor();
//Pen
PrimaryPen = new Pen(PrimaryColor);
DarkPrimaryPen = new Pen(DarkPrimaryColor);
LightPrimaryPen = new Pen(LightPrimaryColor);
AccentPen = new Pen(AccentColor);
TextPen = new Pen(TextColor);
//Brush
PrimaryBrush = new SolidBrush(PrimaryColor);
DarkPrimaryBrush = new SolidBrush(DarkPrimaryColor);
LightPrimaryBrush = new SolidBrush(LightPrimaryColor);
AccentBrush = new SolidBrush(AccentColor);
TextBrush = new SolidBrush(TextColor);
}
public ColorScheme(int primary, int darkPrimary, int lightPrimary, Accent accent, TextShade textShade)
{
//Color
PrimaryColor = ((int)primary).ToColor();
DarkPrimaryColor = ((int)darkPrimary).ToColor();
LightPrimaryColor = ((int)lightPrimary).ToColor();
AccentColor = ((int)accent).ToColor();
TextColor = ((int)textShade).ToColor();
//Pen
PrimaryPen = new Pen(PrimaryColor);
DarkPrimaryPen = new Pen(DarkPrimaryColor);
LightPrimaryPen = new Pen(LightPrimaryColor);
AccentPen = new Pen(AccentColor);
TextPen = new Pen(TextColor);
//Brush
PrimaryBrush = new SolidBrush(PrimaryColor);
DarkPrimaryBrush = new SolidBrush(DarkPrimaryColor);
LightPrimaryBrush = new SolidBrush(LightPrimaryColor);
AccentBrush = new SolidBrush(AccentColor);
TextBrush = new SolidBrush(TextColor);
}
}
public static class ColorExtension
{
/// <summary>
/// Convert an integer number to a Color.
/// </summary>
/// <returns></returns>
public static Color ToColor(this int argb)
{
return Color.FromArgb(
(argb & 0xff0000) >> 16,
(argb & 0xff00) >> 8,
argb & 0xff);
}
/// <summary>
/// Removes the alpha component of a color.
/// </summary>
/// <param name="color"></param>
/// <returns></returns>
public static Color RemoveAlpha(this Color color)
{
return Color.FromArgb(color.R, color.G, color.B);
}
/// <summary>
/// Converts a 0-100 integer to a 0-255 color component.
/// </summary>
/// <param name="percentage"></param>
/// <returns></returns>
public static int PercentageToColorComponent(this int percentage)
{
return (int)((percentage / 100d) * 255d);
}
}
//Color constantes
public enum TextShade
{
WHITE = 0xFFFFFF,
BLACK = 0x212121
}
public enum Primary
{
Red50 = 0xFFEBEE,
Red100 = 0xFFCDD2,
Red200 = 0xEF9A9A,
Red300 = 0xE57373,
Red400 = 0xEF5350,
Red500 = 0xF44336,
Red600 = 0xE53935,
Red700 = 0xD32F2F,
Red800 = 0xC62828,
Red900 = 0xB71C1C,
Pink50 = 0xFCE4EC,
Pink100 = 0xF8BBD0,
Pink200 = 0xF48FB1,
Pink300 = 0xF06292,
Pink400 = 0xEC407A,
Pink500 = 0xE91E63,
Pink600 = 0xD81B60,
Pink700 = 0xC2185B,
Pink800 = 0xAD1457,
Pink900 = 0x880E4F,
Purple50 = 0xF3E5F5,
Purple100 = 0xE1BEE7,
Purple200 = 0xCE93D8,
Purple300 = 0xBA68C8,
Purple400 = 0xAB47BC,
Purple500 = 0x9C27B0,
Purple600 = 0x8E24AA,
Purple700 = 0x7B1FA2,
Purple800 = 0x6A1B9A,
Purple900 = 0x4A148C,
DeepPurple50 = 0xEDE7F6,
DeepPurple100 = 0xD1C4E9,
DeepPurple200 = 0xB39DDB,
DeepPurple300 = 0x9575CD,
DeepPurple400 = 0x7E57C2,
DeepPurple500 = 0x673AB7,
DeepPurple600 = 0x5E35B1,
DeepPurple700 = 0x512DA8,
DeepPurple800 = 0x4527A0,
DeepPurple900 = 0x311B92,
Indigo50 = 0xE8EAF6,
Indigo100 = 0xC5CAE9,
Indigo200 = 0x9FA8DA,
Indigo300 = 0x7986CB,
Indigo400 = 0x5C6BC0,
Indigo500 = 0x3F51B5,
Indigo600 = 0x3949AB,
Indigo700 = 0x303F9F,
Indigo800 = 0x283593,
Indigo900 = 0x1A237E,
Blue50 = 0xE3F2FD,
Blue100 = 0xBBDEFB,
Blue200 = 0x90CAF9,
Blue300 = 0x64B5F6,
Blue400 = 0x42A5F5,
Blue500 = 0x2196F3,
Blue600 = 0x1E88E5,
Blue700 = 0x1976D2,
Blue800 = 0x1565C0,
Blue900 = 0x0D47A1,
LightBlue50 = 0xE1F5FE,
LightBlue100 = 0xB3E5FC,
LightBlue200 = 0x81D4FA,
LightBlue300 = 0x4FC3F7,
LightBlue400 = 0x29B6F6,
LightBlue500 = 0x03A9F4,
LightBlue600 = 0x039BE5,
LightBlue700 = 0x0288D1,
LightBlue800 = 0x0277BD,
LightBlue900 = 0x01579B,
Cyan50 = 0xE0F7FA,
Cyan100 = 0xB2EBF2,
Cyan200 = 0x80DEEA,
Cyan300 = 0x4DD0E1,
Cyan400 = 0x26C6DA,
Cyan500 = 0x00BCD4,
Cyan600 = 0x00ACC1,
Cyan700 = 0x0097A7,
Cyan800 = 0x00838F,
Cyan900 = 0x006064,
Teal50 = 0xE0F2F1,
Teal100 = 0xB2DFDB,
Teal200 = 0x80CBC4,
Teal300 = 0x4DB6AC,
Teal400 = 0x26A69A,
Teal500 = 0x009688,
Teal600 = 0x00897B,
Teal700 = 0x00796B,
Teal800 = 0x00695C,
Teal900 = 0x004D40,
Green50 = 0xE8F5E9,
Green100 = 0xC8E6C9,
Green200 = 0xA5D6A7,
Green300 = 0x81C784,
Green400 = 0x66BB6A,
Green500 = 0x4CAF50,
Green600 = 0x43A047,
Green700 = 0x388E3C,
Green800 = 0x2E7D32,
Green900 = 0x1B5E20,
LightGreen50 = 0xF1F8E9,
LightGreen100 = 0xDCEDC8,
LightGreen200 = 0xC5E1A5,
LightGreen300 = 0xAED581,
LightGreen400 = 0x9CCC65,
LightGreen500 = 0x8BC34A,
LightGreen600 = 0x7CB342,
LightGreen700 = 0x689F38,
LightGreen800 = 0x558B2F,
LightGreen900 = 0x33691E,
Lime50 = 0xF9FBE7,
Lime100 = 0xF0F4C3,
Lime200 = 0xE6EE9C,
Lime300 = 0xDCE775,
Lime400 = 0xD4E157,
Lime500 = 0xCDDC39,
Lime600 = 0xC0CA33,
Lime700 = 0xAFB42B,
Lime800 = 0x9E9D24,
Lime900 = 0x827717,
Yellow50 = 0xFFFDE7,
Yellow100 = 0xFFF9C4,
Yellow200 = 0xFFF59D,
Yellow300 = 0xFFF176,
Yellow400 = 0xFFEE58,
Yellow500 = 0xFFEB3B,
Yellow600 = 0xFDD835,
Yellow700 = 0xFBC02D,
Yellow800 = 0xF9A825,
Yellow900 = 0xF57F17,
Amber50 = 0xFFF8E1,
Amber100 = 0xFFECB3,
Amber200 = 0xFFE082,
Amber300 = 0xFFD54F,
Amber400 = 0xFFCA28,
Amber500 = 0xFFC107,
Amber600 = 0xFFB300,
Amber700 = 0xFFA000,
Amber800 = 0xFF8F00,
Amber900 = 0xFF6F00,
Orange50 = 0xFFF3E0,
Orange100 = 0xFFE0B2,
Orange200 = 0xFFCC80,
Orange300 = 0xFFB74D,
Orange400 = 0xFFA726,
Orange500 = 0xFF9800,
Orange600 = 0xFB8C00,
Orange700 = 0xF57C00,
Orange800 = 0xEF6C00,
Orange900 = 0xE65100,
DeepOrange50 = 0xFBE9E7,
DeepOrange100 = 0xFFCCBC,
DeepOrange200 = 0xFFAB91,
DeepOrange300 = 0xFF8A65,
DeepOrange400 = 0xFF7043,
DeepOrange500 = 0xFF5722,
DeepOrange600 = 0xF4511E,
DeepOrange700 = 0xE64A19,
DeepOrange800 = 0xD84315,
DeepOrange900 = 0xBF360C,
Brown50 = 0xEFEBE9,
Brown100 = 0xD7CCC8,
Brown200 = 0xBCAAA4,
Brown300 = 0xA1887F,
Brown400 = 0x8D6E63,
Brown500 = 0x795548,
Brown600 = 0x6D4C41,
Brown700 = 0x5D4037,
Brown800 = 0x4E342E,
Brown900 = 0x3E2723,
Grey50 = 0xFAFAFA,
Grey100 = 0xF5F5F5,
Grey200 = 0xEEEEEE,
Grey300 = 0xE0E0E0,
Grey400 = 0xBDBDBD,
Grey500 = 0x9E9E9E,
Grey600 = 0x757575,
Grey700 = 0x616161,
Grey800 = 0x424242,
Grey900 = 0x212121,
BlueGrey50 = 0xECEFF1,
BlueGrey100 = 0xCFD8DC,
BlueGrey200 = 0xB0BEC5,
BlueGrey300 = 0x90A4AE,
BlueGrey400 = 0x78909C,
BlueGrey500 = 0x607D8B,
BlueGrey600 = 0x546E7A,
BlueGrey700 = 0x455A64,
BlueGrey800 = 0x37474F,
BlueGrey900 = 0x263238
}
public enum Accent
{
Red100 = 0xFF8A80,
Red200 = 0xFF5252,
Red400 = 0xFF1744,
Red700 = 0xD50000,
Pink100 = 0xFF80AB,
Pink200 = 0xFF4081,
Pink400 = 0xF50057,
Pink700 = 0xC51162,
Purple100 = 0xEA80FC,
Purple200 = 0xE040FB,
Purple400 = 0xD500F9,
Purple700 = 0xAA00FF,
DeepPurple100 = 0xB388FF,
DeepPurple200 = 0x7C4DFF,
DeepPurple400 = 0x651FFF,
DeepPurple700 = 0x6200EA,
Indigo100 = 0x8C9EFF,
Indigo200 = 0x536DFE,
Indigo400 = 0x3D5AFE,
Indigo700 = 0x304FFE,
Blue100 = 0x82B1FF,
Blue200 = 0x448AFF,
Blue400 = 0x2979FF,
Blue700 = 0x2962FF,
LightBlue100 = 0x80D8FF,
LightBlue200 = 0x40C4FF,
LightBlue400 = 0x00B0FF,
LightBlue700 = 0x0091EA,
Cyan100 = 0x84FFFF,
Cyan200 = 0x18FFFF,
Cyan400 = 0x00E5FF,
Cyan700 = 0x00B8D4,
Teal100 = 0xA7FFEB,
Teal200 = 0x64FFDA,
Teal400 = 0x1DE9B6,
Teal700 = 0x00BFA5,
Green100 = 0xB9F6CA,
Green200 = 0x69F0AE,
Green400 = 0x00E676,
Green700 = 0x00C853,
LightGreen100 = 0xCCFF90,
LightGreen200 = 0xB2FF59,
LightGreen400 = 0x76FF03,
LightGreen700 = 0x64DD17,
Lime100 = 0xF4FF81,
Lime200 = 0xEEFF41,
Lime400 = 0xC6FF00,
Lime700 = 0xAEEA00,
Yellow100 = 0xFFFF8D,
Yellow200 = 0xFFFF00,
Yellow400 = 0xFFEA00,
Yellow700 = 0xFFD600,
Amber100 = 0xFFE57F,
Amber200 = 0xFFD740,
Amber400 = 0xFFC400,
Amber700 = 0xFFAB00,
Orange100 = 0xFFD180,
Orange200 = 0xFFAB40,
Orange400 = 0xFF9100,
Orange700 = 0xFF6D00,
DeepOrange100 = 0xFF9E80,
DeepOrange200 = 0xFF6E40,
DeepOrange400 = 0xFF3D00,
DeepOrange700 = 0xDD2C00
}
}

View File

@@ -0,0 +1,250 @@
using System;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Text;
using System.Windows.Forms;
using MaterialSkin.Animations;
namespace MaterialSkin.Controls
{
public class MaterialCheckBox : CheckBox, IMaterialControl
{
[Browsable(false)]
public int Depth { get; set; }
[Browsable(false)]
public MaterialSkinManager SkinManager => MaterialSkinManager.Instance;
[Browsable(false)]
public MouseState MouseState { get; set; }
[Browsable(false)]
public Point MouseLocation { get; set; }
private bool _ripple;
[Category("Behavior")]
public bool Ripple
{
get { return _ripple; }
set
{
_ripple = value;
AutoSize = AutoSize; //Make AutoSize directly set the bounds.
if (value)
{
Margin = new Padding(0);
}
Invalidate();
}
}
private readonly AnimationManager _animationManager;
private readonly AnimationManager _rippleAnimationManager;
private const int CHECKBOX_SIZE = 18;
private const int CHECKBOX_SIZE_HALF = CHECKBOX_SIZE / 2;
private const int CHECKBOX_INNER_BOX_SIZE = CHECKBOX_SIZE - 4;
private int _boxOffset;
private Rectangle _boxRectangle;
public MaterialCheckBox()
{
_animationManager = new AnimationManager
{
AnimationType = AnimationType.EaseInOut,
Increment = 0.05
};
_rippleAnimationManager = new AnimationManager(false)
{
AnimationType = AnimationType.Linear,
Increment = 0.10,
SecondaryIncrement = 0.08
};
_animationManager.OnAnimationProgress += sender => Invalidate();
_rippleAnimationManager.OnAnimationProgress += sender => Invalidate();
CheckedChanged += (sender, args) =>
{
_animationManager.StartNewAnimation(Checked ? AnimationDirection.In : AnimationDirection.Out);
};
Ripple = true;
MouseLocation = new Point(-1, -1);
}
protected override void OnSizeChanged(EventArgs e)
{
base.OnSizeChanged(e);
_boxOffset = Height / 2 - 9;
_boxRectangle = new Rectangle(_boxOffset, _boxOffset, CHECKBOX_SIZE - 1, CHECKBOX_SIZE - 1);
}
public override Size GetPreferredSize(Size proposedSize)
{
var w = _boxOffset + CHECKBOX_SIZE + 2 + (int)CreateGraphics().MeasureString(Text, SkinManager.ROBOTO_MEDIUM_10).Width;
return Ripple ? new Size(w, 30) : new Size(w, 20);
}
private static readonly Point[] CheckmarkLine = { new Point(3, 8), new Point(7, 12), new Point(14, 5) };
private const int TEXT_OFFSET = 22;
protected override void OnPaint(PaintEventArgs pevent)
{
var g = pevent.Graphics;
g.SmoothingMode = SmoothingMode.AntiAlias;
g.TextRenderingHint = TextRenderingHint.AntiAlias;
// clear the control
g.Clear(Parent.BackColor);
var CHECKBOX_CENTER = _boxOffset + CHECKBOX_SIZE_HALF - 1;
var animationProgress = _animationManager.GetProgress();
var colorAlpha = Enabled ? (int)(animationProgress * 255.0) : SkinManager.GetCheckBoxOffDisabledColor().A;
var backgroundAlpha = Enabled ? (int)(SkinManager.GetCheckboxOffColor().A * (1.0 - animationProgress)) : SkinManager.GetCheckBoxOffDisabledColor().A;
var brush = new SolidBrush(Color.FromArgb(colorAlpha, Enabled ? SkinManager.ColorScheme.AccentColor : SkinManager.GetCheckBoxOffDisabledColor()));
var brush3 = new SolidBrush(Enabled ? SkinManager.ColorScheme.AccentColor : SkinManager.GetCheckBoxOffDisabledColor());
var pen = new Pen(brush.Color);
// draw ripple animation
if (Ripple && _rippleAnimationManager.IsAnimating())
{
for (var i = 0; i < _rippleAnimationManager.GetAnimationCount(); i++)
{
var animationValue = _rippleAnimationManager.GetProgress(i);
var animationSource = new Point(CHECKBOX_CENTER, CHECKBOX_CENTER);
var rippleBrush = new SolidBrush(Color.FromArgb((int)((animationValue * 40)), ((bool)_rippleAnimationManager.GetData(i)[0]) ? Color.Black : brush.Color));
var rippleHeight = (Height % 2 == 0) ? Height - 3 : Height - 2;
var rippleSize = (_rippleAnimationManager.GetDirection(i) == AnimationDirection.InOutIn) ? (int)(rippleHeight * (0.8d + (0.2d * animationValue))) : rippleHeight;
using (var path = DrawHelper.CreateRoundRect(animationSource.X - rippleSize / 2, animationSource.Y - rippleSize / 2, rippleSize, rippleSize, rippleSize / 2))
{
g.FillPath(rippleBrush, path);
}
rippleBrush.Dispose();
}
}
brush3.Dispose();
var checkMarkLineFill = new Rectangle(_boxOffset, _boxOffset, (int)((int)(FontHeight * 1.1) * animationProgress), (int)(FontHeight * 1.1));
using (var checkmarkPath = DrawHelper.CreateRoundRect(_boxOffset, _boxOffset, (int)(FontHeight*1.1), (int)(FontHeight * 1.1), 1f))
{
var brush2 = new SolidBrush(DrawHelper.BlendColor(Parent.BackColor, Enabled ? SkinManager.GetCheckboxOffColor() : SkinManager.GetCheckBoxOffDisabledColor(), backgroundAlpha));
var pen2 = new Pen(brush2.Color);
g.FillPath(brush2, checkmarkPath);
g.DrawPath(pen2, checkmarkPath);
g.FillRectangle(new SolidBrush(Parent.BackColor), _boxOffset + 2, _boxOffset + 2, (int)(FontHeight * 1.1) -4, (int)(FontHeight * 1.1) -4);
g.DrawRectangle(new Pen(Parent.BackColor), _boxOffset + 2, _boxOffset + 2, (int)(FontHeight * 1.1) -4, (int)(FontHeight * 1.1) - 4);
brush2.Dispose();
pen2.Dispose();
if (Enabled)
{
g.FillPath(brush, checkmarkPath);
g.DrawPath(pen, checkmarkPath);
}
else if (Checked)
{
g.SmoothingMode = SmoothingMode.None;
g.FillRectangle(brush, _boxOffset + 2, _boxOffset + 2, CHECKBOX_INNER_BOX_SIZE, CHECKBOX_INNER_BOX_SIZE);
g.SmoothingMode = SmoothingMode.AntiAlias;
}
g.DrawImageUnscaledAndClipped(DrawCheckMarkBitmap(), checkMarkLineFill);
}
// draw checkbox text
SizeF stringSize = g.MeasureString(Text, Font);
g.DrawString(
Text,
Font,
Enabled ? SkinManager.GetPrimaryTextBrush() : SkinManager.GetDisabledOrHintBrush(),
_boxOffset + TEXT_OFFSET, Height / 2 - stringSize.Height / 2);
// dispose used paint objects
pen.Dispose();
brush.Dispose();
}
private Bitmap DrawCheckMarkBitmap()
{
var checkMark = new Bitmap(CHECKBOX_SIZE, CHECKBOX_SIZE);
var g = Graphics.FromImage(checkMark);
// clear everything, transparent
g.Clear(Color.Transparent);
// draw the checkmark lines
using (var pen = new Pen(Parent.BackColor, 2))
{
g.DrawLines(pen, CheckmarkLine);
}
return checkMark;
}
public override bool AutoSize
{
get { return base.AutoSize; }
set
{
base.AutoSize = value;
if (value)
{
Size = new Size(10, 10);
}
}
}
private bool IsMouseInCheckArea()
{
return _boxRectangle.Contains(MouseLocation);
}
protected override void OnCreateControl()
{
base.OnCreateControl();
Font = SkinManager.ROBOTO_MEDIUM_10;
if (DesignMode) return;
MouseState = MouseState.OUT;
MouseEnter += (sender, args) =>
{
MouseState = MouseState.HOVER;
};
MouseLeave += (sender, args) =>
{
MouseLocation = new Point(-1, -1);
MouseState = MouseState.OUT;
};
MouseDown += (sender, args) =>
{
MouseState = MouseState.DOWN;
if (Ripple && args.Button == MouseButtons.Left && IsMouseInCheckArea())
{
_rippleAnimationManager.SecondaryIncrement = 0;
_rippleAnimationManager.StartNewAnimation(AnimationDirection.InOutIn, new object[] { Checked });
}
};
MouseUp += (sender, args) =>
{
MouseState = MouseState.HOVER;
_rippleAnimationManager.SecondaryIncrement = 0.08;
};
MouseMove += (sender, args) =>
{
MouseLocation = args.Location;
Cursor = IsMouseInCheckArea() ? Cursors.Hand : Cursors.Default;
};
}
}
}

View File

@@ -0,0 +1,44 @@
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;
namespace MaterialSkin.Controls
{
public partial class MaterialComboBox : ComboBox
{
[Browsable(false)]
public MaterialSkinManager SkinManager => MaterialSkinManager.Instance;
public MaterialComboBox()
{
DrawMode = DrawMode.OwnerDrawFixed;
DrawItem += AdvancedComboBox_DrawItem;
}
void AdvancedComboBox_DrawItem(object sender, DrawItemEventArgs e)
{
if (e.Index < 0)
return;
ComboBox combo = sender as ComboBox;
if ((e.State & DrawItemState.Selected) == DrawItemState.Selected)
e.Graphics.FillRectangle(new SolidBrush(SkinManager.ColorScheme.AccentColor),
e.Bounds);
else
e.Graphics.FillRectangle(new SolidBrush(combo.BackColor),
e.Bounds);
e.Graphics.DrawString(combo.Items[e.Index].ToString(), e.Font,
SkinManager.GetRaisedButtonTextBrush((e.State & DrawItemState.Selected) == DrawItemState.Selected),
new Point(e.Bounds.X, e.Bounds.Y));
e.DrawFocusRectangle();
}
}
}

View File

@@ -0,0 +1,195 @@
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Text;
using System.Windows.Forms;
using MaterialSkin.Animations;
namespace MaterialSkin.Controls
{
public class MaterialContextMenuStrip : ContextMenuStrip, IMaterialControl
{
//Properties for managing the material design properties
[Browsable(false)]
public int Depth { get; set; }
[Browsable(false)]
public MaterialSkinManager SkinManager => MaterialSkinManager.Instance;
[Browsable(false)]
public MouseState MouseState { get; set; }
internal AnimationManager AnimationManager;
internal Point AnimationSource;
public delegate void ItemClickStart(object sender, ToolStripItemClickedEventArgs e);
public event ItemClickStart OnItemClickStart;
public MaterialContextMenuStrip()
{
Renderer = new MaterialToolStripRender();
AnimationManager = new AnimationManager(false)
{
Increment = 0.07,
AnimationType = AnimationType.Linear
};
AnimationManager.OnAnimationProgress += sender => Invalidate();
AnimationManager.OnAnimationFinished += sender => OnItemClicked(_delayesArgs);
BackColor = SkinManager.GetApplicationBackgroundColor();
}
protected override void OnMouseUp(MouseEventArgs mea)
{
base.OnMouseUp(mea);
AnimationSource = mea.Location;
}
private ToolStripItemClickedEventArgs _delayesArgs;
protected override void OnItemClicked(ToolStripItemClickedEventArgs e)
{
if (e.ClickedItem != null && !(e.ClickedItem is ToolStripSeparator))
{
if (e == _delayesArgs)
{
//The event has been fired manualy because the args are the ones we saved for delay
base.OnItemClicked(e);
}
else
{
//Interrupt the default on click, saving the args for the delay which is needed to display the animaton
_delayesArgs = e;
//Fire custom event to trigger actions directly but keep cms open
OnItemClickStart?.Invoke(this, e);
//Start animation
AnimationManager.StartNewAnimation(AnimationDirection.In);
}
}
}
}
public class MaterialToolStripMenuItem : ToolStripMenuItem
{
public MaterialToolStripMenuItem()
{
AutoSize = false;
Size = new Size(120, 30);
}
protected override ToolStripDropDown CreateDefaultDropDown()
{
var baseDropDown = base.CreateDefaultDropDown();
if (DesignMode) return baseDropDown;
var defaultDropDown = new MaterialContextMenuStrip();
defaultDropDown.Items.AddRange(baseDropDown.Items);
return defaultDropDown;
}
}
internal class MaterialToolStripRender : ToolStripProfessionalRenderer, IMaterialControl
{
//Properties for managing the material design properties
public int Depth { get; set; }
public MaterialSkinManager SkinManager => MaterialSkinManager.Instance;
public MouseState MouseState { get; set; }
protected override void OnRenderItemText(ToolStripItemTextRenderEventArgs e)
{
var g = e.Graphics;
g.TextRenderingHint = TextRenderingHint.AntiAlias;
var itemRect = GetItemRect(e.Item);
var textRect = new Rectangle(24, itemRect.Y, itemRect.Width - (24 + 16), itemRect.Height);
g.DrawString(
e.Text,
SkinManager.ROBOTO_MEDIUM_10,
e.Item.Enabled ? SkinManager.GetPrimaryTextBrush() : SkinManager.GetDisabledOrHintBrush(),
textRect,
new StringFormat { LineAlignment = StringAlignment.Center });
}
protected override void OnRenderMenuItemBackground(ToolStripItemRenderEventArgs e)
{
var g = e.Graphics;
g.Clear(SkinManager.GetApplicationBackgroundColor());
//Draw background
var itemRect = GetItemRect(e.Item);
g.FillRectangle(e.Item.Selected && e.Item.Enabled ? SkinManager.GetCmsSelectedItemBrush() : new SolidBrush(SkinManager.GetApplicationBackgroundColor()), itemRect);
//Ripple animation
var toolStrip = e.ToolStrip as MaterialContextMenuStrip;
if (toolStrip != null)
{
var animationManager = toolStrip.AnimationManager;
var animationSource = toolStrip.AnimationSource;
if (toolStrip.AnimationManager.IsAnimating() && e.Item.Bounds.Contains(animationSource))
{
for (int i = 0; i < animationManager.GetAnimationCount(); i++)
{
var animationValue = animationManager.GetProgress(i);
var rippleBrush = new SolidBrush(Color.FromArgb((int)(51 - (animationValue * 50)), Color.Black));
var rippleSize = (int)(animationValue * itemRect.Width * 2.5);
g.FillEllipse(rippleBrush, new Rectangle(animationSource.X - rippleSize / 2, itemRect.Y - itemRect.Height, rippleSize, itemRect.Height * 3));
}
}
}
}
protected override void OnRenderImageMargin(ToolStripRenderEventArgs e)
{
//base.OnRenderImageMargin(e);
}
protected override void OnRenderSeparator(ToolStripSeparatorRenderEventArgs e)
{
var g = e.Graphics;
g.FillRectangle(new SolidBrush(SkinManager.GetApplicationBackgroundColor()), e.Item.Bounds);
g.DrawLine(
new Pen(SkinManager.GetDividersColor()),
new Point(e.Item.Bounds.Left, e.Item.Bounds.Height / 2),
new Point(e.Item.Bounds.Right, e.Item.Bounds.Height / 2));
}
protected override void OnRenderToolStripBorder(ToolStripRenderEventArgs e)
{
var g = e.Graphics;
g.DrawRectangle(
new Pen(SkinManager.GetDividersColor()),
new Rectangle(e.AffectedBounds.X, e.AffectedBounds.Y, e.AffectedBounds.Width - 1, e.AffectedBounds.Height - 1));
}
protected override void OnRenderArrow(ToolStripArrowRenderEventArgs e)
{
var g = e.Graphics;
const int ARROW_SIZE = 4;
var arrowMiddle = new Point(e.ArrowRectangle.X + e.ArrowRectangle.Width / 2, e.ArrowRectangle.Y + e.ArrowRectangle.Height / 2);
var arrowBrush = e.Item.Enabled ? SkinManager.GetPrimaryTextBrush() : SkinManager.GetDisabledOrHintBrush();
using (var arrowPath = new GraphicsPath())
{
arrowPath.AddLines(
new[] {
new Point(arrowMiddle.X - ARROW_SIZE, arrowMiddle.Y - ARROW_SIZE),
new Point(arrowMiddle.X, arrowMiddle.Y),
new Point(arrowMiddle.X - ARROW_SIZE, arrowMiddle.Y + ARROW_SIZE) });
arrowPath.CloseFigure();
g.FillPath(arrowBrush, arrowPath);
}
}
private Rectangle GetItemRect(ToolStripItem item)
{
return new Rectangle(0, item.ContentRectangle.Y, item.ContentRectangle.Width + 4, item.ContentRectangle.Height);
}
}
}

View File

@@ -0,0 +1,27 @@
using System.ComponentModel;
using System.Windows.Forms;
namespace MaterialSkin.Controls
{
public sealed class MaterialDivider : Control, IMaterialControl
{
[Browsable(false)]
public int Depth { get; set; }
[Browsable(false)]
public MaterialSkinManager SkinManager => MaterialSkinManager.Instance;
[Browsable(false)]
public MouseState MouseState { get; set; }
public MaterialDivider()
{
SetStyle(ControlStyles.SupportsTransparentBackColor, true);
}
protected override void OnPaintBackground(PaintEventArgs pevent)
{
BackColor = SkinManager.ColorScheme.PrimaryColor;
base.OnPaintBackground(pevent);
}
}
}

View File

@@ -0,0 +1,200 @@
using System;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Text;
using System.Windows.Forms;
using MaterialSkin.Animations;
namespace MaterialSkin.Controls
{
public class MaterialFlatButton : Button, IMaterialControl
{
[Browsable(false)]
public int Depth { get; set; }
[Browsable(false)]
public MaterialSkinManager SkinManager => MaterialSkinManager.Instance;
[Browsable(false)]
public MouseState MouseState { get; set; }
public bool Primary { get; set; }
private readonly AnimationManager _animationManager;
private readonly AnimationManager _hoverAnimationManager;
private SizeF _textSize;
private Image _icon;
public Image Icon
{
get { return _icon; }
set
{
_icon = value;
if (AutoSize)
Size = GetPreferredSize();
Invalidate();
}
}
public MaterialFlatButton()
{
Primary = false;
_animationManager = new AnimationManager(false)
{
Increment = 0.03,
AnimationType = AnimationType.EaseOut
};
_hoverAnimationManager = new AnimationManager
{
Increment = 0.07,
AnimationType = AnimationType.Linear
};
_hoverAnimationManager.OnAnimationProgress += sender => Invalidate();
_animationManager.OnAnimationProgress += sender => Invalidate();
AutoSizeMode = AutoSizeMode.GrowAndShrink;
Margin = new Padding(4, 6, 4, 6);
Padding = new Padding(0);
}
public override string Text
{
get { return base.Text; }
set
{
base.Text = value;
_textSize = CreateGraphics().MeasureString(value.ToUpper(), SkinManager.ROBOTO_MEDIUM_10);
if (AutoSize)
Size = GetPreferredSize();
Invalidate();
}
}
protected override void OnPaint(PaintEventArgs pevent)
{
var g = pevent.Graphics;
g.TextRenderingHint = TextRenderingHint.AntiAlias;
g.Clear(Parent.BackColor);
//Hover
Color c = SkinManager.GetFlatButtonHoverBackgroundColor();
using (Brush b = new SolidBrush(Color.FromArgb((int)(_hoverAnimationManager.GetProgress() * c.A), c.RemoveAlpha())))
g.FillRectangle(b, ClientRectangle);
//Ripple
if (_animationManager.IsAnimating())
{
g.SmoothingMode = SmoothingMode.AntiAlias;
for (var i = 0; i < _animationManager.GetAnimationCount(); i++)
{
var animationValue = _animationManager.GetProgress(i);
var animationSource = _animationManager.GetSource(i);
using (Brush rippleBrush = new SolidBrush(Color.FromArgb((int)(101 - (animationValue * 100)), Color.Black)))
{
var rippleSize = (int)(animationValue * Width * 2);
g.FillEllipse(rippleBrush, new Rectangle(animationSource.X - rippleSize / 2, animationSource.Y - rippleSize / 2, rippleSize, rippleSize));
}
}
g.SmoothingMode = SmoothingMode.None;
}
//Icon
var iconRect = new Rectangle(8, 6, 24, 24);
if (string.IsNullOrEmpty(Text))
// Center Icon
iconRect.X += 2;
if (Icon != null)
g.DrawImage(Icon, iconRect);
//Text
var textRect = ClientRectangle;
if (Icon != null)
{
//
// Resize and move Text container
//
// First 8: left padding
// 24: icon width
// Second 4: space between Icon and Text
// Third 8: right padding
textRect.Width -= 8 + 24 + 4 + 8;
// First 8: left padding
// 24: icon width
// Second 4: space between Icon and Text
textRect.X += 8 + 24 + 4;
}
g.DrawString(
Text.ToUpper(),
SkinManager.ROBOTO_MEDIUM_10,
Enabled ? (Primary ? SkinManager.ColorScheme.PrimaryBrush : SkinManager.GetPrimaryTextBrush()) : SkinManager.GetFlatButtonDisabledTextBrush(),
textRect,
new StringFormat { Alignment = StringAlignment.Center, LineAlignment = StringAlignment.Center }
);
}
private Size GetPreferredSize()
{
return GetPreferredSize(new Size(0, 0));
}
public override Size GetPreferredSize(Size proposedSize)
{
// Provides extra space for proper padding for content
var extra = 16;
if (Icon != null)
// 24 is for icon size
// 4 is for the space between icon & text
extra += 24 + 4;
return new Size((int)Math.Ceiling(_textSize.Width) + extra, 36);
}
protected override void OnCreateControl()
{
base.OnCreateControl();
if (DesignMode) return;
MouseState = MouseState.OUT;
MouseEnter += (sender, args) =>
{
MouseState = MouseState.HOVER;
_hoverAnimationManager.StartNewAnimation(AnimationDirection.In);
Invalidate();
};
MouseLeave += (sender, args) =>
{
MouseState = MouseState.OUT;
_hoverAnimationManager.StartNewAnimation(AnimationDirection.Out);
Invalidate();
};
MouseDown += (sender, args) =>
{
if (args.Button == MouseButtons.Left)
{
MouseState = MouseState.DOWN;
_animationManager.StartNewAnimation(AnimationDirection.In, args.Location);
Invalidate();
}
};
MouseUp += (sender, args) =>
{
MouseState = MouseState.HOVER;
Invalidate();
};
}
}
}

View File

@@ -0,0 +1,619 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Text;
using System.Linq;
using System.Runtime.InteropServices;
using System.Windows.Forms;
namespace MaterialSkin.Controls
{
public class MaterialForm : Form, IMaterialControl
{
[Browsable(false)]
public int Depth { get; set; }
[Browsable(false)]
public MaterialSkinManager SkinManager => MaterialSkinManager.Instance;
[Browsable(false)]
public MouseState MouseState { get; set; }
public new FormBorderStyle FormBorderStyle { get { return base.FormBorderStyle; } set { base.FormBorderStyle = value; } }
public bool Sizable { get; set; }
[DllImport("user32.dll")]
public static extern int SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam);
[DllImport("user32.dll")]
public static extern bool ReleaseCapture();
[DllImport("user32.dll")]
public static extern int TrackPopupMenuEx(IntPtr hmenu, uint fuFlags, int x, int y, IntPtr hwnd, IntPtr lptpm);
[DllImport("user32.dll")]
public static extern IntPtr GetSystemMenu(IntPtr hWnd, bool bRevert);
[DllImport("user32.dll")]
public static extern IntPtr MonitorFromWindow(IntPtr hwnd, uint dwFlags);
[DllImport("User32.dll", CharSet = CharSet.Auto)]
public static extern bool GetMonitorInfo(HandleRef hmonitor, [In, Out] MONITORINFOEX info);
public const int WM_NCLBUTTONDOWN = 0xA1;
public const int HT_CAPTION = 0x2;
public const int WM_MOUSEMOVE = 0x0200;
public const int WM_LBUTTONDOWN = 0x0201;
public const int WM_LBUTTONUP = 0x0202;
public const int WM_LBUTTONDBLCLK = 0x0203;
public const int WM_RBUTTONDOWN = 0x0204;
private const int HTBOTTOMLEFT = 16;
private const int HTBOTTOMRIGHT = 17;
private const int HTLEFT = 10;
private const int HTRIGHT = 11;
private const int HTBOTTOM = 15;
private const int HTTOP = 12;
private const int HTTOPLEFT = 13;
private const int HTTOPRIGHT = 14;
private const int BORDER_WIDTH = 7;
private ResizeDirection _resizeDir;
private ButtonState _buttonState = ButtonState.None;
private const int WMSZ_TOP = 3;
private const int WMSZ_TOPLEFT = 4;
private const int WMSZ_TOPRIGHT = 5;
private const int WMSZ_LEFT = 1;
private const int WMSZ_RIGHT = 2;
private const int WMSZ_BOTTOM = 6;
private const int WMSZ_BOTTOMLEFT = 7;
private const int WMSZ_BOTTOMRIGHT = 8;
private readonly Dictionary<int, int> _resizingLocationsToCmd = new Dictionary<int, int>
{
{HTTOP, WMSZ_TOP},
{HTTOPLEFT, WMSZ_TOPLEFT},
{HTTOPRIGHT, WMSZ_TOPRIGHT},
{HTLEFT, WMSZ_LEFT},
{HTRIGHT, WMSZ_RIGHT},
{HTBOTTOM, WMSZ_BOTTOM},
{HTBOTTOMLEFT, WMSZ_BOTTOMLEFT},
{HTBOTTOMRIGHT, WMSZ_BOTTOMRIGHT}
};
private const int STATUS_BAR_BUTTON_WIDTH = STATUS_BAR_HEIGHT;
private const int STATUS_BAR_HEIGHT = 24;
private const int ACTION_BAR_HEIGHT = 40;
private const uint TPM_LEFTALIGN = 0x0000;
private const uint TPM_RETURNCMD = 0x0100;
private const int WM_SYSCOMMAND = 0x0112;
private const int WS_MINIMIZEBOX = 0x20000;
private const int WS_SYSMENU = 0x00080000;
private const int MONITOR_DEFAULTTONEAREST = 2;
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto, Pack = 4)]
public class MONITORINFOEX
{
public int cbSize = Marshal.SizeOf(typeof(MONITORINFOEX));
public RECT rcMonitor = new RECT();
public RECT rcWork = new RECT();
public int dwFlags = 0;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)]
public char[] szDevice = new char[32];
}
[StructLayout(LayoutKind.Sequential)]
public struct RECT
{
public int left;
public int top;
public int right;
public int bottom;
public int Width()
{
return right - left;
}
public int Height()
{
return bottom - top;
}
}
private enum ResizeDirection
{
BottomLeft,
Left,
Right,
BottomRight,
Bottom,
None
}
private enum ButtonState
{
XOver,
MaxOver,
MinOver,
XDown,
MaxDown,
MinDown,
None
}
private readonly Cursor[] _resizeCursors = { Cursors.SizeNESW, Cursors.SizeWE, Cursors.SizeNWSE, Cursors.SizeWE, Cursors.SizeNS };
private Rectangle _minButtonBounds;
private Rectangle _maxButtonBounds;
private Rectangle _xButtonBounds;
private Rectangle _actionBarBounds;
private Rectangle _statusBarBounds;
private bool _maximized;
private Size _previousSize;
private Point _previousLocation;
private bool _headerMouseDown;
private MouseMessageFilter _mouseMessageFilter;
public MaterialForm()
{
FormBorderStyle = FormBorderStyle.None;
AutoScaleMode = AutoScaleMode.None;
DoubleBuffered = true;
SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.ResizeRedraw, true);
// This enables the form to trigger the MouseMove event even when mouse is over another control
//_mouseMessageFilter = new MouseMessageFilter();
//Application.AddMessageFilter(_mouseMessageFilter);
//MouseMessageFilter.MouseMove += OnGlobalMouseMove;
}
public void RemoveMessageFilter()
{
Application.RemoveMessageFilter(_mouseMessageFilter);
MouseMessageFilter.MouseMove -= OnGlobalMouseMove;
}
protected override void WndProc(ref Message m)
{
base.WndProc(ref m);
if (DesignMode || IsDisposed) return;
if (m.Msg == WM_LBUTTONDBLCLK)
{
MaximizeWindow(!_maximized);
}
else if (m.Msg == WM_MOUSEMOVE && _maximized &&
(_statusBarBounds.Contains(PointToClient(Cursor.Position)) || _actionBarBounds.Contains(PointToClient(Cursor.Position))) &&
!(_minButtonBounds.Contains(PointToClient(Cursor.Position)) || _maxButtonBounds.Contains(PointToClient(Cursor.Position)) || _xButtonBounds.Contains(PointToClient(Cursor.Position))))
{
if (_headerMouseDown)
{
_maximized = false;
_headerMouseDown = false;
var mousePoint = PointToClient(Cursor.Position);
if (mousePoint.X < Width / 2)
Location = mousePoint.X < _previousSize.Width / 2 ?
new Point(Cursor.Position.X - mousePoint.X, Cursor.Position.Y - mousePoint.Y) :
new Point(Cursor.Position.X - _previousSize.Width / 2, Cursor.Position.Y - mousePoint.Y);
else
Location = Width - mousePoint.X < _previousSize.Width / 2 ?
new Point(Cursor.Position.X - _previousSize.Width + Width - mousePoint.X, Cursor.Position.Y - mousePoint.Y) :
new Point(Cursor.Position.X - _previousSize.Width / 2, Cursor.Position.Y - mousePoint.Y);
Size = _previousSize;
ReleaseCapture();
SendMessage(Handle, WM_NCLBUTTONDOWN, HT_CAPTION, 0);
}
}
else if (m.Msg == WM_LBUTTONDOWN &&
(_statusBarBounds.Contains(PointToClient(Cursor.Position)) || _actionBarBounds.Contains(PointToClient(Cursor.Position))) &&
!(_minButtonBounds.Contains(PointToClient(Cursor.Position)) || _maxButtonBounds.Contains(PointToClient(Cursor.Position)) || _xButtonBounds.Contains(PointToClient(Cursor.Position))))
{
if (!_maximized)
{
ReleaseCapture();
SendMessage(Handle, WM_NCLBUTTONDOWN, HT_CAPTION, 0);
}
else
{
_headerMouseDown = true;
}
}
else if (m.Msg == WM_RBUTTONDOWN)
{
Point cursorPos = PointToClient(Cursor.Position);
if (_statusBarBounds.Contains(cursorPos) && !_minButtonBounds.Contains(cursorPos) &&
!_maxButtonBounds.Contains(cursorPos) && !_xButtonBounds.Contains(cursorPos))
{
// Show default system menu when right clicking titlebar
var id = TrackPopupMenuEx(GetSystemMenu(Handle, false), TPM_LEFTALIGN | TPM_RETURNCMD, Cursor.Position.X, Cursor.Position.Y, Handle, IntPtr.Zero);
// Pass the command as a WM_SYSCOMMAND message
SendMessage(Handle, WM_SYSCOMMAND, id, 0);
}
}
else if (m.Msg == WM_NCLBUTTONDOWN)
{
// This re-enables resizing by letting the application know when the
// user is trying to resize a side. This is disabled by default when using WS_SYSMENU.
if (!Sizable) return;
byte bFlag = 0;
// Get which side to resize from
if (_resizingLocationsToCmd.ContainsKey((int)m.WParam))
bFlag = (byte)_resizingLocationsToCmd[(int)m.WParam];
if (bFlag != 0)
SendMessage(Handle, WM_SYSCOMMAND, 0xF000 | bFlag, (int)m.LParam);
}
else if (m.Msg == WM_LBUTTONUP)
{
_headerMouseDown = false;
}
}
public bool DropShadow { get; set; } = true;
protected override CreateParams CreateParams
{
get
{
const int CS_DROPSHADOW = 0x20000;
var par = base.CreateParams;
// WS_SYSMENU: Trigger the creation of the system menu
// WS_MINIMIZEBOX: Allow minimizing from taskbar
par.Style = par.Style | WS_MINIMIZEBOX | WS_SYSMENU; // Turn on the WS_MINIMIZEBOX style flag
if(DropShadow)
par.ClassStyle |= CS_DROPSHADOW;
return par;
}
}
protected override void OnMouseDown(MouseEventArgs e)
{
if (DesignMode) return;
UpdateButtons(e);
if (e.Button == MouseButtons.Left && !_maximized)
ResizeForm(_resizeDir);
base.OnMouseDown(e);
}
protected override void OnMouseLeave(EventArgs e)
{
base.OnMouseLeave(e);
if (DesignMode) return;
_buttonState = ButtonState.None;
Invalidate();
}
protected override void OnMouseMove(MouseEventArgs e)
{
base.OnMouseMove(e);
if (DesignMode) return;
if (Sizable)
{
//True if the mouse is hovering over a child control
var isChildUnderMouse = GetChildAtPoint(e.Location) != null;
if (e.Location.X < BORDER_WIDTH && e.Location.Y > Height - BORDER_WIDTH && !isChildUnderMouse && !_maximized)
{
_resizeDir = ResizeDirection.BottomLeft;
Cursor = Cursors.SizeNESW;
}
else if (e.Location.X < BORDER_WIDTH && !isChildUnderMouse && !_maximized)
{
_resizeDir = ResizeDirection.Left;
Cursor = Cursors.SizeWE;
}
else if (e.Location.X > Width - BORDER_WIDTH && e.Location.Y > Height - BORDER_WIDTH && !isChildUnderMouse && !_maximized)
{
_resizeDir = ResizeDirection.BottomRight;
Cursor = Cursors.SizeNWSE;
}
else if (e.Location.X > Width - BORDER_WIDTH && !isChildUnderMouse && !_maximized)
{
_resizeDir = ResizeDirection.Right;
Cursor = Cursors.SizeWE;
}
else if (e.Location.Y > Height - BORDER_WIDTH && !isChildUnderMouse && !_maximized)
{
_resizeDir = ResizeDirection.Bottom;
Cursor = Cursors.SizeNS;
}
else
{
_resizeDir = ResizeDirection.None;
//Only reset the cursor when needed, this prevents it from flickering when a child control changes the cursor to its own needs
if (_resizeCursors.Contains(Cursor))
{
Cursor = Cursors.Default;
}
}
}
UpdateButtons(e);
}
protected void OnGlobalMouseMove(object sender, MouseEventArgs e)
{
if (IsDisposed) return;
// Convert to client position and pass to Form.MouseMove
var clientCursorPos = PointToClient(e.Location);
var newE = new MouseEventArgs(MouseButtons.None, 0, clientCursorPos.X, clientCursorPos.Y, 0);
OnMouseMove(newE);
}
private void UpdateButtons(MouseEventArgs e, bool up = false)
{
if (DesignMode) return;
var oldState = _buttonState;
bool showMin = MinimizeBox && ControlBox;
bool showMax = MaximizeBox && ControlBox;
if (e.Button == MouseButtons.Left && !up)
{
if (showMin && !showMax && _maxButtonBounds.Contains(e.Location))
_buttonState = ButtonState.MinDown;
else if (showMin && showMax && _minButtonBounds.Contains(e.Location))
_buttonState = ButtonState.MinDown;
else if (showMax && _maxButtonBounds.Contains(e.Location))
_buttonState = ButtonState.MaxDown;
else if (ControlBox && _xButtonBounds.Contains(e.Location))
_buttonState = ButtonState.XDown;
else
_buttonState = ButtonState.None;
}
else
{
if (showMin && !showMax && _maxButtonBounds.Contains(e.Location))
{
_buttonState = ButtonState.MinOver;
if (oldState == ButtonState.MinDown && up)
WindowState = FormWindowState.Minimized;
}
else if (showMin && showMax && _minButtonBounds.Contains(e.Location))
{
_buttonState = ButtonState.MinOver;
if (oldState == ButtonState.MinDown && up)
WindowState = FormWindowState.Minimized;
}
else if (MaximizeBox && ControlBox && _maxButtonBounds.Contains(e.Location))
{
_buttonState = ButtonState.MaxOver;
if (oldState == ButtonState.MaxDown && up)
MaximizeWindow(!_maximized);
}
else if (ControlBox && _xButtonBounds.Contains(e.Location))
{
_buttonState = ButtonState.XOver;
if (oldState == ButtonState.XDown && up)
Close();
}
else _buttonState = ButtonState.None;
}
if (oldState != _buttonState) Invalidate();
}
public void MaximizeWindow(bool maximize)
{
if (!MaximizeBox || !ControlBox) return;
_maximized = maximize;
if (maximize)
{
var monitorHandle = MonitorFromWindow(Handle, MONITOR_DEFAULTTONEAREST);
var monitorInfo = new MONITORINFOEX();
GetMonitorInfo(new HandleRef(null, monitorHandle), monitorInfo);
_previousSize = Size;
_previousLocation = Location;
//var area=Screen.FromHandle(this.Handle).WorkingArea;
Size = new Size(monitorInfo.rcWork.Width(), monitorInfo.rcWork.Height());
Location = new Point(monitorInfo.rcWork.left, monitorInfo.rcWork.top);
//Size = new Size(area.Width, area.Height);
//Location = new Point(area.Left, area.Top);
}
else
{
Size = _previousSize;
Location = _previousLocation;
}
}
protected override void OnMouseUp(MouseEventArgs e)
{
if (DesignMode) return;
UpdateButtons(e, true);
base.OnMouseUp(e);
ReleaseCapture();
}
private void ResizeForm(ResizeDirection direction)
{
if (DesignMode) return;
var dir = -1;
switch (direction)
{
case ResizeDirection.BottomLeft:
dir = HTBOTTOMLEFT;
break;
case ResizeDirection.Left:
dir = HTLEFT;
break;
case ResizeDirection.Right:
dir = HTRIGHT;
break;
case ResizeDirection.BottomRight:
dir = HTBOTTOMRIGHT;
break;
case ResizeDirection.Bottom:
dir = HTBOTTOM;
break;
}
ReleaseCapture();
if (dir != -1)
{
SendMessage(Handle, WM_NCLBUTTONDOWN, dir, 0);
}
}
protected override void OnResize(EventArgs e)
{
base.OnResize(e);
_minButtonBounds = new Rectangle((Width - SkinManager.FORM_PADDING / 2) - 3 * STATUS_BAR_BUTTON_WIDTH, 0, STATUS_BAR_BUTTON_WIDTH, STATUS_BAR_HEIGHT);
_maxButtonBounds = new Rectangle((Width - SkinManager.FORM_PADDING / 2) - 2 * STATUS_BAR_BUTTON_WIDTH, 0, STATUS_BAR_BUTTON_WIDTH, STATUS_BAR_HEIGHT);
_xButtonBounds = new Rectangle((Width - SkinManager.FORM_PADDING / 2) - STATUS_BAR_BUTTON_WIDTH, 0, STATUS_BAR_BUTTON_WIDTH, STATUS_BAR_HEIGHT);
_statusBarBounds = new Rectangle(0, 0, Width, STATUS_BAR_HEIGHT);
_actionBarBounds = new Rectangle(0, STATUS_BAR_HEIGHT, Width, ACTION_BAR_HEIGHT);
}
public bool ShowSubHeader { get; set; }
protected override void OnPaint(PaintEventArgs e)
{
var g = e.Graphics;
g.TextRenderingHint = TextRenderingHint.AntiAlias;
g.Clear(SkinManager.GetApplicationBackgroundColor());
g.FillRectangle(SkinManager.ColorScheme.DarkPrimaryBrush, _statusBarBounds);
if(ShowSubHeader) g.FillRectangle(SkinManager.ColorScheme.PrimaryBrush, _actionBarBounds);
//Draw border
using (var borderPen = new Pen(SkinManager.GetDividersColor(), 1))
{
g.DrawLine(borderPen, new Point(0, _statusBarBounds.Bottom), new Point(0, Height - 2));
g.DrawLine(borderPen, new Point(Width - 1, _statusBarBounds.Bottom), new Point(Width - 1, Height - 2));
g.DrawLine(borderPen, new Point(0, Height - 1), new Point(Width - 1, Height - 1));
}
// Determine whether or not we even should be drawing the buttons.
bool showMin = MinimizeBox && ControlBox;
bool showMax = MaximizeBox && ControlBox;
var hoverBrush = SkinManager.GetFlatButtonHoverBackgroundBrush();
var downBrush = SkinManager.GetFlatButtonPressedBackgroundBrush();
// When MaximizeButton == false, the minimize button will be painted in its place
if (_buttonState == ButtonState.MinOver && showMin)
g.FillRectangle(hoverBrush, showMax ? _minButtonBounds : _maxButtonBounds);
if (_buttonState == ButtonState.MinDown && showMin)
g.FillRectangle(downBrush, showMax ? _minButtonBounds : _maxButtonBounds);
if (_buttonState == ButtonState.MaxOver && showMax)
g.FillRectangle(hoverBrush, _maxButtonBounds);
if (_buttonState == ButtonState.MaxDown && showMax)
g.FillRectangle(downBrush, _maxButtonBounds);
if (_buttonState == ButtonState.XOver && ControlBox)
g.FillRectangle(hoverBrush, _xButtonBounds);
if (_buttonState == ButtonState.XDown && ControlBox)
g.FillRectangle(downBrush, _xButtonBounds);
using (var formButtonsPen = new Pen(SkinManager.ACTION_BAR_TEXT_SECONDARY, 2))
{
// Minimize button.
if (showMin)
{
int x = showMax ? _minButtonBounds.X : _maxButtonBounds.X;
int y = showMax ? _minButtonBounds.Y : _maxButtonBounds.Y;
g.DrawLine(
formButtonsPen,
x + (int)(_minButtonBounds.Width * 0.33),
y + (int)(_minButtonBounds.Height * 0.66),
x + (int)(_minButtonBounds.Width * 0.66),
y + (int)(_minButtonBounds.Height * 0.66)
);
}
// Maximize button
if (showMax)
{
g.DrawRectangle(
formButtonsPen,
_maxButtonBounds.X + (int)(_maxButtonBounds.Width * 0.33),
_maxButtonBounds.Y + (int)(_maxButtonBounds.Height * 0.36),
(int)(_maxButtonBounds.Width * 0.39),
(int)(_maxButtonBounds.Height * 0.31)
);
}
// Close button
if (ControlBox)
{
g.DrawLine(
formButtonsPen,
_xButtonBounds.X + (int)(_xButtonBounds.Width * 0.33),
_xButtonBounds.Y + (int)(_xButtonBounds.Height * 0.33),
_xButtonBounds.X + (int)(_xButtonBounds.Width * 0.66),
_xButtonBounds.Y + (int)(_xButtonBounds.Height * 0.66)
);
g.DrawLine(
formButtonsPen,
_xButtonBounds.X + (int)(_xButtonBounds.Width * 0.66),
_xButtonBounds.Y + (int)(_xButtonBounds.Height * 0.33),
_xButtonBounds.X + (int)(_xButtonBounds.Width * 0.33),
_xButtonBounds.Y + (int)(_xButtonBounds.Height * 0.66));
}
}
//Form title
g.DrawString(Text, SkinManager.ROBOTO_MEDIUM_12, SkinManager.ColorScheme.TextBrush, new Rectangle(SkinManager.FORM_PADDING, STATUS_BAR_HEIGHT, Width-20, ACTION_BAR_HEIGHT), new StringFormat { LineAlignment = StringAlignment.Center,Alignment = StringAlignment.Near });
//Primary title
g.DrawString(PrimaryText, new Font("Roboto",20,FontStyle.Bold),SkinManager.ColorScheme.TextBrush, new Rectangle(SkinManager.FORM_PADDING, STATUS_BAR_HEIGHT, Width, ACTION_BAR_HEIGHT), new StringFormat { LineAlignment = StringAlignment.Center, Alignment = StringAlignment.Center });
g.DrawString(HeaderText, new Font("Roboto", 12, FontStyle.Bold), SkinManager.ColorScheme.TextBrush, new Rectangle(SkinManager.FORM_PADDING, 0, Width, STATUS_BAR_HEIGHT), new StringFormat { LineAlignment = StringAlignment.Center, Alignment = StringAlignment.Near });
}
public string PrimaryText { get; set; }
public string HeaderText { get; set; }
public Font TitleFont { get; set; }
}
public class MouseMessageFilter : IMessageFilter
{
private const int WM_MOUSEMOVE = 0x0200;
public static event MouseEventHandler MouseMove;
public bool PreFilterMessage(ref Message m)
{
if (m.Msg == WM_MOUSEMOVE)
{
if (MouseMove != null)
{
int x = Control.MousePosition.X, y = Control.MousePosition.Y;
MouseMove(null, new MouseEventArgs(MouseButtons.None, 0, x, y, 0));
}
}
return false;
}
}
}

View File

@@ -0,0 +1,120 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

View File

@@ -0,0 +1,171 @@
using System;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.Threading.Tasks;
using System.Windows.Forms;
using MaterialSkin.Animations;
namespace MaterialSkin.Controls
{
public class MaterialIcon:Control
{
private Image _image;
private Bitmap _bmp;
private AnimationManager _animationManager;
private Point _lastLocation;
private Bitmap _backBuffer = null;
private bool _primary;
public MaterialIcon()
{
Cursor = Cursors.Hand;
Clickable = true;
_animationManager = new AnimationManager(false)
{
Increment = 0.02,
AnimationType = AnimationType.EaseOut
};
_animationManager.OnAnimationProgress += sender => Invalidate();
_animationManager.OnAnimationFinished += AnimationManagerOnOnAnimationFinished;
}
private void AnimationManagerOnOnAnimationFinished(object sender)
{
}
[Browsable(false)]
public MaterialSkinManager SkinManager => MaterialSkinManager.Instance;
public Image Image
{
get { return _image; }
set
{
_image = value;
RebuildIcon();
}
}
public bool Primary
{
get { return _primary; }
set
{
_primary = value;
if (_image == null) return;
RebuildIcon();
}
}
protected override void OnEnabledChanged(EventArgs e)
{
base.OnEnabledChanged(e);
RebuildIcon();
}
protected override void OnResize(EventArgs e)
{
_backBuffer=new Bitmap(Width,Height);
if (_image == null) return;
RebuildIcon();
base.OnResize(e);
}
private void RebuildIcon()
{
Task.Run(() =>
{
lock (_lockObject)
{
var tmp = new Bitmap(_image);
ReplaceColor(tmp, Color.Black,
Enabled
? (_primary
? SkinManager.GetApplicationBackgroundColor()
: SkinManager.ColorScheme.PrimaryColor)
: Color.FromArgb(0xAA, 0xAA, 0xAA));
_bmp = tmp;
Invalidate();
}
});
}
protected override void OnPaintBackground(PaintEventArgs pevent)
{
//base.OnPaintBackground(pevent);
}
protected override void OnMouseDown(MouseEventArgs mevent)
{
base.OnMouseDown(mevent);
if (!Enabled) return;
_lastLocation = mevent.Location;
_animationManager.StartNewAnimation(AnimationDirection.In, _lastLocation);
}
public bool Clickable { get; set; }
protected override void OnClick(EventArgs e)
{
if (!Clickable) return;
base.OnClick(e);
}
protected override void OnPaint(PaintEventArgs pe)
{
if (Image == null) return;
if(_bmp == null)return;
if(_backBuffer==null)return;
using (Graphics g=Graphics.FromImage(_backBuffer))
{
g.InterpolationMode = InterpolationMode.Bicubic;
g.SmoothingMode = SmoothingMode.HighQuality;
g.Clear(_primary? SkinManager.ColorScheme.PrimaryColor : SkinManager.GetApplicationBackgroundColor());
if (_animationManager.IsAnimating())
{
for (int i = 0; i < _animationManager.GetAnimationCount(); i++)
{
var animationValue = _animationManager.GetProgress(i);
var animationSource = _animationManager.GetSource(i);
var rippleBrush = new SolidBrush(Color.FromArgb((int)(51 - (animationValue * 50)), _primary ? SkinManager.GetApplicationBackgroundColor() : SkinManager.ColorScheme.PrimaryColor));
var rippleSize = (int)(animationValue * Width * 2);
g.FillEllipse(rippleBrush, new Rectangle(animationSource.X - rippleSize / 2, animationSource.Y - rippleSize / 2, rippleSize, rippleSize));
}
}
g.DrawImage(_bmp,1,1,Width-2,Height-2);
}
pe.Graphics.DrawImage(_backBuffer, 0,0);
}
object _lockObject = new object();
private void ReplaceColor(Bitmap bmp, Color oldColor, Color newColor)
{
{
var lockedBitmap = bmp;
for (int y = 0; y < lockedBitmap.Height; y++)
{
for (int x = 0; x < lockedBitmap.Width; x++)
{
if (lockedBitmap.GetPixel(x, y).A > 0)
{
lockedBitmap.SetPixel(x, y, newColor);
}
}
}
}
}
}
}

View File

@@ -0,0 +1,44 @@
namespace MaterialSkin.Controls
{
partial class MaterialIndicator
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Component Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.SuspendLayout();
//
// MaterialIndicator
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.Name = "MaterialIndicator";
this.ResumeLayout(false);
}
#endregion
}
}

View File

@@ -0,0 +1,51 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace MaterialSkin.Controls
{
public partial class MaterialIndicator : UserControl
{
private bool _checked;
[Browsable(false)]
public MaterialSkinManager SkinManager => MaterialSkinManager.Instance;
public Color CheckedColor { get; set; }
public Color UncheckedColor { get; set; }
public Color BorderColor { get; set; }
public MaterialIndicator()
{
InitializeComponent();
}
public bool Checked
{
get { return _checked; }
set
{
_checked = value;
Invalidate();
}
}
protected override void OnPaintBackground(PaintEventArgs e)
{
base.OnPaintBackground(e);
}
protected override void OnPaint(PaintEventArgs e)
{
e.Graphics.FillEllipse(new SolidBrush(Checked?CheckedColor:UncheckedColor),1,1,Width-2,Height-2);
e.Graphics.DrawEllipse(new Pen(BorderColor),1,1,Width-2,Height-2 );
}
}
}

View File

@@ -0,0 +1,120 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

View File

@@ -0,0 +1,115 @@
namespace MaterialSkin.Core.Controls
{
partial class MaterialInputBox
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.materialRaisedButton1 = new MaterialSkin.Controls.MaterialRaisedButton();
this.materialRaisedButton2 = new MaterialSkin.Controls.MaterialRaisedButton();
this.textBox1 = new System.Windows.Forms.TextBox();
this.label1 = new System.Windows.Forms.Label();
this.SuspendLayout();
//
// materialRaisedButton1
//
this.materialRaisedButton1.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
this.materialRaisedButton1.Cursor = System.Windows.Forms.Cursors.Hand;
this.materialRaisedButton1.Depth = 0;
this.materialRaisedButton1.DrawBorder = false;
this.materialRaisedButton1.Icon = null;
this.materialRaisedButton1.Location = new System.Drawing.Point(440, 88);
this.materialRaisedButton1.MouseState = MaterialSkin.MouseState.HOVER;
this.materialRaisedButton1.Name = "materialRaisedButton1";
this.materialRaisedButton1.Primary = true;
this.materialRaisedButton1.Size = new System.Drawing.Size(128, 48);
this.materialRaisedButton1.TabIndex = 0;
this.materialRaisedButton1.Text = "OK";
this.materialRaisedButton1.UseVisualStyleBackColor = true;
this.materialRaisedButton1.Click += new System.EventHandler(this.materialRaisedButton1_Click);
//
// materialRaisedButton2
//
this.materialRaisedButton2.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
this.materialRaisedButton2.Cursor = System.Windows.Forms.Cursors.Hand;
this.materialRaisedButton2.Depth = 0;
this.materialRaisedButton2.DrawBorder = true;
this.materialRaisedButton2.Icon = null;
this.materialRaisedButton2.Location = new System.Drawing.Point(304, 88);
this.materialRaisedButton2.MouseState = MaterialSkin.MouseState.HOVER;
this.materialRaisedButton2.Name = "materialRaisedButton2";
this.materialRaisedButton2.Primary = false;
this.materialRaisedButton2.Size = new System.Drawing.Size(128, 48);
this.materialRaisedButton2.TabIndex = 1;
this.materialRaisedButton2.Text = "Cancel";
this.materialRaisedButton2.UseVisualStyleBackColor = true;
this.materialRaisedButton2.Click += new System.EventHandler(this.materialRaisedButton2_Click);
//
// textBox1
//
this.textBox1.Location = new System.Drawing.Point(16, 56);
this.textBox1.Name = "textBox1";
this.textBox1.Size = new System.Drawing.Size(552, 23);
this.textBox1.TabIndex = 0;
this.textBox1.KeyDown += new System.Windows.Forms.KeyEventHandler(this.textBox1_KeyDown);
//
// label1
//
this.label1.AutoSize = true;
this.label1.BackColor = System.Drawing.Color.White;
this.label1.Location = new System.Drawing.Point(16, 32);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(38, 15);
this.label1.TabIndex = 3;
this.label1.Text = "label1";
//
// MaterialInputBox
//
this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(579, 149);
this.Controls.Add(this.label1);
this.Controls.Add(this.textBox1);
this.Controls.Add(this.materialRaisedButton2);
this.Controls.Add(this.materialRaisedButton1);
this.MaximizeBox = false;
this.MinimizeBox = false;
this.Name = "MaterialInputBox";
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private MaterialSkin.Controls.MaterialRaisedButton materialRaisedButton1;
private MaterialSkin.Controls.MaterialRaisedButton materialRaisedButton2;
private System.Windows.Forms.TextBox textBox1;
private System.Windows.Forms.Label label1;
}
}

View File

@@ -0,0 +1,48 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using MaterialSkin.Controls;
namespace MaterialSkin.Core.Controls
{
public partial class MaterialInputBox : MaterialForm
{
private MaterialInputBox()
{
InitializeComponent();
}
public static DialogResult Prompt(string title, string defaultValue, out string result, bool masked = false)
{
MaterialInputBox box = new MaterialInputBox {label1 = {Text = title}, textBox1 = {Text = defaultValue}};
if (masked) box.textBox1.PasswordChar = '*';
var res= box.ShowDialog();
result = box.textBox1.Text;
return res;
}
private void textBox1_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Return)
{
DialogResult = DialogResult.OK;
}
}
private void materialRaisedButton2_Click(object sender, EventArgs e)
{
DialogResult = DialogResult.Cancel;
}
private void materialRaisedButton1_Click(object sender, EventArgs e)
{
DialogResult = DialogResult.OK;
}
}
}

View File

@@ -0,0 +1,60 @@
<root>
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

View File

@@ -0,0 +1,24 @@
using System.ComponentModel;
using System.Windows.Forms;
namespace MaterialSkin.Controls
{
public class MaterialLabel : Label, IMaterialControl
{
[Browsable(false)]
public int Depth { get; set; }
[Browsable(false)]
public MaterialSkinManager SkinManager => MaterialSkinManager.Instance;
[Browsable(false)]
public MouseState MouseState { get; set; }
protected override void OnCreateControl()
{
base.OnCreateControl();
ForeColor = SkinManager.GetPrimaryTextColor();
Font = SkinManager.ROBOTO_REGULAR_11;
BackColorChanged += (sender, args) => ForeColor = SkinManager.GetPrimaryTextColor();
}
}
}

View File

@@ -0,0 +1,163 @@
using System;
using System.ComponentModel;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Windows.Forms;
namespace MaterialSkin.Controls
{
public class MaterialListView : ListView, IMaterialControl
{
[Browsable(false)]
public int Depth { get; set; }
[Browsable(false)]
public MaterialSkinManager SkinManager => MaterialSkinManager.Instance;
[Browsable(false)]
public MouseState MouseState { get; set; }
[Browsable(false)]
public Point MouseLocation { get; set; }
[Browsable(false)]
private ListViewItem HoveredItem { get; set; }
public MaterialListView()
{
GridLines = false;
FullRowSelect = true;
HeaderStyle = ColumnHeaderStyle.Nonclickable;
View = View.Details;
OwnerDraw = true;
ResizeRedraw = true;
BorderStyle = BorderStyle.None;
SetStyle(ControlStyles.DoubleBuffer | ControlStyles.OptimizedDoubleBuffer, true);
//Fix for hovers, by default it doesn't redraw
//TODO: should only redraw when the hovered line changed, this to reduce unnecessary redraws
MouseLocation = new Point(-1, -1);
MouseState = MouseState.OUT;
MouseEnter += delegate
{
MouseState = MouseState.HOVER;
};
MouseLeave += delegate
{
MouseState = MouseState.OUT;
MouseLocation = new Point(-1, -1);
HoveredItem = null;
Invalidate();
};
MouseDown += delegate { MouseState = MouseState.DOWN; };
MouseUp += delegate { MouseState = MouseState.HOVER; };
MouseMove += delegate (object sender, MouseEventArgs args)
{
MouseLocation = args.Location;
var currentHoveredItem = this.GetItemAt(MouseLocation.X, MouseLocation.Y);
if (HoveredItem != currentHoveredItem)
{
HoveredItem = currentHoveredItem;
Invalidate();
}
};
}
protected override void OnDrawColumnHeader(DrawListViewColumnHeaderEventArgs e)
{
e.Graphics.FillRectangle(new SolidBrush(SkinManager.GetApplicationBackgroundColor()), new Rectangle(e.Bounds.X, e.Bounds.Y, Width, e.Bounds.Height));
e.Graphics.DrawString(e.Header.Text,
SkinManager.ROBOTO_MEDIUM_10,
SkinManager.GetSecondaryTextBrush(),
new Rectangle(e.Bounds.X + ITEM_PADDING, e.Bounds.Y + ITEM_PADDING, e.Bounds.Width - ITEM_PADDING * 2, e.Bounds.Height - ITEM_PADDING * 2),
getStringFormat());
}
private const int ITEM_PADDING = 12;
protected override void OnDrawItem(DrawListViewItemEventArgs e)
{
//We draw the current line of items (= item with subitems) on a temp bitmap, then draw the bitmap at once. This is to reduce flickering.
var b = new Bitmap(e.Item.Bounds.Width, e.Item.Bounds.Height);
var g = Graphics.FromImage(b);
//always draw default background
g.FillRectangle(new SolidBrush(SkinManager.GetApplicationBackgroundColor()), new Rectangle(new Point(e.Bounds.X, 0), e.Bounds.Size));
if (e.State.HasFlag(ListViewItemStates.Selected))
{
//selected background
g.FillRectangle(SkinManager.GetFlatButtonPressedBackgroundBrush(), new Rectangle(new Point(e.Bounds.X, 0), e.Bounds.Size));
}
else if (e.Bounds.Contains(MouseLocation) && MouseState == MouseState.HOVER)
{
//hover background
g.FillRectangle(SkinManager.GetFlatButtonHoverBackgroundBrush(), new Rectangle(new Point(e.Bounds.X, 0), e.Bounds.Size));
}
//Draw separator
g.DrawLine(new Pen(SkinManager.GetDividersColor()), e.Bounds.Left, 0, e.Bounds.Right, 0);
foreach (ListViewItem.ListViewSubItem subItem in e.Item.SubItems)
{
//Draw text
g.DrawString(subItem.Text, SkinManager.ROBOTO_MEDIUM_10, SkinManager.GetPrimaryTextBrush(),
new Rectangle(subItem.Bounds.X + ITEM_PADDING, ITEM_PADDING, subItem.Bounds.Width - 2 * ITEM_PADDING, subItem.Bounds.Height - 2 * ITEM_PADDING),
getStringFormat());
}
e.Graphics.DrawImage((Image)b.Clone(), new Point(0, e.Item.Bounds.Location.Y));
g.Dispose();
b.Dispose();
}
private StringFormat getStringFormat()
{
return new StringFormat
{
FormatFlags = StringFormatFlags.LineLimit,
Trimming = StringTrimming.EllipsisCharacter,
Alignment = StringAlignment.Near,
LineAlignment = StringAlignment.Center
};
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public class LogFont
{
public int lfHeight = 0;
public int lfWidth = 0;
public int lfEscapement = 0;
public int lfOrientation = 0;
public int lfWeight = 0;
public byte lfItalic = 0;
public byte lfUnderline = 0;
public byte lfStrikeOut = 0;
public byte lfCharSet = 0;
public byte lfOutPrecision = 0;
public byte lfClipPrecision = 0;
public byte lfQuality = 0;
public byte lfPitchAndFamily = 0;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
public string lfFaceName = string.Empty;
}
protected override void OnCreateControl()
{
base.OnCreateControl();
// This hack tries to apply the Roboto (24) font to all ListViewItems in this ListView
// It only succeeds if the font is installed on the system.
// Otherwise, a default sans serif font is used.
var roboto24 = new Font(SkinManager.ROBOTO_MEDIUM_12.FontFamily, 24);
var roboto24Logfont = new LogFont();
roboto24.ToLogFont(roboto24Logfont);
try
{
// Font.FromLogFont is the method used when drawing ListViewItems. I 'test' it in this safer context to avoid unhandled exceptions later.
Font = Font.FromLogFont(roboto24Logfont);
}
catch (ArgumentException)
{
Font = new Font(FontFamily.GenericSansSerif, 24);
}
}
}
}

View File

@@ -0,0 +1,47 @@
namespace MaterialSkin.Controls
{
partial class MaterialLoader
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
SuspendLayout();
//
// MaterialLoader
//
AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F);
AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
ClientSize = new System.Drawing.Size(422, 189);
ControlBox = false;
Name = "MaterialLoader";
StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
ResumeLayout(false);
}
#endregion
}
}

View File

@@ -0,0 +1,139 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace MaterialSkin.Controls
{
public partial class MaterialLoader : MaterialForm
{
private static MaterialLoader _instance;
private static Thread _loaderThread;
private static ManualResetEvent _instanceReadyEvent = new ManualResetEvent(false);
private readonly Dictionary<string, (MaterialProgressBar ProgressBar, Label Label)> _loadingProcesses;
private MaterialLoader()
{
InitializeComponent();
RemoveMessageFilter();
_loadingProcesses = new Dictionary<string, (MaterialProgressBar, Label)>();
this.MaximizeBox = false;
this.MinimizeBox = false;
this.StartPosition = FormStartPosition.CenterScreen;
}
public static MaterialLoader Instance
{
get
{
if (_instance == null || _instance.IsDisposed)
{
_instanceReadyEvent.Reset();
_loaderThread = new Thread(() =>
{
_instance = new MaterialLoader();
_instance.Shown += (_, _) =>
{
_instanceReadyEvent.Set();
};
Application.Run(_instance);
});
_loaderThread.SetApartmentState(ApartmentState.STA);
_loaderThread.Start();
_instanceReadyEvent.WaitOne();
}
return _instance;
}
}
public void StartLoading(string title)
{
if (_instance == null || !_instance.Visible)
{
Instance.Invoke(new Action(() =>
{
Instance.Show();
Instance.Visible= true;
}));
}
Instance.Invoke(new Action(() =>
{
if (_loadingProcesses.ContainsKey(title))
{
return; // Prevent duplicate loading processes with the same title
}
var progressBar = new MaterialProgressBar
{
Width = Instance.ClientSize.Width - 20,
Height = 20,
Top = 50 + (_loadingProcesses.Count * 30),
Left = 10,
Style = ProgressBarStyle.Marquee,
MarqueeAnimationSpeed = 30,
Value = 50,
BackColor = Color.White
};
var label = new Label
{
Text = title,
AutoSize = true,
Top = progressBar.Top - 20,
Left = progressBar.Left,
BackColor = Color.White
};
_loadingProcesses[title] = (progressBar, label);
Instance.Controls.Add(label);
Instance.Controls.Add(progressBar);
Instance.Height = 50 + (_loadingProcesses.Count * 30);
Instance.Refresh();
}));
}
public void FinishLoading(string title)
{
if (_instance == null)
{
return;
}
Instance.Invoke(new Action(() =>
{
if (_loadingProcesses.TryGetValue(title, out var components))
{
Instance.Controls.Remove(components.ProgressBar);
Instance.Controls.Remove(components.Label);
_loadingProcesses.Remove(title);
RearrangeProgressBarsAndLabels();
}
if (_loadingProcesses.Count == 0)
{
Instance.Visible= false;
}
}));
}
private void RearrangeProgressBarsAndLabels()
{
int index = 0;
foreach (var components in _loadingProcesses.Values)
{
components.ProgressBar.Top = 50 + (index * 30);
components.Label.Top = components.ProgressBar.Top - 20;
index++;
}
this.Height = 50 + (_loadingProcesses.Count * 30);
}
}
}

View File

@@ -0,0 +1,120 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

View File

@@ -0,0 +1,90 @@
namespace MaterialSkin.Controls
{
partial class MaterialMessageBox
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.pnlButtons = new System.Windows.Forms.FlowLayoutPanel();
this.lblTitle = new System.Windows.Forms.Label();
this.lblText = new System.Windows.Forms.Label();
this.SuspendLayout();
//
// pnlButtons
//
this.pnlButtons.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.pnlButtons.AutoSize = true;
this.pnlButtons.Location = new System.Drawing.Point(280, 204);
this.pnlButtons.Name = "pnlButtons";
this.pnlButtons.Padding = new System.Windows.Forms.Padding(0, 20, 0, 0);
this.pnlButtons.Size = new System.Drawing.Size(140, 100);
this.pnlButtons.TabIndex = 0;
//
// lblTitle
//
this.lblTitle.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.lblTitle.Location = new System.Drawing.Point(0, 20);
this.lblTitle.Name = "lblTitle";
this.lblTitle.Size = new System.Drawing.Size(1340, 40);
this.lblTitle.TabIndex = 1;
this.lblTitle.Text = "label1";
this.lblTitle.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
//
// lblText
//
this.lblText.Location = new System.Drawing.Point(280, 80);
this.lblText.Name = "lblText";
this.lblText.Size = new System.Drawing.Size(680, 100);
this.lblText.TabIndex = 2;
this.lblText.Text = "label1";
this.lblText.TextAlign = System.Drawing.ContentAlignment.TopCenter;
//
// MaterialMessageBox
//
this.AutoScaleDimensions = new System.Drawing.SizeF(12F, 26F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
this.ClientSize = new System.Drawing.Size(1338, 312);
this.ControlBox = false;
this.Controls.Add(this.lblText);
this.Controls.Add(this.lblTitle);
this.Controls.Add(this.pnlButtons);
this.Font = new System.Drawing.Font("Roboto", 15.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(204)));
this.Margin = new System.Windows.Forms.Padding(6);
this.Name = "MaterialMessageBox";
this.StartPosition = System.Windows.Forms.FormStartPosition.Manual;
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.FlowLayoutPanel pnlButtons;
private System.Windows.Forms.Label lblTitle;
private System.Windows.Forms.Label lblText;
}
}

View File

@@ -0,0 +1,86 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace MaterialSkin.Controls
{
public partial class MaterialMessageBox : MaterialForm
{
[Browsable(false)]
private MaterialSkinManager SkinManager => MaterialSkinManager.Instance;
private MaterialMessageBox()
{
InitializeComponent();
BackColor = SkinManager.GetApplicationBackgroundColor();
Left = 0;
Width = Screen.PrimaryScreen.WorkingArea.Width;
Top = (Screen.PrimaryScreen.WorkingArea.Height - Height) / 2;
lblTitle.BackColor = SkinManager.ColorScheme.PrimaryColor;
lblTitle.ForeColor= SkinManager.ColorScheme.TextColor;
lblText.Left = (Width - lblText.Width) / 2;
}
private void AlignControls()
{
pnlButtons.Left = (Width - pnlButtons.Width) / 2;
}
public static DialogResult Show(string text)
{
return Show(null, text, string.Empty, MessageBoxButtons.OK);
}
public static DialogResult Show(IWin32Window owner,string text, string caption, MessageBoxButtons buttons)
{
var mb = new MaterialMessageBox();
mb.lblTitle.Text = caption;
mb.lblText.Text = text;
List<DialogResult> results;
switch (buttons)
{
case MessageBoxButtons.OK:
results=new List<DialogResult>(){DialogResult.OK};
break;
case MessageBoxButtons.OKCancel:
results = new List<DialogResult>() { DialogResult.OK,DialogResult.Cancel };
break;
case MessageBoxButtons.AbortRetryIgnore:
results = new List<DialogResult>() { DialogResult.Abort,DialogResult.Retry,DialogResult.Ignore };
break;
case MessageBoxButtons.YesNoCancel:
results = new List<DialogResult>() { DialogResult.Yes,DialogResult.No,DialogResult.Cancel };
break;
case MessageBoxButtons.YesNo:
results = new List<DialogResult>() { DialogResult.Yes,DialogResult.No };
break;
case MessageBoxButtons.RetryCancel:
results = new List<DialogResult>() { DialogResult.Retry,DialogResult.Cancel };
break;
default:
throw new ArgumentOutOfRangeException(nameof(buttons), buttons, null);
}
var btns=Enum.GetNames(typeof(DialogResult));
foreach (var btn in results)
{
MaterialRaisedButton opt = new MaterialRaisedButton();
opt.Size = new Size(180, 60);
opt.Margin = new Padding(10, 20, 10, 0);
opt.Text = Enum.GetName(typeof(DialogResult),btn);
opt.Click += (sender, args) =>
mb.DialogResult = btn;
mb.pnlButtons.Controls.Add(opt);
mb.AlignControls();
}
return mb.ShowDialog(owner);
}
}
}

View File

@@ -0,0 +1,120 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

View File

@@ -0,0 +1,16 @@
using System.ComponentModel;
using System.Windows.Forms;
namespace MaterialSkin.Controls
{
public class MaterialPanel:Panel
{
[Browsable(false)]
public MaterialSkinManager SkinManager => MaterialSkinManager.Instance;
protected override void OnPaint(PaintEventArgs e)
{
e.Graphics.Clear(SkinManager.GetApplicationBackgroundColor());
}
}
}

View File

@@ -0,0 +1,134 @@
using System;
using System.ComponentModel;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace MaterialSkin.Controls
{
/// <summary>
/// Material design-like progress bar
/// </summary>
public class MaterialProgressBar : ProgressBar, IMaterialControl
{
private int _animation;
/// <summary>
/// Initializes a new instance of the <see cref="MaterialProgressBar"/> class.
/// </summary>
public MaterialProgressBar()
{
SetStyle(ControlStyles.UserPaint, true);
SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
Timer timer = new Timer();
timer.Interval = 33;
timer.Tick += Timer_Tick;
timer.Enabled = true;
}
private void Timer_Tick(object sender, EventArgs e)
{
Invalidate();
}
/// <summary>
/// Gets or sets the depth.
/// </summary>
/// <value>
/// The depth.
/// </value>
[Browsable(false)]
public int Depth { get; set; }
/// <summary>
/// Gets the skin manager.
/// </summary>
/// <value>
/// The skin manager.
/// </value>
[Browsable(false)]
public MaterialSkinManager SkinManager => MaterialSkinManager.Instance;
/// <summary>
/// Gets or sets the state of the mouse.
/// </summary>
/// <value>
/// The state of the mouse.
/// </value>
[Browsable(false)]
public MouseState MouseState { get; set; }
/// <summary>
/// Performs the work of setting the specified bounds of this control.
/// </summary>
/// <param name="x">The new <see cref="P:System.Windows.Forms.Control.Left" /> property value of the control.</param>
/// <param name="y">The new <see cref="P:System.Windows.Forms.Control.Top" /> property value of the control.</param>
/// <param name="width">The new <see cref="P:System.Windows.Forms.Control.Width" /> property value of the control.</param>
/// <param name="height">The new <see cref="P:System.Windows.Forms.Control.Height" /> property value of the control.</param>
/// <param name="specified">A bitwise combination of the <see cref="T:System.Windows.Forms.BoundsSpecified" /> values.</param>
protected override void SetBoundsCore(int x, int y, int width, int height, BoundsSpecified specified)
{
base.SetBoundsCore(x, y, width, 5, specified);
}
protected override void CreateHandle()
{
base.CreateHandle();
if (Style == ProgressBarStyle.Marquee)
StartAnimation();
}
private void StartAnimation()
{
_animation = 0;
}
/// <summary>
/// Raises the <see cref="E:System.Windows.Forms.Control.Paint" /> event.
/// </summary>
/// <param name="e">A <see cref="T:System.Windows.Forms.PaintEventArgs" /> that contains the event data.</param>
protected override void OnPaint(PaintEventArgs e)
{
if (Style == ProgressBarStyle.Marquee)
{
try
{
var animationProgress = (int)(e.ClipRectangle.Width * ((double)_animation / Maximum));
var doneProgress = (int)(e.ClipRectangle.Width * ((double)Value / Maximum));
if (doneProgress + animationProgress > e.ClipRectangle.Width)
doneProgress = e.ClipRectangle.Width - animationProgress;
_animation+=Step;
if (_animation >= 100) _animation = -Value;
e.Graphics.FillRectangle(SkinManager.GetDisabledOrHintBrush(), 0, 0, e.ClipRectangle.Width, e.ClipRectangle.Height);
e.Graphics.FillRectangle(SkinManager.ColorScheme.PrimaryBrush, animationProgress, 0, doneProgress, e.ClipRectangle.Height);
//Task.Delay(33).ContinueWith((x) =>
//{
// try
// {
// System.Action a = () => { };
// if (InvokeRequired)
// Invoke(a);
// else
// a();
// }catch{}
//});
}
catch (Exception exception)
{
}
}
else
{
var doneProgress = (int)(e.ClipRectangle.Width * ((double)Value / Maximum));
e.Graphics.FillRectangle(SkinManager.ColorScheme.PrimaryBrush, 0, 0, doneProgress, e.ClipRectangle.Height);
e.Graphics.FillRectangle(SkinManager.GetDisabledOrHintBrush(), doneProgress, 0, e.ClipRectangle.Width, e.ClipRectangle.Height);
}
}
}
}

View File

@@ -0,0 +1,211 @@
using System;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Text;
using System.Windows.Forms;
using MaterialSkin.Animations;
namespace MaterialSkin.Controls
{
public class MaterialRadioButton : RadioButton, IMaterialControl
{
[Browsable(false)]
public int Depth { get; set; }
[Browsable(false)]
public MaterialSkinManager SkinManager => MaterialSkinManager.Instance;
[Browsable(false)]
public MouseState MouseState { get; set; }
[Browsable(false)]
public Point MouseLocation { get; set; }
private bool ripple;
[Category("Behavior")]
public bool Ripple
{
get { return ripple; }
set
{
ripple = value;
AutoSize = AutoSize; //Make AutoSize directly set the bounds.
if (value)
{
Margin = new Padding(0);
}
Invalidate();
}
}
// animation managers
private readonly AnimationManager _animationManager;
private readonly AnimationManager _rippleAnimationManager;
// size related variables which should be recalculated onsizechanged
private Rectangle _radioButtonBounds;
private int _boxOffset;
// size constants
private const int RADIOBUTTON_SIZE = 19;
private const int RADIOBUTTON_SIZE_HALF = RADIOBUTTON_SIZE / 2;
private const int RADIOBUTTON_OUTER_CIRCLE_WIDTH = 2;
private const int RADIOBUTTON_INNER_CIRCLE_SIZE = RADIOBUTTON_SIZE - (2 * RADIOBUTTON_OUTER_CIRCLE_WIDTH);
public MaterialRadioButton()
{
SetStyle(ControlStyles.DoubleBuffer | ControlStyles.OptimizedDoubleBuffer, true);
_animationManager = new AnimationManager
{
AnimationType = AnimationType.EaseInOut,
Increment = 0.06
};
_rippleAnimationManager = new AnimationManager(false)
{
AnimationType = AnimationType.Linear,
Increment = 0.10,
SecondaryIncrement = 0.08
};
_animationManager.OnAnimationProgress += sender => Invalidate();
_rippleAnimationManager.OnAnimationProgress += sender => Invalidate();
CheckedChanged += (sender, args) => _animationManager.StartNewAnimation(Checked ? AnimationDirection.In : AnimationDirection.Out);
SizeChanged += OnSizeChanged;
Ripple = true;
MouseLocation = new Point(-1, -1);
}
private void OnSizeChanged(object sender, EventArgs eventArgs)
{
_boxOffset = Height / 2 - (int)Math.Ceiling(RADIOBUTTON_SIZE / 2d);
_radioButtonBounds = new Rectangle(_boxOffset, _boxOffset, RADIOBUTTON_SIZE, RADIOBUTTON_SIZE);
}
public override Size GetPreferredSize(Size proposedSize)
{
var width = _boxOffset + 20 + (int)CreateGraphics().MeasureString(Text, SkinManager.ROBOTO_MEDIUM_10).Width;
return Ripple ? new Size(width, 30) : new Size(width, 20);
}
protected override void OnPaint(PaintEventArgs pevent)
{
var g = pevent.Graphics;
g.SmoothingMode = SmoothingMode.AntiAlias;
g.TextRenderingHint = TextRenderingHint.AntiAlias;
// clear the control
g.Clear(Parent.BackColor);
var RADIOBUTTON_CENTER = _boxOffset + RADIOBUTTON_SIZE_HALF;
var animationProgress = _animationManager.GetProgress();
int colorAlpha = Enabled ? (int)(animationProgress * 255.0) : SkinManager.GetCheckBoxOffDisabledColor().A;
int backgroundAlpha = Enabled ? (int)(SkinManager.GetCheckboxOffColor().A * (1.0 - animationProgress)) : SkinManager.GetCheckBoxOffDisabledColor().A;
float animationSize = (float)(animationProgress * 8f);
float animationSizeHalf = animationSize / 2;
animationSize = (float)(animationProgress * 9f);
var brush = new SolidBrush(Color.FromArgb(colorAlpha, Enabled ? SkinManager.ColorScheme.AccentColor : SkinManager.GetCheckBoxOffDisabledColor()));
var pen = new Pen(brush.Color);
// draw ripple animation
if (Ripple && _rippleAnimationManager.IsAnimating())
{
for (var i = 0; i < _rippleAnimationManager.GetAnimationCount(); i++)
{
var animationValue = _rippleAnimationManager.GetProgress(i);
var animationSource = new Point(RADIOBUTTON_CENTER, RADIOBUTTON_CENTER);
var rippleBrush = new SolidBrush(Color.FromArgb((int)((animationValue * 40)), ((bool)_rippleAnimationManager.GetData(i)[0]) ? Color.Black : brush.Color));
var rippleHeight = (Height % 2 == 0) ? Height - 3 : Height - 2;
var rippleSize = (_rippleAnimationManager.GetDirection(i) == AnimationDirection.InOutIn) ? (int)(rippleHeight * (0.8d + (0.2d * animationValue))) : rippleHeight;
using (var path = DrawHelper.CreateRoundRect(animationSource.X - rippleSize / 2, animationSource.Y - rippleSize / 2, rippleSize, rippleSize, rippleSize / 2))
{
g.FillPath(rippleBrush, path);
}
rippleBrush.Dispose();
}
}
// draw radiobutton circle
Color uncheckedColor = DrawHelper.BlendColor(Parent.BackColor, Enabled ? SkinManager.GetCheckboxOffColor() : SkinManager.GetCheckBoxOffDisabledColor(), backgroundAlpha);
using (var path = DrawHelper.CreateRoundRect(_boxOffset, _boxOffset, RADIOBUTTON_SIZE, RADIOBUTTON_SIZE, 9f))
{
g.FillPath(new SolidBrush(uncheckedColor), path);
if (Enabled)
{
g.FillPath(brush, path);
}
}
g.FillEllipse(
new SolidBrush(Parent.BackColor),
RADIOBUTTON_OUTER_CIRCLE_WIDTH + _boxOffset,
RADIOBUTTON_OUTER_CIRCLE_WIDTH + _boxOffset,
RADIOBUTTON_INNER_CIRCLE_SIZE,
RADIOBUTTON_INNER_CIRCLE_SIZE);
if (Checked)
{
using (var path = DrawHelper.CreateRoundRect(RADIOBUTTON_CENTER - animationSizeHalf, RADIOBUTTON_CENTER - animationSizeHalf, animationSize, animationSize, 4f))
{
g.FillPath(brush, path);
}
}
SizeF stringSize = g.MeasureString(Text, SkinManager.ROBOTO_MEDIUM_10);
g.DrawString(Text, SkinManager.ROBOTO_MEDIUM_10, Enabled ? SkinManager.GetPrimaryTextBrush() : SkinManager.GetDisabledOrHintBrush(), _boxOffset + 22, Height / 2 - stringSize.Height / 2);
brush.Dispose();
pen.Dispose();
}
private bool IsMouseInCheckArea()
{
return _radioButtonBounds.Contains(MouseLocation);
}
protected override void OnCreateControl()
{
base.OnCreateControl();
Font = SkinManager.ROBOTO_MEDIUM_10;
if (DesignMode) return;
MouseState = MouseState.OUT;
MouseEnter += (sender, args) =>
{
MouseState = MouseState.HOVER;
};
MouseLeave += (sender, args) =>
{
MouseLocation = new Point(-1, -1);
MouseState = MouseState.OUT;
};
MouseDown += (sender, args) =>
{
MouseState = MouseState.DOWN;
if (Ripple && args.Button == MouseButtons.Left && IsMouseInCheckArea())
{
_rippleAnimationManager.SecondaryIncrement = 0;
_rippleAnimationManager.StartNewAnimation(AnimationDirection.InOutIn, new object[] { Checked });
}
};
MouseUp += (sender, args) =>
{
MouseState = MouseState.HOVER;
_rippleAnimationManager.SecondaryIncrement = 0.08;
};
MouseMove += (sender, args) =>
{
MouseLocation = args.Location;
Cursor = IsMouseInCheckArea() ? Cursors.Hand : Cursors.Default;
};
}
}
}

View File

@@ -0,0 +1,216 @@
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Text;
using System.Windows.Forms;
using MaterialSkin.Animations;
using System;
namespace MaterialSkin.Controls
{
public class MaterialRaisedButton : Button, IMaterialControl
{
[Browsable(false)]
public int Depth { get; set; }
[Browsable(false)]
public MaterialSkinManager SkinManager => MaterialSkinManager.Instance;
[Browsable(false)]
public MouseState MouseState { get; set; }
public bool Primary { get; set; }
public bool DrawBorder
{
get { return _drawBorder; }
set
{
_drawBorder = value;
}
}
private readonly AnimationManager _animationManager;
private SizeF _textSize;
private Image _icon;
private bool _drawBorder;
private Point _lastLocation;
private bool _wasClick;
public Image Icon
{
get { return _icon; }
set
{
_icon = value;
if (AutoSize)
Size = GetPreferredSize();
Invalidate();
}
}
public MaterialRaisedButton()
{
Primary = true;
Cursor = Cursors.Hand;
_animationManager = new AnimationManager(false)
{
Increment = 0.02,
AnimationType = AnimationType.EaseOut
};
_animationManager.OnAnimationProgress += sender => Invalidate();
_animationManager.OnAnimationFinished +=AnimationManagerOnOnAnimationFinished;
AutoSizeMode = AutoSizeMode.GrowAndShrink;
}
private void AnimationManagerOnOnAnimationFinished(object o)
{
if (_wasClick)
{
_wasClick = false;
}
}
public override string Text
{
get { return base.Text; }
set
{
base.Text = value;
_textSize = CreateGraphics().MeasureString(value.ToUpper(), SkinManager.ROBOTO_MEDIUM_10);
if (AutoSize)
Size = GetPreferredSize();
Invalidate();
}
}
protected override void OnMouseUp(MouseEventArgs mevent)
{
base.OnMouseUp(mevent);
}
protected override void OnMouseDown(MouseEventArgs mevent)
{
base.OnMouseDown(mevent);
_lastLocation = mevent.Location;
}
protected override void OnClick(EventArgs e)
{
_animationManager.StartNewAnimation(AnimationDirection.In,_lastLocation);
base.OnClick(e);
}
protected override void OnPaint(PaintEventArgs pevent)
{
try
{
var g = pevent.Graphics;
g.SmoothingMode = SmoothingMode.AntiAlias;
//g.TextRenderingHint = TextRenderingHint.AntiAlias;
g.Clear(Parent.BackColor);
using (var backgroundPath = DrawHelper.CreateRoundRect(ClientRectangle.X,
ClientRectangle.Y,
ClientRectangle.Width - 1,
ClientRectangle.Height - 1,
1f))
{
g.FillPath(
Enabled
? (Primary
? SkinManager.ColorScheme.PrimaryBrush
: SkinManager.GetRaisedButtonBackgroundBrush())
: Brushes.DarkGray, backgroundPath);
if (!Primary && this.DrawBorder)
{
g.DrawPath(SkinManager.ColorScheme.PrimaryPen, backgroundPath);
}
}
if (_animationManager.IsAnimating())
{
for (int i = 0; i < _animationManager.GetAnimationCount(); i++)
{
var animationValue = _animationManager.GetProgress(i);
var animationSource = _animationManager.GetSource(i);
var rippleBrush = new SolidBrush(Color.FromArgb((int) (51 - (animationValue * 50)),
Primary ? Color.White : SkinManager.ColorScheme.PrimaryColor));
var rippleSize = (int) (animationValue * Width * 2);
g.FillEllipse(rippleBrush,
new Rectangle(animationSource.X - rippleSize / 2, animationSource.Y - rippleSize / 2,
rippleSize, rippleSize));
}
}
//Icon
var iconRect = new Rectangle(8, 6, 24, 24);
if (string.IsNullOrEmpty(Text))
// Center Icon
iconRect.X += 2;
if (Icon != null)
g.DrawImage(Icon, iconRect);
//Text
var textRect = ClientRectangle;
if (Icon != null)
{
//
// Resize and move Text container
//
// First 8: left padding
// 24: icon width
// Second 4: space between Icon and Text
// Third 8: right padding
textRect.Width -= 8 + 24 + 4 + 8;
// First 8: left padding
// 24: icon width
// Second 4: space between Icon and Text
textRect.X += 8 + 24 + 4;
}
g.DrawString(
Text.ToUpper(),
Font,
Primary ? SkinManager.GetRaisedButtonTextBrush(Primary) : SkinManager.ColorScheme.PrimaryBrush,
textRect,
new StringFormat {Alignment = StringAlignment.Center, LineAlignment = StringAlignment.Center});
}
catch
{
}
}
private Size GetPreferredSize()
{
return GetPreferredSize(new Size(0, 0));
}
public override Size GetPreferredSize(Size proposedSize)
{
// Provides extra space for proper padding for content
var extra = 16;
if (Icon != null)
// 24 is for icon size
// 4 is for the space between icon & text
extra += 24 + 4;
return new Size((int)Math.Ceiling(_textSize.Width) + extra, 36);
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,22 @@
using System;
using System.ComponentModel;
using System.Windows.Forms;
namespace MaterialSkin.Controls
{
public class MaterialTabControl : TabControl, IMaterialControl
{
[Browsable(false)]
public int Depth { get; set; }
[Browsable(false)]
public MaterialSkinManager SkinManager => MaterialSkinManager.Instance;
[Browsable(false)]
public MouseState MouseState { get; set; }
protected override void WndProc(ref Message m)
{
if (m.Msg == 0x1328 && !DesignMode) m.Result = (IntPtr)1;
else base.WndProc(ref m);
}
}
}

View File

@@ -0,0 +1,175 @@
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Text;
using System.Windows.Forms;
using MaterialSkin.Animations;
namespace MaterialSkin.Controls
{
public class MaterialTabSelector : Control, IMaterialControl
{
[Browsable(false)]
public int Depth { get; set; }
[Browsable(false)]
public MaterialSkinManager SkinManager => MaterialSkinManager.Instance;
[Browsable(false)]
public MouseState MouseState { get; set; }
private MaterialTabControl _baseTabControl;
public MaterialTabControl BaseTabControl
{
get { return _baseTabControl; }
set
{
_baseTabControl = value;
if (_baseTabControl == null) return;
_previousSelectedTabIndex = _baseTabControl.SelectedIndex;
_baseTabControl.Deselected += (sender, args) =>
{
_previousSelectedTabIndex = _baseTabControl.SelectedIndex;
};
_baseTabControl.SelectedIndexChanged += (sender, args) =>
{
_animationManager.SetProgress(0);
_animationManager.StartNewAnimation(AnimationDirection.In);
};
_baseTabControl.ControlAdded += delegate
{
Invalidate();
};
_baseTabControl.ControlRemoved += delegate
{
Invalidate();
};
}
}
private int _previousSelectedTabIndex;
private Point _animationSource;
private readonly AnimationManager _animationManager;
private List<Rectangle> _tabRects;
private const int TAB_HEADER_PADDING = 24;
private const int TAB_INDICATOR_HEIGHT = 2;
public MaterialTabSelector()
{
SetStyle(ControlStyles.DoubleBuffer | ControlStyles.OptimizedDoubleBuffer, true);
Height = 48;
_animationManager = new AnimationManager
{
AnimationType = AnimationType.EaseOut,
Increment = 0.04
};
_animationManager.OnAnimationProgress += sender => Invalidate();
}
protected override void OnPaint(PaintEventArgs e)
{
var g = e.Graphics;
g.TextRenderingHint = TextRenderingHint.AntiAlias;
g.Clear(SkinManager.ColorScheme.PrimaryColor);
if (_baseTabControl == null) return;
if (!_animationManager.IsAnimating() || _tabRects == null || _tabRects.Count != _baseTabControl.TabCount)
UpdateTabRects();
var animationProgress = _animationManager.GetProgress();
//Click feedback
if (_animationManager.IsAnimating())
{
var rippleBrush = new SolidBrush(Color.FromArgb((int)(51 - (animationProgress * 50)), Color.White));
var rippleSize = (int)(animationProgress * _tabRects[_baseTabControl.SelectedIndex].Width * 1.75);
g.SetClip(_tabRects[_baseTabControl.SelectedIndex]);
g.FillEllipse(rippleBrush, new Rectangle(_animationSource.X - rippleSize / 2, _animationSource.Y - rippleSize / 2, rippleSize, rippleSize));
g.ResetClip();
rippleBrush.Dispose();
}
//Draw tab headers
foreach (TabPage tabPage in _baseTabControl.TabPages)
{
var currentTabIndex = _baseTabControl.TabPages.IndexOf(tabPage);
Brush textBrush = new SolidBrush(Color.FromArgb(CalculateTextAlpha(currentTabIndex, animationProgress), SkinManager.ColorScheme.TextColor));
g.DrawString(tabPage.Text.ToUpper(), SkinManager.ROBOTO_MEDIUM_10, textBrush, _tabRects[currentTabIndex], new StringFormat { Alignment = StringAlignment.Center, LineAlignment = StringAlignment.Center });
textBrush.Dispose();
}
//Animate tab indicator
var previousSelectedTabIndexIfHasOne = _previousSelectedTabIndex == -1 ? _baseTabControl.SelectedIndex : _previousSelectedTabIndex;
var previousActiveTabRect = _tabRects[previousSelectedTabIndexIfHasOne];
var activeTabPageRect = _tabRects[_baseTabControl.SelectedIndex];
var y = activeTabPageRect.Bottom - 2;
var x = previousActiveTabRect.X + (int)((activeTabPageRect.X - previousActiveTabRect.X) * animationProgress);
var width = previousActiveTabRect.Width + (int)((activeTabPageRect.Width - previousActiveTabRect.Width) * animationProgress);
g.FillRectangle(SkinManager.ColorScheme.AccentBrush, x, y, width, TAB_INDICATOR_HEIGHT);
}
private int CalculateTextAlpha(int tabIndex, double animationProgress)
{
int primaryA = SkinManager.ACTION_BAR_TEXT.A;
int secondaryA = SkinManager.ACTION_BAR_TEXT_SECONDARY.A;
if (tabIndex == _baseTabControl.SelectedIndex && !_animationManager.IsAnimating())
{
return primaryA;
}
if (tabIndex != _previousSelectedTabIndex && tabIndex != _baseTabControl.SelectedIndex)
{
return secondaryA;
}
if (tabIndex == _previousSelectedTabIndex)
{
return primaryA - (int)((primaryA - secondaryA) * animationProgress);
}
return secondaryA + (int)((primaryA - secondaryA) * animationProgress);
}
protected override void OnMouseUp(MouseEventArgs e)
{
base.OnMouseUp(e);
if (_tabRects == null) UpdateTabRects();
for (var i = 0; i < _tabRects.Count; i++)
{
if (_tabRects[i].Contains(e.Location))
{
_baseTabControl.SelectedIndex = i;
}
}
_animationSource = e.Location;
}
private void UpdateTabRects()
{
_tabRects = new List<Rectangle>();
//If there isn't a base tab control, the rects shouldn't be calculated
//If there aren't tab pages in the base tab control, the list should just be empty which has been set already; exit the void
if (_baseTabControl == null || _baseTabControl.TabCount == 0) return;
//Calculate the bounds of each tab header specified in the base tab control
using (var b = new Bitmap(1, 1))
{
using (var g = Graphics.FromImage(b))
{
_tabRects.Add(new Rectangle(SkinManager.FORM_PADDING, 0, TAB_HEADER_PADDING * 2 + (int)g.MeasureString(_baseTabControl.TabPages[0].Text, SkinManager.ROBOTO_MEDIUM_10).Width, Height));
for (int i = 1; i < _baseTabControl.TabPages.Count; i++)
{
_tabRects.Add(new Rectangle(_tabRects[i - 1].Right, 0, TAB_HEADER_PADDING * 2 + (int)g.MeasureString(_baseTabControl.TabPages[i].Text, SkinManager.ROBOTO_MEDIUM_10).Width, Height));
}
}
}
}
}
}

View File

@@ -0,0 +1,103 @@
using MaterialSkin.Core.Resources;
namespace MaterialSkin.Controls
{
partial class MaterialUpDown
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Component Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.textBox1 = new System.Windows.Forms.TextBox();
this.materialIcon2 = new MaterialSkin.Controls.MaterialIcon();
this.materialIcon1 = new MaterialSkin.Controls.MaterialIcon();
this.SuspendLayout();
//
// textBox1
//
this.textBox1.BorderStyle = System.Windows.Forms.BorderStyle.None;
this.textBox1.Font = new System.Drawing.Font("Roboto", 15.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(204)));
this.textBox1.Location = new System.Drawing.Point(80, 20);
this.textBox1.Name = "textBox1";
this.textBox1.Size = new System.Drawing.Size(100, 28);
this.textBox1.TabIndex = 13;
this.textBox1.Text = "0000";
this.textBox1.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
this.textBox1.Click += new System.EventHandler(this.textBox1_Click);
this.textBox1.TextChanged += new System.EventHandler(this.textBox1_TextChanged);
this.textBox1.KeyDown += new System.Windows.Forms.KeyEventHandler(this.textBox1_KeyDown);
this.textBox1.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.textBox1_KeyPress);
this.textBox1.Leave += new System.EventHandler(this.textBox1_Leave);
//
// materialIcon2
//
this.materialIcon2.Clickable = true;
this.materialIcon2.Cursor = System.Windows.Forms.Cursors.Hand;
this.materialIcon2.Image = Resource1.rounded_add_button;
this.materialIcon2.Location = new System.Drawing.Point(200, 0);
this.materialIcon2.Name = "materialIcon2";
this.materialIcon2.Primary = false;
this.materialIcon2.Size = new System.Drawing.Size(64, 64);
this.materialIcon2.TabIndex = 12;
this.materialIcon2.Text = "materialIcon2";
this.materialIcon2.Click += new System.EventHandler(this.materialIcon2_Click);
this.materialIcon2.MouseDown += new System.Windows.Forms.MouseEventHandler(this.materialIcon2_MouseDown);
this.materialIcon2.MouseLeave += new System.EventHandler(this.materialIcon2_MouseLeave);
this.materialIcon2.MouseUp += new System.Windows.Forms.MouseEventHandler(this.materialIcon2_MouseUp);
//
// materialIcon1
//
this.materialIcon1.Clickable = true;
this.materialIcon1.Cursor = System.Windows.Forms.Cursors.Hand;
this.materialIcon1.Image = Resource1.round_delete_button;
this.materialIcon1.Location = new System.Drawing.Point(0, 0);
this.materialIcon1.Name = "materialIcon1";
this.materialIcon1.Primary = false;
this.materialIcon1.Size = new System.Drawing.Size(64, 64);
this.materialIcon1.TabIndex = 11;
this.materialIcon1.Text = "materialIcon1";
this.materialIcon1.Click += new System.EventHandler(this.materialIcon1_Click);
this.materialIcon1.MouseDown += new System.Windows.Forms.MouseEventHandler(this.materialIcon1_MouseDown);
this.materialIcon1.MouseLeave += new System.EventHandler(this.materialIcon1_MouseLeave);
this.materialIcon1.MouseUp += new System.Windows.Forms.MouseEventHandler(this.materialIcon1_MouseUp);
//
// MaterialUpDown
//
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.None;
this.Controls.Add(this.textBox1);
this.Controls.Add(this.materialIcon2);
this.Controls.Add(this.materialIcon1);
this.Name = "MaterialUpDown";
this.Size = new System.Drawing.Size(266, 66);
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private MaterialIcon materialIcon2;
private MaterialIcon materialIcon1;
private System.Windows.Forms.TextBox textBox1;
}
}

View File

@@ -0,0 +1,256 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
using System.Security.Principal;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace MaterialSkin.Controls
{
public partial class MaterialUpDown : UserControl,INotifyPropertyChanged
{
private double _value;
private bool _mouseDown;
private int _direction;
public MaterialUpDown()
{
InitializeComponent();
textBox1.BackColor = SkinManager.GetApplicationBackgroundColor();
AllowDecimal = false;
AllowKeyboard=true;
}
[Browsable(false)]
public MaterialSkinManager SkinManager => MaterialSkinManager.Instance;
public bool AllowDecimal { get; set; }
public bool AllowKeyboard
{
get { return _allowKeyboard; }
set
{
_allowKeyboard = value;
textBox1.ReadOnly = !_allowKeyboard || _readOnly;
}
}
public bool HideControls
{
get { return _hideControls; }
set
{
_hideControls = value;
materialIcon1.Visible = !value;
materialIcon2.Visible = !value;
}
}
public double Value
{
get { return _value; }
set
{
_value = value;
if (_value>Max)
{
_value = Max;
}
if (_value < Min)
{
_value = Min;
}
if (!AllowDecimal)
{
_value = Math.Floor(_value);
}
Action a = ()=> textBox1.Text = _value.ToString();
if (textBox1.InvokeRequired)
textBox1.Invoke(a);
else
a();
}
}
public bool ReadOnly
{
get { return _readOnly; }
set
{
_readOnly = value;
materialIcon1.Enabled = !value;
materialIcon2.Enabled = !value;
textBox1.ReadOnly = !_allowKeyboard || _readOnly;
}
}
public event PropertyChangedEventHandler PropertyChanged= delegate { };
public double Max { get; set; }
public double Min { get; set; }
public double Step { get; set; }
protected override void OnPaintBackground(PaintEventArgs e)
{
e.Graphics.Clear(SkinManager.GetApplicationBackgroundColor());
}
private void materialIcon2_Click(object sender, EventArgs e)
{
}
private void materialIcon1_Click(object sender, EventArgs e)
{
}
private async void HoldCountDown(CancellationToken cancellationSourceToken)
{
await Task.Delay(500);
var startTime = DateTime.Now;
while (_mouseDown&&!cancellationSourceToken.IsCancellationRequested)
{
Value += Step*_direction;
await Task.Delay(100/(int)Math.Max(1,Math.Min(5,(DateTime.Now-startTime).TotalSeconds)));
}
}
private CancellationTokenSource _cancellationSource;
private bool _readOnly;
private bool _allowKeyboard;
private void materialIcon2_MouseDown(object sender, MouseEventArgs e)
{
_cancellationSource =new CancellationTokenSource();
Value += Step;
_mouseDown = true;
_direction = 1;
Task.Run(()=> HoldCountDown(_cancellationSource.Token));
}
private void materialIcon2_MouseUp(object sender, MouseEventArgs e)
{
if (_cancellationSource != null)
{
_cancellationSource.Cancel();
_cancellationSource = null;
}
_mouseDown = false;
PropertyChanged(this,new PropertyChangedEventArgs(nameof(Value)));
}
private void materialIcon1_MouseDown(object sender, MouseEventArgs e)
{
_cancellationSource = new CancellationTokenSource();
Value -= Step;
_mouseDown = true;
_direction = -1;
Task.Run(() => HoldCountDown(_cancellationSource.Token));
}
private void materialIcon1_MouseUp(object sender, MouseEventArgs e)
{
if (_cancellationSource != null)
{
_cancellationSource.Cancel();
_cancellationSource = null;
}
_mouseDown = false;
PropertyChanged(this, new PropertyChangedEventArgs(nameof(Value)));
}
private void materialIcon2_MouseLeave(object sender, EventArgs e)
{
materialIcon2_MouseUp(null,null);
}
private void materialIcon1_MouseLeave(object sender, EventArgs e)
{
materialIcon1_MouseUp(null, null);
}
private void textBox1_KeyPress(object sender, KeyPressEventArgs e)
{
if (!char.IsControl(e.KeyChar) && !char.IsDigit(e.KeyChar) &&
(e.KeyChar != '.'))
{
e.Handled = true;
return;
}
// only allow one decimal point
if ((e.KeyChar == '.') && ((sender as TextBox).Text.IndexOf('.') > -1))
{
e.Handled = true;
return;
}
_validate = true;
}
private CancellationTokenSource _cancellationTokenSource = null;
private bool _validate;
private bool _hideControls;
private void textBox1_Click(object sender, EventArgs e)
{
if (textBox1.ReadOnly) return;
textBox1.SelectAll();
}
private void textBox1_TextChanged(object sender, EventArgs e)
{
}
private void textBox1_Leave(object sender, EventArgs e)
{
if (double.TryParse((sender as TextBox).Text, NumberStyles.AllowDecimalPoint, CultureInfo.GetCultureInfo("en-us"), out var value))
{
if (_cancellationTokenSource != null) _cancellationTokenSource.Cancel();
_cancellationTokenSource = new CancellationTokenSource();
Task.Run(async () =>
{
var newValue = value;
var token = _cancellationTokenSource.Token;
if (token.IsCancellationRequested) throw new OperationCanceledException();
Value = newValue;
PropertyChanged(this, new PropertyChangedEventArgs(nameof(Value)));
});
}
}
private void textBox1_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Enter)
{
textBox1_Leave(textBox1,null);
e.Handled = true;
}
}
}
}

View File

@@ -0,0 +1,120 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

View File

@@ -0,0 +1,43 @@
using System.Drawing;
using System.Drawing.Drawing2D;
namespace MaterialSkin
{
static class DrawHelper
{
public static GraphicsPath CreateRoundRect(float x, float y, float width, float height, float radius)
{
var gp = new GraphicsPath();
gp.AddLine(x + radius, y, x + width - (radius * 2), y);
gp.AddArc(x + width - (radius * 2), y, radius * 2, radius * 2, 270, 90);
gp.AddLine(x + width, y + radius, x + width, y + height - (radius * 2));
gp.AddArc(x + width - (radius * 2), y + height - (radius * 2), radius * 2, radius * 2, 0, 90);
gp.AddLine(x + width - (radius * 2), y + height, x + radius, y + height);
gp.AddArc(x, y + height - (radius * 2), radius * 2, radius * 2, 90, 90);
gp.AddLine(x, y + height - (radius * 2), x, y + radius);
gp.AddArc(x, y, radius * 2, radius * 2, 180, 90);
gp.CloseFigure();
return gp;
}
public static GraphicsPath CreateRoundRect(Rectangle rect, float radius)
{
return CreateRoundRect(rect.X, rect.Y, rect.Width, rect.Height, radius);
}
public static Color BlendColor(Color backgroundColor, Color frontColor, double blend)
{
var ratio = blend / 255d;
var invRatio = 1d - ratio;
var r = (int)((backgroundColor.R * invRatio) + (frontColor.R * ratio));
var g = (int)((backgroundColor.G * invRatio) + (frontColor.G * ratio));
var b = (int)((backgroundColor.B * invRatio) + (frontColor.B * ratio));
return Color.FromArgb(r, g, b);
}
public static Color BlendColor(Color backgroundColor, Color frontColor)
{
return BlendColor(backgroundColor, frontColor, frontColor.A);
}
}
}

View File

@@ -0,0 +1,279 @@
#region The MIT License (MIT)
//
// Copyright (c) 2011 Robert Prouse http://www.alteridem.net
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
// Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
#endregion
#region Using Directives
using System;
using System.Drawing;
#endregion
namespace MaterialSkin.Gesture
{
#region GestureEventArgs Class
/// <summary>
/// Base class for all the gesture based events
/// </summary>
public abstract class GestureEventArgs : EventArgs
{
internal GestureEventArgs( GestureInfo info )
{
Location = new Point( info.location.x, info.location.y );
Info = info;
Handled = true;
}
#region Helper Methods
protected static int LoDWord( IntPtr lParam )
{
return LoDWord( lParam.ToInt64() );
}
protected static int HiDWord( IntPtr lParam )
{
return HiDWord( lParam.ToInt64() );
}
protected static int LoDWord( long l )
{
return (int)(l & 0xFFFFFFFF);
}
protected static int HiDWord( long l )
{
return (int)((l >> 32) & 0xFFFFFFFF);
}
protected static short LoWord( int i )
{
return (short)(i & 0xFFFF);
}
protected static short HiWord( int i )
{
return (short)((i >> 16) & 0xFFFF);
}
#endregion
#region Properties
protected GestureInfo Info { get; set; }
/// <summary>
/// Gets the location of the gesture in Screen (not client) coordinates.
/// </summary>
public Point Location { get; private set; }
/// <summary>
/// Gets a value indicating whether this <see cref="GestureEventArgs"/> is beginning.
/// </summary>
public bool Begin
{
get { return Info.Begin; }
}
/// <summary>
/// Gets a value indicating whether this <see cref="GestureEventArgs"/> is ending
/// </summary>
public bool End
{
get { return Info.End; }
}
/// <summary>
/// Gets or sets a value indicating whether the window message was handled. Set this to false if you don't handle the message.
/// </summary>
public bool Handled { get; set; }
#endregion
}
#endregion
#region PanEventArgs Class
/// <summary>
/// Event for the Pan gesture
/// </summary>
public class PanEventArgs : GestureEventArgs
{
internal PanEventArgs( GestureInfo info, Point lastPanPoint )
: base( info )
{
int hiword = HiDWord( info.arguments );
InertiaVector = new Point( LoWord( hiword ), HiWord( hiword ) );
PanOffset = new Point( Location.X - lastPanPoint.X, Location.Y - lastPanPoint.Y );
}
/// <summary>
/// Gets a value indicating whether this <see cref="GestureEventArgs"/> has triggered inertia.
/// </summary>
public bool Inertia
{
get { return Info.Inertia; }
}
public Point InertiaVector { get; private set; }
/// <summary>
/// Gets the pan offset since the last pan message.
/// </summary>
public Point PanOffset { get; private set; }
}
#endregion
#region ZoomEventArgs Class
/// <summary>
/// Event for the Zoom gesture
/// </summary>
public class ZoomEventArgs : GestureEventArgs
{
internal ZoomEventArgs( GestureInfo info, long lastZoomDistance )
: base( info )
{
Distance = info.arguments;
PercentChange = (double)Distance / lastZoomDistance;
}
/// <summary>
/// Gets the distance between the two points as they are being zoomed.
/// </summary>
public long Distance { get; private set; }
/// <summary>
/// Gets the percent changed since the last zoom message
/// </summary>
public double PercentChange { get; private set; }
}
#endregion
#region PressAndTapEventArgs Class
/// <summary>
/// Event for the Press and Tap gesture
/// </summary>
public class PressAndTapEventArgs : GestureEventArgs
{
internal PressAndTapEventArgs( GestureInfo info )
: base( info )
{
int pointsStruct = LoDWord( info.arguments );
Distance = new Point( LoWord( pointsStruct ), HiWord( pointsStruct ) );
}
/// <summary>
/// Gets the distance between the two points.
/// </summary>
public Point Distance { get; private set; }
}
#endregion
#region RotateEventArgs Class
/// <summary>
/// Event for the Rotate gesture
/// </summary>
public class RotateEventArgs : GestureEventArgs
{
internal RotateEventArgs( GestureInfo info, double lastRotation )
: base( info )
{
int loword = LoDWord( info.arguments );
TotalAngle = RotateAngleFromArgument( loword );
Angle = TotalAngle - lastRotation;
string msg = string.Format("Total:{0} Angle:{1} Last:{2}", TotalAngle, Angle, lastRotation );
System.Diagnostics.Debug.WriteLine( msg );
}
/// <summary>
/// Gesture argument helper that converts an argument to a rotation angle.
/// </summary>
/// <param name="arg">The argument to convert. Should be an unsigned 16-bit value.</param>
/// <returns></returns>
private static double RotateAngleFromArgument( int arg )
{
return ((arg / 65535.0) * 4.0 * Math.PI) - 2.0 * Math.PI;
}
/// <summary>
/// Gets the angle of rotation in Radians since the beginning of the gesture
/// </summary>
public double TotalAngle { get; private set; }
/// <summary>
/// Gets the angle of rotation in Degrees since the beginning of the gesture
/// </summary>
public double TotalDegrees
{
get { return RadiandsToDegrees( TotalAngle ); }
}
/// <summary>
/// Gets the angle of rotation in Radians since the last rotation message
/// </summary>
public double Angle { get; private set; }
/// <summary>
/// Gets the angle of rotation in Degrees since the last rotation message
/// </summary>
public double Degrees
{
get { return RadiandsToDegrees( Angle ); }
}
private double RadiandsToDegrees( double radians )
{
return radians * 180.0 / Math.PI;
}
}
#endregion
#region TwoFingerTapEventArgs Class
/// <summary>
/// Base class for the Two Finger Tap gesture
/// </summary>
public class TwoFingerTapEventArgs : GestureEventArgs
{
internal TwoFingerTapEventArgs( GestureInfo info )
: base( info )
{
Distance = info.arguments;
}
/// <summary>
/// Gets the distance between the two points.
/// </summary>
public long Distance { get; private set; }
}
#endregion
}

View File

@@ -0,0 +1,446 @@
#region The MIT License (MIT)
//
// Copyright (c) 2011 Robert Prouse http://www.alteridem.net
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
// Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
#endregion
#region Using Directives
using System;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Security.Permissions;
using System.Threading.Tasks;
using System.Windows.Forms;
#endregion
namespace MaterialSkin.Gesture
{
[PermissionSet( SecurityAction.Demand, Name = "FullTrust" )]
public sealed class GestureListener : NativeWindow
{
#region Private Members
// Saved state
private Point _lastPanPoint;
private double _lastRotation;
private long _lastZoom;
private readonly Control _parent;
private readonly GestureConfig[] m_configs;
private int _touchInputSize;
#endregion
#region Public Events
public event EventHandler<PanEventArgs> Pan;
public event EventHandler<PressAndTapEventArgs> PressAndTap;
public event EventHandler<RotateEventArgs> Rotate;
public event EventHandler<TwoFingerTapEventArgs> TwoFingerTap;
public event EventHandler<ZoomEventArgs> Zoom;
#endregion
#region Construction
/// <summary>
/// Initializes a new instance of the <see cref="GestureListener"/> class to receive all gestures.
/// </summary>
/// <param name="parent">The parent.</param>
public GestureListener( Control parent )
: this( parent, new[] { new GestureConfig( 0, GestureConfigurationFlag.GC_ALLGESTURES, 0 ) } )
{
}
/// <summary>
/// Initializes a new instance of the <see cref="GestureListener"/> class to receive specific gestures.
/// </summary>
/// <param name="parent">The parent.</param>
/// <param name="configs">The gesture configurations.</param>
public GestureListener( Control parent, GestureConfig[] configs )
{
if ( parent.IsHandleCreated )
{
Initialize( parent );
}
else
{
parent.HandleCreated += OnHandleCreated;
}
parent.HandleDestroyed += OnHandleDestroyed;
_parent = parent;
m_configs = configs;
_touchInputSize = Marshal.SizeOf(new TOUCHINPUT());
}
#endregion
#region Private Methods
[DllImport("user32")]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool RegisterTouchWindow(System.IntPtr hWnd, ulong ulFlags);
private void Initialize( Control parent )
{
AssignHandle( parent.Handle );
NativeMethods.SetGestureConfig( parent.Handle, m_configs );
}
public void LoadMultitouch()
{
Task.Run(async () =>
{
await Task.Delay(1000);
Action a = () =>
{
if (!RegisterTouchWindow(_parent.Handle, 0))
{
}
};
_parent.Invoke(a);
});
}
private void OnHandleCreated( object sender, EventArgs e )
{
// Window is now created, assign handle to NativeWindow.
var control = sender as Control;
if ( control != null )
{
Initialize( control );
}
}
private void OnHandleDestroyed( object sender, EventArgs e )
{
// Window was destroyed, release hook.
ReleaseHandle();
}
#endregion
#region WndProc
/// <summary>
/// Invokes the default window procedure associated with this window.
/// </summary>
/// <param name="m">A <see cref="T:System.Windows.Forms.Message"/> that is associated with the current Windows message.</param>
[PermissionSet( SecurityAction.Demand, Name = "FullTrust" )]
protected override void WndProc( ref Message m )
{
bool handled = false;
// Listen for operating system messages
switch ( m.Msg )
{
case WindowMessage.WM_GESTURE:
GestureInfo info;
if ( NativeMethods.GetGestureInfo( m.LParam, out info ) )
{
switch ( (GestureId)info.id )
{
case GestureId.Pan:
handled = OnPan( info );
break;
case GestureId.PressAndTap:
handled = OnPressAndTap( info );
break;
case GestureId.Rotate:
handled = OnRotate( info );
break;
case GestureId.TwoFingerTap:
handled = OnTwoFingerTap( info );
break;
case GestureId.Zoom:
handled = OnZoom( info );
break;
}
if ( handled )
{
NativeMethods.CloseGestureInfoHandle( m.LParam );
}
}
break;
case WindowMessage.WM_TOUCH:
MessageBox.Show("touch");
this.DecodeTouch(ref m);
break;
//case WindowMessage.WM_POINTERUPDATE:
// MessageBox.Show("ptr");
// break;
}
if ( !handled )
{
base.WndProc( ref m );
}
}
private static int LoWord(int number)
{
return (number & 0xffff);
}
[StructLayout(LayoutKind.Sequential)]
private struct TOUCHINPUT
{
public int x;
public int y;
public System.IntPtr hSource;
public int dwID;
public int dwFlags;
public int dwMask;
public int dwTime;
public System.IntPtr dwExtraInfo;
public int cxContact;
public int cyContact;
}
[StructLayout(LayoutKind.Sequential)]
private struct POINTS
{
public short x;
public short y;
}
public event EventHandler<WMTouchEventArgs> Touchdown; // touch down event handler
public event EventHandler<WMTouchEventArgs> Touchup; // touch up event handler
public event EventHandler<WMTouchEventArgs> TouchMove; // touch move event handler
// EventArgs passed to Touch handlers
public class WMTouchEventArgs : System.EventArgs
{
// Private data members
private int x; // touch x client coordinate in pixels
private int y; // touch y client coordinate in pixels
private int id; // contact ID
private int mask; // mask which fields in the structure are valid
private int flags; // flags
private int time; // touch event time
private int contactX; // x size of the contact area in pixels
private int contactY; // y size of the contact area in pixels
// Access to data members
public int LocationX
{
get { return x; }
set { x = value; }
}
public int LocationY
{
get { return y; }
set { y = value; }
}
public int Id
{
get { return id; }
set { id = value; }
}
public int Flags
{
get { return flags; }
set { flags = value; }
}
public int Mask
{
get { return mask; }
set { mask = value; }
}
public int Time
{
get { return time; }
set { time = value; }
}
public int ContactX
{
get { return contactX; }
set { contactX = value; }
}
public int ContactY
{
get { return contactY; }
set { contactY = value; }
}
public bool IsPrimaryContact
{
get { return (flags & WindowMessage.TOUCHEVENTF_PRIMARY) != 0; }
}
// Constructor
public WMTouchEventArgs()
{
}
}
[DllImport("user32")]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool GetTouchInputInfo(System.IntPtr hTouchInput, int cInputs, [In, Out] TOUCHINPUT[] pInputs, int cbSize);
[DllImport("user32")]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern void CloseTouchInputHandle(System.IntPtr lParam);
public bool DecodeTouch(ref Message m)
{
// More than one touchinput may be associated with a touch message,
// so an array is needed to get all event information.
int inputCount = LoWord(m.WParam.ToInt32()); // Number of touch inputs, actual per-contact messages
TOUCHINPUT[] inputs; // Array of TOUCHINPUT structures
inputs = new TOUCHINPUT[inputCount]; // Allocate the storage for the parameters of the per-contact messages
// Unpack message parameters into the array of TOUCHINPUT structures, each
// representing a message for one single contact.
if (!GetTouchInputInfo(m.LParam, inputCount, inputs, _touchInputSize))
{
// Get touch info failed.
return false;
}
// For each contact, dispatch the message to the appropriate message
// handler.
bool handled = false; // Boolean, is message handled
for (int i = 0; i < inputCount; i++)
{
TOUCHINPUT ti = inputs[i];
// Assign a handler to this message.
EventHandler<WMTouchEventArgs> handler = null; // Touch event handler
if ((ti.dwFlags & WindowMessage.TOUCHEVENTF_DOWN) != 0)
{
handler = Touchdown;
}
else if ((ti.dwFlags & WindowMessage.TOUCHEVENTF_UP) != 0)
{
handler = Touchup;
}
else if ((ti.dwFlags & WindowMessage.TOUCHEVENTF_MOVE) != 0)
{
handler = TouchMove;
}
// Convert message parameters into touch event arguments and handle the event.
if (handler != null)
{
// Convert the raw touchinput message into a touchevent.
WMTouchEventArgs te = new WMTouchEventArgs(); // Touch event arguments
// TOUCHINFO point coordinates and contact size is in 1/100 of a pixel; convert it to pixels.
// Also convert screen to client coordinates.
te.ContactY = ti.cyContact / 100;
te.ContactX = ti.cxContact / 100;
te.Id = ti.dwID;
{
Point pt = _parent.PointToClient(new Point(ti.x / 100, ti.y / 100));
te.LocationX = pt.X;
te.LocationY = pt.Y;
}
te.Time = ti.dwTime;
te.Mask = ti.dwMask;
te.Flags = ti.dwFlags;
// Invoke the event handler.
handler(this, te);
// Mark this event as handled.
handled = true;
}
}
CloseTouchInputHandle(m.LParam);
return handled;
}
private bool OnPan( GestureInfo info )
{
if ( Pan != null )
{
if ( info.Begin )
{
_lastPanPoint = new Point( info.location.x, info.location.y );
}
var args = new PanEventArgs( info, _lastPanPoint );
_lastPanPoint = new Point( info.location.x, info.location.y );
Pan( this, args );
return args.Handled;
}
return false;
}
private bool OnPressAndTap( GestureInfo info )
{
if ( PressAndTap != null )
{
var args = new PressAndTapEventArgs( info );
PressAndTap( this, args );
return args.Handled;
}
return false;
}
private bool OnRotate( GestureInfo info )
{
if ( Rotate != null )
{
if ( info.Begin )
{
_lastRotation = 0;
}
var args = new RotateEventArgs( info, _lastRotation );
if ( !info.Begin )
{
// First rotation is the angle the fingers are at, so don't use it
_lastRotation = args.TotalAngle;
}
Rotate( this, args );
return args.Handled;
}
return false;
}
private bool OnTwoFingerTap( GestureInfo info )
{
if ( TwoFingerTap != null )
{
var args = new TwoFingerTapEventArgs( info );
TwoFingerTap( this, args );
return args.Handled;
}
return false;
}
private bool OnZoom( GestureInfo info )
{
if ( Zoom != null )
{
if ( info.Begin )
{
_lastZoom = info.arguments;
}
var args = new ZoomEventArgs( info, _lastZoom );
_lastZoom = args.Distance;
Zoom( this, args );
return args.Handled;
}
return false;
}
#endregion
}
}

View File

@@ -0,0 +1,341 @@
#region The MIT License (MIT)
//
// Copyright (c) 2011 Robert Prouse http://www.alteridem.net
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
// Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
#endregion
#region Using Directives
using System;
using System.Runtime.InteropServices;
#endregion
namespace MaterialSkin.Gesture
{
internal static class NativeMethods
{
#region Private Delegates
[UnmanagedFunctionPointer( CallingConvention.Cdecl )]
private delegate bool GetGestureInfoPtr( IntPtr gestureInfoHandle, ref GestureInfo pGestureInfo );
[UnmanagedFunctionPointer( CallingConvention.Cdecl )]
private delegate bool CloseGestureInfoHandlePtr( IntPtr gestureInfoHandle );
[UnmanagedFunctionPointer( CallingConvention.Cdecl )]
private delegate bool SetGestureConfigPtr( IntPtr hwnd, uint reserved, uint ids, GestureConfig[] configs, uint size );
private static readonly GetGestureInfoPtr _pGetGestureInfoPtr;
private static readonly CloseGestureInfoHandlePtr _pCloseGestureInfoHandle;
private static readonly SetGestureConfigPtr _pSetGestureConfig;
#endregion
#region Static Construction
static NativeMethods()
{
var user32 = new UnmanagedLibrary( "user32" );
_pGetGestureInfoPtr = user32.GetUnmanagedFunction<GetGestureInfoPtr>( "GetGestureInfo" );
_pCloseGestureInfoHandle = user32.GetUnmanagedFunction<CloseGestureInfoHandlePtr>( "CloseGestureInfoHandle" );
_pSetGestureConfig = user32.GetUnmanagedFunction<SetGestureConfigPtr>( "SetGestureConfig" );
}
#endregion
#region Public Interface
/// <summary>
/// Registers the HWND to receive all gestures.
/// </summary>
/// <remarks>
/// http://msdn.microsoft.com/en-us/library/windows/desktop/dd353231%28v=vs.85%29.aspx
/// </remarks>
/// <param name="hwnd">The HWND.</param>
/// <returns></returns>
public static bool SetGestureConfig( IntPtr hwnd )
{
if ( _pSetGestureConfig == null )
return false;
var configs = new[] { new GestureConfig( 0, GestureConfigurationFlag.GC_ALLGESTURES, 0 ) };
return SetGestureConfig(hwnd, configs);
}
/// <summary>
/// Registers the HWND to receive specific gestures.
/// </summary>
/// <remarks>
/// http://msdn.microsoft.com/en-us/library/windows/desktop/dd353231%28v=vs.85%29.aspx
/// </remarks>
/// <param name="hwnd">The HWND.</param>
/// <param name="configs">The gesture configurations</param>
/// <returns></returns>
public static bool SetGestureConfig( IntPtr hwnd, GestureConfig[] configs )
{
return _pSetGestureConfig( hwnd, 0, 1, configs, (uint)Marshal.SizeOf( typeof( GestureConfig ) ) );
}
/// <summary>
/// Gets the gesture info.
/// </summary>
/// <param name="gestureInfoHandle">The gesture info handle.</param>
/// <param name="gestureInfo">The gesture info.</param>
/// <returns></returns>
public static bool GetGestureInfo( IntPtr gestureInfoHandle, out GestureInfo gestureInfo )
{
gestureInfo = new GestureInfo();
if ( _pGetGestureInfoPtr == null )
return false;
gestureInfo.size = Marshal.SizeOf( gestureInfo );
return _pGetGestureInfoPtr( gestureInfoHandle, ref gestureInfo );
}
/// <summary>
/// Closes the gesture info handle.
/// </summary>
/// <param name="gestureInfoHandle">The gesture info handle.</param>
/// <returns></returns>
public static bool CloseGestureInfoHandle( IntPtr gestureInfoHandle )
{
if ( _pCloseGestureInfoHandle == null )
return false;
return _pCloseGestureInfoHandle( gestureInfoHandle );
}
#endregion
}
/// <summary>
/// Gesture configuration flags
/// </summary>
internal static class GestureConfigurationFlag
{
public const int GC_ALLGESTURES = 0x00000001;
public const int GC_ZOOM = 0x00000001;
public const int GC_PAN = 0x00000001;
public const int GC_PAN_WITH_SINGLE_FINGER_VERTICALLY = 0x00000002;
public const int GC_PAN_WITH_SINGLE_FINGER_HORIZONTALLY = 0x00000004;
public const int GC_PAN_WITH_GUTTER = 0x00000008;
public const int GC_PAN_WITH_INERTIA = 0x00000010;
public const int GC_ROTATE = 0x00000001;
public const int GC_TWOFINGERTAP = 0x00000001;
public const int GC_PRESSANDTAP = 0x00000001;
}
/// <summary>
/// Gesture flags - GestureInfo.flags
/// </summary>
[Flags]
public enum GestureFlags
{
/// <summary>
/// GF_BEGIN
/// </summary>
Begin = 0x1,
/// <summary>
/// GF_INERTIA
/// </summary>
Inertia = 0x2,
/// <summary>
/// GF_END
/// </summary>
End = 0x4
}
/// <summary>
/// Gesture IDs - GestureInfo.id
/// </summary>
public enum GestureId
{
/// <summary>
/// GID_BEGIN
/// </summary>
Begin = 1,
/// <summary>
/// GID_END
/// </summary>
End = 2,
/// <summary>
/// GID_ZOOM
/// </summary>
Zoom = 3,
/// <summary>
/// GID_PAN
/// </summary>
Pan = 4,
/// <summary>
/// GID_ROTATE
/// </summary>
Rotate = 5,
/// <summary>
/// GID_TWOFINGERTAP
/// </summary>
TwoFingerTap = 6,
/// <summary>
/// GID_PRESSANDTAP
/// </summary>
PressAndTap = 7
}
/// <summary>
/// Window Messages
/// </summary>
internal static class WindowMessage
{
public const int WM_TOUCH = 0x0240;
public const int WM_POINTERUPDATE =0x0245;
public const int WM_GESTURE = 0x0119;
public const int WM_GESTURENOTIFY = 0x011A;
public const int TOUCHEVENTF_MOVE = 0x0001;
public const int TOUCHEVENTF_DOWN = 0x0002;
public const int TOUCHEVENTF_UP = 0x0004;
public const int TOUCHEVENTF_INRANGE = 0x0008;
public const int TOUCHEVENTF_PRIMARY = 0x0010;
public const int TOUCHEVENTF_NOCOALESCE = 0x0020;
public const int TOUCHEVENTF_PEN = 0x0040;
// Touch input mask values (TOUCHINPUT.dwMask) [winuser.h]
public const int TOUCHINPUTMASKF_TIMEFROMSYSTEM = 0x0001; // the dwTime field contains a system generated value
public const int TOUCHINPUTMASKF_EXTRAINFO = 0x0002; // the dwExtraInfo field is valid
public const int TOUCHINPUTMASKF_CONTACTAREA = 0x0004; // the cxContact and cyContact fields are valid
}
[StructLayout( LayoutKind.Sequential )]
public struct Points
{
public short x;
public short y;
}
/// <summary>
/// Gesture configuration structure
/// </summary>
/// <remarks>
/// Used in SetGestureConfig and GetGestureConfig
/// http://msdn.microsoft.com/en-us/library/windows/desktop/dd353231%28v=vs.85%29.aspx
/// </remarks>
[StructLayout( LayoutKind.Sequential )]
public struct GestureConfig
{
public GestureConfig( uint id, uint want, uint block )
{
Id = id;
Want = want;
Block = block;
}
/// <summary>
/// The identifier for the type of configuration that will have messages enabled or disabled.
/// </summary>
public uint Id;
/// <summary>
/// The messages to enable.
/// </summary>
public uint Want;
/// <summary>
/// The messages to disable.
/// </summary>
public uint Block;
}
/// <summary>
/// Stores information about a gesture.
/// </summary>
/// <remarks>
/// - Pass the HGESTUREINFO received in the WM_GESTURE message lParam into the
/// GetGestureInfo function to retrieve this information.
/// - If cbExtraArgs is non-zero, pass the HGESTUREINFO received in the WM_GESTURE
/// message lParam into the GetGestureExtraArgs function to retrieve extended
/// argument information.
/// </remarks>
[StructLayout( LayoutKind.Sequential )]
public struct GestureInfo
{
/// <summary>
/// The size of the structure, in bytes. The caller must set this.
/// </summary>
public int size;
/// <summary>
/// The state of the gesture. Contains GestureFlags.
/// </summary>
public int flags;
/// <summary>
/// The identifier of the gesture command. Contains GestureId.
/// </summary>
public int id;
/// <summary>
/// A handle to the window that is targeted by this gesture.
/// </summary>
public IntPtr hwnd;
/// <summary>
/// A Points structure containing the coordinates associated with the gesture. These coordinates are always relative to the origin of the screen.
/// </summary>
public Points location;
/// <summary>
/// An internally used identifier for the structure.
/// </summary>
public int instanceId;
/// <summary>
/// An internally used identifier for the sequence.
/// </summary>
public int sequenceId;
/// <summary>
/// A 64-bit unsigned integer that contains the arguments for gestures that fit into 8 bytes.
/// </summary>
public Int64 arguments;
/// <summary>
/// The size, in bytes, of extra arguments that accompany this gesture.
/// </summary>
public int extraArguments;
/// <summary>
/// Gets a value indicating whether the <see cref="GestureFlags"/> Begin is set.
/// </summary>
public bool Begin
{
get { return ((GestureFlags)flags & GestureFlags.Begin) == GestureFlags.Begin; }
}
/// <summary>
/// Gets a value indicating whether the <see cref="GestureFlags"/> End is set.
/// </summary>
public bool End
{
get { return ((GestureFlags)flags & GestureFlags.End) == GestureFlags.End; }
}
/// <summary>
/// Gets a value indicating whether the <see cref="GestureFlags"/> Inertia is set
/// </summary>
public bool Inertia
{
get { return ((GestureFlags)flags & GestureFlags.Inertia) == GestureFlags.Inertia; }
}
}
}

View File

@@ -0,0 +1,142 @@
#region Copyright (c) Microsoft Corporation.
//
// The source code of UnmanagedLibrary.cs is quoted from Mike Stall's article:
//
// Type-safe Managed wrappers for kernel32!GetProcAddress
// http://blogs.msdn.com/jmstall/archive/2007/01/06/Typesafe-GetProcAddress.aspx
//
// This source is subject to the Microsoft Public License.
// See http://www.opensource.org/licenses/MS-PL.
// All other rights reserved.
//
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
// EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
//
#endregion
#region Using Directives
using System;
using System.IO;
using System.Runtime.ConstrainedExecution;
using System.Runtime.InteropServices;
using System.Security.Permissions;
using Microsoft.Win32.SafeHandles;
#endregion
namespace MaterialSkin.Gesture
{
/// <summary>
/// Utility class to wrap an unmanaged DLL and be responsible for freeing it.
/// </summary>
/// <remarks>This is a managed wrapper over the native LoadLibrary, GetProcAddress, and
/// FreeLibrary calls.
/// </remarks>
public sealed class UnmanagedLibrary : IDisposable
{
#region Safe Handles and Native imports
// See http://msdn.microsoft.com/msdnmag/issues/05/10/Reliability/ for more about safe handles.
[SecurityPermission( SecurityAction.LinkDemand, UnmanagedCode = true )]
sealed class SafeLibraryHandle : SafeHandleZeroOrMinusOneIsInvalid
{
private SafeLibraryHandle() : base( true ) { }
protected override bool ReleaseHandle()
{
return NativeMethods.FreeLibrary( handle );
}
}
static class NativeMethods
{
const string KERNEL32 = "kernel32";
[DllImport( KERNEL32, CharSet = CharSet.Auto, BestFitMapping = false, SetLastError = true )]
public static extern SafeLibraryHandle LoadLibrary( string fileName );
[ReliabilityContract( Consistency.WillNotCorruptState, Cer.Success )]
[DllImport( KERNEL32, SetLastError = true )]
[return: MarshalAs( UnmanagedType.Bool )]
public static extern bool FreeLibrary( IntPtr hModule );
[DllImport( KERNEL32 )]
public static extern IntPtr GetProcAddress( SafeLibraryHandle hModule, String procname );
}
#endregion // Safe Handles and Native imports
/// <summary>
/// Constructor to load a dll and be responible for freeing it.
/// </summary>
/// <param name="fileName">full path name of dll to load</param>
/// <exception cref="FileNotFoundException">if fileName can't be found</exception>
/// <remarks>Throws exceptions on failure. Most common failure would be file-not-found, or
/// that the file is not a loadable image.</remarks>
public UnmanagedLibrary( string fileName )
{
m_hLibrary = NativeMethods.LoadLibrary( fileName );
if ( m_hLibrary.IsInvalid )
{
int hr = Marshal.GetHRForLastWin32Error();
Marshal.ThrowExceptionForHR( hr );
}
}
/// <summary>
/// Dynamically lookup a function in the dll via kernel32!GetProcAddress.
/// </summary>
/// <param name="functionName">raw name of the function in the export table.</param>
/// <returns>null if function is not found. Else a delegate to the unmanaged function.
/// </returns>
/// <remarks>GetProcAddress results are valid as long as the dll is not yet unloaded. This
/// is very very dangerous to use since you need to ensure that the dll is not unloaded
/// until after you're done with any objects implemented by the dll. For example, if you
/// get a delegate that then gets an IUnknown implemented by this dll,
/// you can not dispose this library until that IUnknown is collected. Else, you may free
/// the library and then the CLR may call release on that IUnknown and it will crash.</remarks>
public TDelegate GetUnmanagedFunction<TDelegate>( string functionName ) where TDelegate : class
{
IntPtr p = NativeMethods.GetProcAddress( m_hLibrary, functionName );
// Failure is a common case, especially for adaptive code.
if ( p == IntPtr.Zero )
{
return null;
}
Delegate function = Marshal.GetDelegateForFunctionPointer( p, typeof( TDelegate ) );
// Ideally, we'd just make the constraint on TDelegate be
// System.Delegate, but compiler error CS0702 (constrained can't be System.Delegate)
// prevents that. So we make the constraint system.object and do the cast from object-->TDelegate.
object o = function;
return (TDelegate)o;
}
#region IDisposable Members
/// <summary>
/// Call FreeLibrary on the unmanaged dll. All function pointers
/// handed out from this class become invalid after this.
/// </summary>
/// <remarks>This is very dangerous because it suddenly invalidate
/// everything retrieved from this dll. This includes any functions
/// handed out via GetProcAddress, and potentially any objects returned
/// from those functions (which may have an implemention in the
/// dll).
/// </remarks>
public void Dispose()
{
if ( !m_hLibrary.IsClosed )
{
m_hLibrary.Close();
}
}
// Unmanaged resource. CLR will ensure SafeHandles get freed, without requiring a finalizer on this class.
SafeLibraryHandle m_hLibrary;
#endregion
}
}

View File

@@ -0,0 +1,17 @@
namespace MaterialSkin
{
public interface IMaterialControl
{
int Depth { get; set; }
MaterialSkinManager SkinManager { get; }
MouseState MouseState { get; set; }
}
public enum MouseState
{
HOVER,
DOWN,
OUT
}
}

View File

@@ -0,0 +1,117 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0-windows</TargetFramework>
<UseWindowsForms>true</UseWindowsForms>
</PropertyGroup>
<ItemGroup>
<None Remove="Resources\Roboto-Medium.ttf" />
<None Remove="Resources\Roboto-Regular.ttf" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="Resources\Roboto-Medium.ttf" />
<EmbeddedResource Include="Resources\Roboto-Regular.ttf" />
</ItemGroup>
<ItemGroup>
<Compile Update="Controls\MaterialCheckBox.cs">
<SubType>Component</SubType>
</Compile>
<Compile Update="Controls\MaterialComboBox.cs">
<SubType>Component</SubType>
</Compile>
<Compile Update="Controls\MaterialContextMenuStrip.cs">
<SubType>Component</SubType>
</Compile>
<Compile Update="Controls\MaterialDivider.cs">
<SubType>Component</SubType>
</Compile>
<Compile Update="Controls\MaterialFlatButton.cs">
<SubType>Component</SubType>
</Compile>
<Compile Update="Controls\MaterialForm.cs">
<SubType>Form</SubType>
</Compile>
<Compile Update="Controls\MaterialIcon.cs">
<SubType>Component</SubType>
</Compile>
<Compile Update="Controls\MaterialIndicator.cs">
<SubType>UserControl</SubType>
</Compile>
<Compile Update="Controls\MaterialIndicator.Designer.cs">
<DependentUpon>MaterialIndicator.cs</DependentUpon>
</Compile>
<Compile Update="Controls\MaterialLabel.cs">
<SubType>Component</SubType>
</Compile>
<Compile Update="Controls\MaterialListView.cs">
<SubType>Component</SubType>
</Compile>
<Compile Update="Controls\MaterialLoader.cs">
<SubType>Form</SubType>
</Compile>
<Compile Update="Controls\MaterialLoader.Designer.cs">
<DependentUpon>MaterialLoader.cs</DependentUpon>
</Compile>
<Compile Update="Controls\MaterialMessageBox.cs">
<SubType>Form</SubType>
</Compile>
<Compile Update="Controls\MaterialMessageBox.Designer.cs">
<DependentUpon>MaterialMessageBox.cs</DependentUpon>
</Compile>
<Compile Update="Controls\MaterialPanel.cs">
<SubType>Component</SubType>
</Compile>
<Compile Update="Controls\MaterialProgressBar.cs">
<SubType>Component</SubType>
</Compile>
<Compile Update="Controls\MaterialRadioButton.cs">
<SubType>Component</SubType>
</Compile>
<Compile Update="Controls\MaterialRaisedButton.cs">
<SubType>Component</SubType>
</Compile>
<Compile Update="Controls\MaterialSingleLineTextField.cs">
<SubType>Component</SubType>
</Compile>
<Compile Update="Controls\MaterialTabControl.cs">
<SubType>Component</SubType>
</Compile>
<Compile Update="Controls\MaterialTabSelector.cs">
<SubType>Component</SubType>
</Compile>
<Compile Update="Controls\MaterialUpDown.cs">
<SubType>UserControl</SubType>
</Compile>
<Compile Update="Controls\MaterialUpDown.Designer.cs">
<DependentUpon>MaterialUpDown.cs</DependentUpon>
</Compile>
<Compile Update="Resources\Resource1.Designer.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<DependentUpon>Resource1.resx</DependentUpon>
</Compile>
</ItemGroup>
<ItemGroup>
<EmbeddedResource Update="Controls\MaterialIndicator.resx">
<DependentUpon>MaterialIndicator.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Update="Controls\MaterialLoader.resx">
<DependentUpon>MaterialLoader.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Update="Controls\MaterialMessageBox.resx">
<DependentUpon>MaterialMessageBox.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Update="Controls\MaterialUpDown.resx">
<DependentUpon>MaterialUpDown.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Update="Resources\Resource1.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resource1.Designer.cs</LastGenOutput>
</EmbeddedResource>
</ItemGroup>
</Project>

View File

@@ -0,0 +1,349 @@
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Text;
using System.Linq;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using MaterialSkin.Controls;
using MaterialSkin.Core.Resources;
namespace MaterialSkin
{
public class MaterialSkinManager
{
public static void ConfigureForInspectron()
{
Instance.ColorScheme = new ColorScheme(Primary.Red800, Primary.Red800, Primary.Red400, Accent.Red200, TextShade.BLACK);
}
//Singleton instance
private static MaterialSkinManager _instance;
//Forms to control
private readonly List<MaterialForm> _formsToManage = new List<MaterialForm>();
//Theme
private Themes _theme;
public Themes Theme
{
get { return _theme; }
set
{
_theme = value;
UpdateBackgrounds();
}
}
private ColorScheme _colorScheme;
public ColorScheme ColorScheme
{
get { return _colorScheme; }
set
{
_colorScheme = value;
UpdateBackgrounds();
}
}
public enum Themes : byte
{
LIGHT,
DARK
}
//Constant color values
private static readonly Color PRIMARY_TEXT_BLACK = Color.FromArgb(222, 0, 0, 0);
private static readonly Brush PRIMARY_TEXT_BLACK_BRUSH = new SolidBrush(PRIMARY_TEXT_BLACK);
public static Color SECONDARY_TEXT_BLACK = Color.FromArgb(138, 0, 0, 0);
public static Brush SECONDARY_TEXT_BLACK_BRUSH = new SolidBrush(SECONDARY_TEXT_BLACK);
private static readonly Color DISABLED_OR_HINT_TEXT_BLACK = Color.FromArgb(66, 0, 0, 0);
private static readonly Brush DISABLED_OR_HINT_TEXT_BLACK_BRUSH = new SolidBrush(DISABLED_OR_HINT_TEXT_BLACK);
private static readonly Color DIVIDERS_BLACK = Color.FromArgb(31, 0, 0, 0);
private static readonly Brush DIVIDERS_BLACK_BRUSH = new SolidBrush(DIVIDERS_BLACK);
private static readonly Color PRIMARY_TEXT_WHITE = Color.FromArgb(255, 255, 255, 255);
private static readonly Brush PRIMARY_TEXT_WHITE_BRUSH = new SolidBrush(PRIMARY_TEXT_WHITE);
public static Color SECONDARY_TEXT_WHITE = Color.FromArgb(179, 255, 255, 255);
public static Brush SECONDARY_TEXT_WHITE_BRUSH = new SolidBrush(SECONDARY_TEXT_WHITE);
private static readonly Color DISABLED_OR_HINT_TEXT_WHITE = Color.FromArgb(77, 255, 255, 255);
private static readonly Brush DISABLED_OR_HINT_TEXT_WHITE_BRUSH = new SolidBrush(DISABLED_OR_HINT_TEXT_WHITE);
private static readonly Color DIVIDERS_WHITE = Color.FromArgb(31, 255, 255, 255);
private static readonly Brush DIVIDERS_WHITE_BRUSH = new SolidBrush(DIVIDERS_WHITE);
// Checkbox colors
private static readonly Color CHECKBOX_OFF_LIGHT = Color.FromArgb(138, 0, 0, 0);
private static readonly Brush CHECKBOX_OFF_LIGHT_BRUSH = new SolidBrush(CHECKBOX_OFF_LIGHT);
private static readonly Color CHECKBOX_OFF_DISABLED_LIGHT = Color.FromArgb(66, 0, 0, 0);
private static readonly Brush CHECKBOX_OFF_DISABLED_LIGHT_BRUSH = new SolidBrush(CHECKBOX_OFF_DISABLED_LIGHT);
private static readonly Color CHECKBOX_OFF_DARK = Color.FromArgb(179, 255, 255, 255);
private static readonly Brush CHECKBOX_OFF_DARK_BRUSH = new SolidBrush(CHECKBOX_OFF_DARK);
private static readonly Color CHECKBOX_OFF_DISABLED_DARK = Color.FromArgb(77, 255, 255, 255);
private static readonly Brush CHECKBOX_OFF_DISABLED_DARK_BRUSH = new SolidBrush(CHECKBOX_OFF_DISABLED_DARK);
//Raised button
private static readonly Color RAISED_BUTTON_BACKGROUND = Color.FromArgb(255, 255, 255, 255);
private static readonly Brush RAISED_BUTTON_BACKGROUND_BRUSH = new SolidBrush(RAISED_BUTTON_BACKGROUND);
private static readonly Color RAISED_BUTTON_TEXT_LIGHT = PRIMARY_TEXT_WHITE;
private static readonly Brush RAISED_BUTTON_TEXT_LIGHT_BRUSH = new SolidBrush(RAISED_BUTTON_TEXT_LIGHT);
private static readonly Color RAISED_BUTTON_TEXT_DARK = PRIMARY_TEXT_BLACK;
private static readonly Brush RAISED_BUTTON_TEXT_DARK_BRUSH = new SolidBrush(RAISED_BUTTON_TEXT_DARK);
//Flat button
private static readonly Color FLAT_BUTTON_BACKGROUND_HOVER_LIGHT = Color.FromArgb(20.PercentageToColorComponent(), 0x999999.ToColor());
private static readonly Brush FLAT_BUTTON_BACKGROUND_HOVER_LIGHT_BRUSH = new SolidBrush(FLAT_BUTTON_BACKGROUND_HOVER_LIGHT);
private static readonly Color FLAT_BUTTON_BACKGROUND_PRESSED_LIGHT = Color.FromArgb(40.PercentageToColorComponent(), 0x999999.ToColor());
private static readonly Brush FLAT_BUTTON_BACKGROUND_PRESSED_LIGHT_BRUSH = new SolidBrush(FLAT_BUTTON_BACKGROUND_PRESSED_LIGHT);
private static readonly Color FLAT_BUTTON_DISABLEDTEXT_LIGHT = Color.FromArgb(26.PercentageToColorComponent(), 0x000000.ToColor());
private static readonly Brush FLAT_BUTTON_DISABLEDTEXT_LIGHT_BRUSH = new SolidBrush(FLAT_BUTTON_DISABLEDTEXT_LIGHT);
private static readonly Color FLAT_BUTTON_BACKGROUND_HOVER_DARK = Color.FromArgb(15.PercentageToColorComponent(), 0xCCCCCC.ToColor());
private static readonly Brush FLAT_BUTTON_BACKGROUND_HOVER_DARK_BRUSH = new SolidBrush(FLAT_BUTTON_BACKGROUND_HOVER_DARK);
private static readonly Color FLAT_BUTTON_BACKGROUND_PRESSED_DARK = Color.FromArgb(25.PercentageToColorComponent(), 0xCCCCCC.ToColor());
private static readonly Brush FLAT_BUTTON_BACKGROUND_PRESSED_DARK_BRUSH = new SolidBrush(FLAT_BUTTON_BACKGROUND_PRESSED_DARK);
private static readonly Color FLAT_BUTTON_DISABLEDTEXT_DARK = Color.FromArgb(30.PercentageToColorComponent(), 0xFFFFFF.ToColor());
private static readonly Brush FLAT_BUTTON_DISABLEDTEXT_DARK_BRUSH = new SolidBrush(FLAT_BUTTON_DISABLEDTEXT_DARK);
//ContextMenuStrip
private static readonly Color CMS_BACKGROUND_LIGHT_HOVER = Color.FromArgb(255, 238, 238, 238);
private static readonly Brush CMS_BACKGROUND_HOVER_LIGHT_BRUSH = new SolidBrush(CMS_BACKGROUND_LIGHT_HOVER);
private static readonly Color CMS_BACKGROUND_DARK_HOVER = Color.FromArgb(38, 204, 204, 204);
private static readonly Brush CMS_BACKGROUND_HOVER_DARK_BRUSH = new SolidBrush(CMS_BACKGROUND_DARK_HOVER);
//Application background
private static readonly Color BACKGROUND_LIGHT = Color.FromArgb(255, 255, 255, 255);
private static Brush BACKGROUND_LIGHT_BRUSH = new SolidBrush(BACKGROUND_LIGHT);
private static readonly Color BACKGROUND_DARK = Color.FromArgb(255, 51, 51, 51);
private static Brush BACKGROUND_DARK_BRUSH = new SolidBrush(BACKGROUND_DARK);
//Application action bar
public readonly Color ACTION_BAR_TEXT = Color.FromArgb(255, 255, 255, 255);
public readonly Brush ACTION_BAR_TEXT_BRUSH = new SolidBrush(Color.FromArgb(255, 255, 255, 255));
public readonly Color ACTION_BAR_TEXT_SECONDARY = Color.FromArgb(153, 255, 255, 255);
public readonly Brush ACTION_BAR_TEXT_SECONDARY_BRUSH = new SolidBrush(Color.FromArgb(153, 255, 255, 255));
public Color GetPrimaryTextColor()
{
return Theme == Themes.LIGHT ? PRIMARY_TEXT_BLACK : PRIMARY_TEXT_WHITE;
}
public Brush GetPrimaryTextBrush()
{
return Theme == Themes.LIGHT ? PRIMARY_TEXT_BLACK_BRUSH : PRIMARY_TEXT_WHITE_BRUSH;
}
public Color GetSecondaryTextColor()
{
return Theme == Themes.LIGHT ? SECONDARY_TEXT_BLACK : SECONDARY_TEXT_WHITE;
}
public Brush GetSecondaryTextBrush()
{
return Theme == Themes.LIGHT ? SECONDARY_TEXT_BLACK_BRUSH : SECONDARY_TEXT_WHITE_BRUSH;
}
public Color GetDisabledOrHintColor()
{
return Theme == Themes.LIGHT ? DISABLED_OR_HINT_TEXT_BLACK : DISABLED_OR_HINT_TEXT_WHITE;
}
public Brush GetDisabledOrHintBrush()
{
return Theme == Themes.LIGHT ? DISABLED_OR_HINT_TEXT_BLACK_BRUSH : DISABLED_OR_HINT_TEXT_WHITE_BRUSH;
}
public Color GetDividersColor()
{
return Theme == Themes.LIGHT ? DIVIDERS_BLACK : DIVIDERS_WHITE;
}
public Brush GetDividersBrush()
{
return Theme == Themes.LIGHT ? DIVIDERS_BLACK_BRUSH : DIVIDERS_WHITE_BRUSH;
}
public Color GetCheckboxOffColor()
{
return Theme == Themes.LIGHT ? CHECKBOX_OFF_LIGHT : CHECKBOX_OFF_DARK;
}
public Brush GetCheckboxOffBrush()
{
return Theme == Themes.LIGHT ? CHECKBOX_OFF_LIGHT_BRUSH : CHECKBOX_OFF_DARK_BRUSH;
}
public Color GetCheckBoxOffDisabledColor()
{
return Theme == Themes.LIGHT ? CHECKBOX_OFF_DISABLED_LIGHT : CHECKBOX_OFF_DISABLED_DARK;
}
public Brush GetCheckBoxOffDisabledBrush()
{
return Theme == Themes.LIGHT ? CHECKBOX_OFF_DISABLED_LIGHT_BRUSH : CHECKBOX_OFF_DISABLED_DARK_BRUSH;
}
public Brush GetRaisedButtonBackgroundBrush()
{
return RAISED_BUTTON_BACKGROUND_BRUSH;
}
public Brush GetRaisedButtonTextBrush(bool primary)
{
return primary ? RAISED_BUTTON_TEXT_LIGHT_BRUSH : RAISED_BUTTON_TEXT_DARK_BRUSH;
}
public Color GetFlatButtonHoverBackgroundColor()
{
return Theme == Themes.LIGHT ? FLAT_BUTTON_BACKGROUND_HOVER_LIGHT : FLAT_BUTTON_BACKGROUND_HOVER_DARK;
}
public Brush GetFlatButtonHoverBackgroundBrush()
{
return Theme == Themes.LIGHT ? FLAT_BUTTON_BACKGROUND_HOVER_LIGHT_BRUSH : FLAT_BUTTON_BACKGROUND_HOVER_DARK_BRUSH;
}
public Color GetFlatButtonPressedBackgroundColor()
{
return Theme == Themes.LIGHT ? FLAT_BUTTON_BACKGROUND_PRESSED_LIGHT : FLAT_BUTTON_BACKGROUND_PRESSED_DARK;
}
public Brush GetFlatButtonPressedBackgroundBrush()
{
return Theme == Themes.LIGHT ? FLAT_BUTTON_BACKGROUND_PRESSED_LIGHT_BRUSH : FLAT_BUTTON_BACKGROUND_PRESSED_DARK_BRUSH;
}
public Brush GetFlatButtonDisabledTextBrush()
{
return Theme == Themes.LIGHT ? FLAT_BUTTON_DISABLEDTEXT_LIGHT_BRUSH : FLAT_BUTTON_DISABLEDTEXT_DARK_BRUSH;
}
public Brush GetCmsSelectedItemBrush()
{
return Theme == Themes.LIGHT ? CMS_BACKGROUND_HOVER_LIGHT_BRUSH : CMS_BACKGROUND_HOVER_DARK_BRUSH;
}
public Color GetApplicationBackgroundColor()
{
return Theme == Themes.LIGHT ? BACKGROUND_LIGHT : BACKGROUND_DARK;
}
//Roboto font
public Font ROBOTO_MEDIUM_12;
public Font ROBOTO_REGULAR_11;
public Font ROBOTO_MEDIUM_11;
public Font ROBOTO_MEDIUM_10;
//Other constants
public int FORM_PADDING = 14;
[DllImport("gdi32.dll")]
private static extern IntPtr AddFontMemResourceEx(IntPtr pbFont, uint cbFont, IntPtr pvd, [In] ref uint pcFonts);
private MaterialSkinManager()
{
ROBOTO_MEDIUM_12 = new Font(LoadFont(Resource1.Roboto_Medium), 12f);
ROBOTO_MEDIUM_10 = new Font(LoadFont(Resource1.Roboto_Medium), 10f);
ROBOTO_REGULAR_11 = new Font(LoadFont(Resource1.Roboto_Regular), 11f);
ROBOTO_MEDIUM_11 = new Font(LoadFont(Resource1.Roboto_Medium), 11f);
Theme = Themes.LIGHT;
ColorScheme = new ColorScheme(Primary.BlueGrey800, Primary.BlueGrey900, Primary.BlueGrey500, Accent.LightBlue200, TextShade.WHITE);
}
public static MaterialSkinManager Instance => _instance ?? (_instance = new MaterialSkinManager());
public void AddFormToManage(MaterialForm materialForm)
{
_formsToManage.Add(materialForm);
UpdateBackgrounds();
}
public void RemoveFormToManage(MaterialForm materialForm)
{
_formsToManage.Remove(materialForm);
}
private readonly PrivateFontCollection privateFontCollection = new PrivateFontCollection();
private FontFamily LoadFont(byte[] fontResource)
{
int dataLength = fontResource.Length;
IntPtr fontPtr = Marshal.AllocCoTaskMem(dataLength);
Marshal.Copy(fontResource, 0, fontPtr, dataLength);
uint cFonts = 0;
AddFontMemResourceEx(fontPtr, (uint)fontResource.Length, IntPtr.Zero, ref cFonts);
privateFontCollection.AddMemoryFont(fontPtr, dataLength);
return privateFontCollection.Families.Last();
}
private void UpdateBackgrounds()
{
var newBackColor = GetApplicationBackgroundColor();
foreach (var materialForm in _formsToManage)
{
materialForm.BackColor = newBackColor;
UpdateControl(materialForm, newBackColor);
}
}
private void UpdateToolStrip(ToolStrip toolStrip, Color newBackColor)
{
if (toolStrip == null) return;
toolStrip.BackColor = newBackColor;
foreach (ToolStripItem control in toolStrip.Items)
{
control.BackColor = newBackColor;
if (control is MaterialToolStripMenuItem && (control as MaterialToolStripMenuItem).HasDropDown)
{
//recursive call
UpdateToolStrip((control as MaterialToolStripMenuItem).DropDown, newBackColor);
}
}
}
private void UpdateControl(Control controlToUpdate, Color newBackColor)
{
if (controlToUpdate == null) return;
if (controlToUpdate.ContextMenuStrip != null)
{
UpdateToolStrip(controlToUpdate.ContextMenuStrip, newBackColor);
}
var tabControl = controlToUpdate as MaterialTabControl;
if (tabControl != null)
{
foreach (TabPage tabPage in tabControl.TabPages)
{
tabPage.BackColor = newBackColor;
}
}
if (controlToUpdate is MaterialDivider)
{
controlToUpdate.BackColor = GetDividersColor();
}
if (controlToUpdate is MaterialListView)
{
controlToUpdate.BackColor = newBackColor;
}
//recursive call
foreach (Control control in controlToUpdate.Controls)
{
UpdateControl(control, newBackColor);
}
controlToUpdate.Invalidate();
}
}
}

View File

@@ -0,0 +1,113 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace MaterialSkin.Core.Resources {
using System;
/// <summary>
/// A strongly-typed resource class, for looking up localized strings, etc.
/// </summary>
// This class was auto-generated by the StronglyTypedResourceBuilder
// class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class Resource1 {
private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal Resource1() {
}
/// <summary>
/// Returns the cached ResourceManager instance used by this class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager {
get {
if (object.ReferenceEquals(resourceMan, null)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("MaterialSkin.Core.Resources.Resource1", typeof(Resource1).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
/// <summary>
/// Overrides the current thread's CurrentUICulture property for all
/// resource lookups using this strongly typed resource class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture {
get {
return resourceCulture;
}
set {
resourceCulture = value;
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap drop_down_arrow {
get {
object obj = ResourceManager.GetObject("drop_down_arrow", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Byte[].
/// </summary>
internal static byte[] Roboto_Medium {
get {
object obj = ResourceManager.GetObject("Roboto_Medium", resourceCulture);
return ((byte[])(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Byte[].
/// </summary>
internal static byte[] Roboto_Regular {
get {
object obj = ResourceManager.GetObject("Roboto_Regular", resourceCulture);
return ((byte[])(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap round_delete_button {
get {
object obj = ResourceManager.GetObject("round_delete_button", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap rounded_add_button {
get {
object obj = ResourceManager.GetObject("rounded_add_button", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
}
}

View File

@@ -0,0 +1,136 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<data name="drop_down_arrow" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>drop-down-arrow.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="Roboto_Medium" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>roboto-medium.ttf;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="Roboto_Regular" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>roboto-regular.ttf;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="rounded_add_button" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>rounded-add-button.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="round_delete_button" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>round-delete-button.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
</root>

Binary file not shown.

After

Width:  |  Height:  |  Size: 478 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB