ShareX/ShareX.HelpersLib/Colors/ColorUserControl.cs

413 lines
14 KiB
C#
Raw Normal View History

2013-11-03 23:53:49 +13:00
#region License Information (GPL v3)
/*
ShareX - A program that allows you to take screenshots and share any file type
2024-01-03 12:57:14 +13:00
Copyright (c) 2007-2024 ShareX Team
2013-11-03 23:53:49 +13:00
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
Optionally you can also view the license at <http://www.gnu.org/licenses/>.
*/
#endregion License Information (GPL v3)
2014-12-11 09:25:20 +13:00
using ShareX.HelpersLib.Properties;
2013-11-03 23:53:49 +13:00
using System;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Imaging;
using System.Windows.Forms;
2014-12-11 09:25:20 +13:00
namespace ShareX.HelpersLib
2013-11-03 23:53:49 +13:00
{
public abstract class ColorUserControl : UserControl
{
public event ColorEventHandler ColorChanged;
2016-12-01 02:01:12 +13:00
public bool CrosshairVisible { get; set; } = true;
2013-11-03 23:53:49 +13:00
public MyColor SelectedColor
{
get
{
return selectedColor;
}
set
{
selectedColor = value;
if (this is ColorBox)
{
SetBoxMarker();
}
else
{
SetSliderMarker();
}
Invalidate();
2013-11-03 23:53:49 +13:00
}
}
public DrawStyle DrawStyle
{
get
{
return drawStyle;
}
set
{
drawStyle = value;
if (this is ColorBox)
{
SetBoxMarker();
}
else
{
SetSliderMarker();
}
Invalidate();
2013-11-03 23:53:49 +13:00
}
}
2016-12-01 02:01:12 +13:00
protected Bitmap bmp;
protected int clientWidth, clientHeight;
protected DrawStyle drawStyle;
protected MyColor selectedColor;
protected bool mouseDown;
protected Point lastPos;
protected Timer mouseMoveTimer;
2013-11-03 23:53:49 +13:00
#region Component Designer generated code
private IContainer components = null;
protected virtual void Initialize()
{
SuspendLayout();
DoubleBuffered = true;
2016-12-01 02:01:12 +13:00
clientWidth = ClientRectangle.Width;
clientHeight = ClientRectangle.Height;
bmp = new Bitmap(clientWidth, clientHeight, PixelFormat.Format32bppArgb);
2013-11-03 23:53:49 +13:00
SelectedColor = Color.Red;
DrawStyle = DrawStyle.Hue;
mouseMoveTimer = new Timer();
mouseMoveTimer.Interval = 10;
mouseMoveTimer.Tick += new EventHandler(MouseMoveTimer_Tick);
ClientSizeChanged += new EventHandler(EventClientSizeChanged);
MouseDown += new MouseEventHandler(EventMouseDown);
MouseEnter += new EventHandler(EventMouseEnter);
MouseUp += new MouseEventHandler(EventMouseUp);
Paint += new PaintEventHandler(EventPaint);
ResumeLayout(false);
}
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
if (bmp != null) bmp.Dispose();
}
base.Dispose(disposing);
}
#endregion Component Designer generated code
#region Events
private void EventClientSizeChanged(object sender, EventArgs e)
{
2016-12-01 02:01:12 +13:00
clientWidth = ClientRectangle.Width;
clientHeight = ClientRectangle.Height;
2013-11-03 23:53:49 +13:00
if (bmp != null) bmp.Dispose();
2016-12-01 02:01:12 +13:00
bmp = new Bitmap(clientWidth, clientHeight, PixelFormat.Format32bppArgb);
2013-11-03 23:53:49 +13:00
DrawColors();
}
private void EventMouseDown(object sender, MouseEventArgs e)
{
2016-12-01 02:01:12 +13:00
CrosshairVisible = true;
2013-11-03 23:53:49 +13:00
mouseDown = true;
mouseMoveTimer.Start();
}
private void EventMouseEnter(object sender, EventArgs e)
{
if (this is ColorBox)
{
2016-07-04 22:27:31 +12:00
Cursor = Helpers.CreateCursor(Resources.Crosshair);
2013-11-03 23:53:49 +13:00
}
}
private void EventMouseUp(object sender, MouseEventArgs e)
{
mouseDown = false;
mouseMoveTimer.Stop();
}
private void EventPaint(object sender, PaintEventArgs e)
{
Graphics g = e.Graphics;
if (!mouseDown)
{
if (SelectedColor.IsTransparent)
{
if (bmp != null) bmp.Dispose();
2020-03-22 10:16:55 +13:00
bmp = ImageHelpers.DrawCheckers(clientWidth, clientHeight);
2013-11-03 23:53:49 +13:00
}
DrawColors();
}
g.DrawImage(bmp, ClientRectangle);
2016-12-01 02:01:12 +13:00
if (CrosshairVisible)
2013-11-03 23:53:49 +13:00
{
DrawCrosshair(g);
}
}
private void MouseMoveTimer_Tick(object sender, EventArgs e)
{
Point mousePosition = GetPoint(PointToClient(MousePosition));
if (mouseDown && lastPos != mousePosition)
{
GetPointColor(mousePosition);
OnColorChanged();
Refresh();
}
}
#endregion Events
#region Protected Methods
protected void OnColorChanged()
{
2021-06-10 10:14:01 +12:00
ColorChanged?.Invoke(this, new ColorEventArgs(SelectedColor, DrawStyle));
2013-11-03 23:53:49 +13:00
}
protected void DrawColors()
{
switch (DrawStyle)
{
case DrawStyle.Hue:
DrawHue();
break;
case DrawStyle.Saturation:
DrawSaturation();
break;
case DrawStyle.Brightness:
DrawBrightness();
break;
case DrawStyle.Red:
DrawRed();
break;
case DrawStyle.Green:
DrawGreen();
break;
case DrawStyle.Blue:
DrawBlue();
break;
}
}
protected void SetBoxMarker()
{
switch (DrawStyle)
{
case DrawStyle.Hue:
2016-12-01 02:01:12 +13:00
lastPos.X = Round((clientWidth - 1) * SelectedColor.HSB.Saturation);
lastPos.Y = Round((clientHeight - 1) * (1.0 - SelectedColor.HSB.Brightness));
2013-11-03 23:53:49 +13:00
break;
case DrawStyle.Saturation:
2016-12-01 02:01:12 +13:00
lastPos.X = Round((clientWidth - 1) * SelectedColor.HSB.Hue);
lastPos.Y = Round((clientHeight - 1) * (1.0 - SelectedColor.HSB.Brightness));
2013-11-03 23:53:49 +13:00
break;
case DrawStyle.Brightness:
2016-12-01 02:01:12 +13:00
lastPos.X = Round((clientWidth - 1) * SelectedColor.HSB.Hue);
lastPos.Y = Round((clientHeight - 1) * (1.0 - SelectedColor.HSB.Saturation));
2013-11-03 23:53:49 +13:00
break;
case DrawStyle.Red:
2016-12-01 02:01:12 +13:00
lastPos.X = Round((clientWidth - 1) * (double)SelectedColor.RGBA.Blue / 255);
lastPos.Y = Round((clientHeight - 1) * (1.0 - ((double)SelectedColor.RGBA.Green / 255)));
2013-11-03 23:53:49 +13:00
break;
case DrawStyle.Green:
2016-12-01 02:01:12 +13:00
lastPos.X = Round((clientWidth - 1) * (double)SelectedColor.RGBA.Blue / 255);
lastPos.Y = Round((clientHeight - 1) * (1.0 - ((double)SelectedColor.RGBA.Red / 255)));
2013-11-03 23:53:49 +13:00
break;
case DrawStyle.Blue:
2016-12-01 02:01:12 +13:00
lastPos.X = Round((clientWidth - 1) * (double)SelectedColor.RGBA.Red / 255);
lastPos.Y = Round((clientHeight - 1) * (1.0 - ((double)SelectedColor.RGBA.Green / 255)));
2013-11-03 23:53:49 +13:00
break;
}
lastPos = GetPoint(lastPos);
}
protected void GetBoxColor()
{
switch (DrawStyle)
{
case DrawStyle.Hue:
2016-12-01 02:01:12 +13:00
selectedColor.HSB.Saturation = (double)lastPos.X / (clientWidth - 1);
selectedColor.HSB.Brightness = 1.0 - ((double)lastPos.Y / (clientHeight - 1));
2013-11-03 23:53:49 +13:00
selectedColor.HSBUpdate();
break;
case DrawStyle.Saturation:
2016-12-01 02:01:12 +13:00
selectedColor.HSB.Hue = (double)lastPos.X / (clientWidth - 1);
selectedColor.HSB.Brightness = 1.0 - ((double)lastPos.Y / (clientHeight - 1));
2013-11-03 23:53:49 +13:00
selectedColor.HSBUpdate();
break;
case DrawStyle.Brightness:
2016-12-01 02:01:12 +13:00
selectedColor.HSB.Hue = (double)lastPos.X / (clientWidth - 1);
selectedColor.HSB.Saturation = 1.0 - ((double)lastPos.Y / (clientHeight - 1));
2013-11-03 23:53:49 +13:00
selectedColor.HSBUpdate();
break;
case DrawStyle.Red:
2016-12-01 02:01:12 +13:00
selectedColor.RGBA.Blue = Round(255 * (double)lastPos.X / (clientWidth - 1));
selectedColor.RGBA.Green = Round(255 * (1.0 - ((double)lastPos.Y / (clientHeight - 1))));
2013-11-03 23:53:49 +13:00
selectedColor.RGBAUpdate();
break;
case DrawStyle.Green:
2016-12-01 02:01:12 +13:00
selectedColor.RGBA.Blue = Round(255 * (double)lastPos.X / (clientWidth - 1));
selectedColor.RGBA.Red = Round(255 * (1.0 - ((double)lastPos.Y / (clientHeight - 1))));
2013-11-03 23:53:49 +13:00
selectedColor.RGBAUpdate();
break;
case DrawStyle.Blue:
2016-12-01 02:01:12 +13:00
selectedColor.RGBA.Red = Round(255 * (double)lastPos.X / (clientWidth - 1));
selectedColor.RGBA.Green = Round(255 * (1.0 - ((double)lastPos.Y / (clientHeight - 1))));
2013-11-03 23:53:49 +13:00
selectedColor.RGBAUpdate();
break;
}
}
protected void SetSliderMarker()
{
switch (DrawStyle)
{
case DrawStyle.Hue:
2016-12-01 02:01:12 +13:00
lastPos.Y = (clientHeight - 1) - Round((clientHeight - 1) * SelectedColor.HSB.Hue);
2013-11-03 23:53:49 +13:00
break;
case DrawStyle.Saturation:
2016-12-01 02:01:12 +13:00
lastPos.Y = (clientHeight - 1) - Round((clientHeight - 1) * SelectedColor.HSB.Saturation);
2013-11-03 23:53:49 +13:00
break;
case DrawStyle.Brightness:
2016-12-01 02:01:12 +13:00
lastPos.Y = (clientHeight - 1) - Round((clientHeight - 1) * SelectedColor.HSB.Brightness);
2013-11-03 23:53:49 +13:00
break;
case DrawStyle.Red:
2016-12-01 02:01:12 +13:00
lastPos.Y = (clientHeight - 1) - Round((clientHeight - 1) * (double)SelectedColor.RGBA.Red / 255);
2013-11-03 23:53:49 +13:00
break;
case DrawStyle.Green:
2016-12-01 02:01:12 +13:00
lastPos.Y = (clientHeight - 1) - Round((clientHeight - 1) * (double)SelectedColor.RGBA.Green / 255);
2013-11-03 23:53:49 +13:00
break;
case DrawStyle.Blue:
2016-12-01 02:01:12 +13:00
lastPos.Y = (clientHeight - 1) - Round((clientHeight - 1) * (double)SelectedColor.RGBA.Blue / 255);
2013-11-03 23:53:49 +13:00
break;
}
lastPos = GetPoint(lastPos);
}
protected void GetSliderColor()
{
switch (DrawStyle)
{
case DrawStyle.Hue:
selectedColor.HSB.Hue = 1.0 - ((double)lastPos.Y / (clientHeight - 1));
2013-11-03 23:53:49 +13:00
selectedColor.HSBUpdate();
break;
case DrawStyle.Saturation:
selectedColor.HSB.Saturation = 1.0 - ((double)lastPos.Y / (clientHeight - 1));
2013-11-03 23:53:49 +13:00
selectedColor.HSBUpdate();
break;
case DrawStyle.Brightness:
selectedColor.HSB.Brightness = 1.0 - ((double)lastPos.Y / (clientHeight - 1));
2013-11-03 23:53:49 +13:00
selectedColor.HSBUpdate();
break;
case DrawStyle.Red:
2016-12-01 02:01:12 +13:00
selectedColor.RGBA.Red = 255 - Round(255 * (double)lastPos.Y / (clientHeight - 1));
2013-11-03 23:53:49 +13:00
selectedColor.RGBAUpdate();
break;
case DrawStyle.Green:
2016-12-01 02:01:12 +13:00
selectedColor.RGBA.Green = 255 - Round(255 * (double)lastPos.Y / (clientHeight - 1));
2013-11-03 23:53:49 +13:00
selectedColor.RGBAUpdate();
break;
case DrawStyle.Blue:
2016-12-01 02:01:12 +13:00
selectedColor.RGBA.Blue = 255 - Round(255 * (double)lastPos.Y / (clientHeight - 1));
2013-11-03 23:53:49 +13:00
selectedColor.RGBAUpdate();
break;
}
}
protected abstract void DrawCrosshair(Graphics g);
protected abstract void DrawHue();
protected abstract void DrawSaturation();
protected abstract void DrawBrightness();
protected abstract void DrawRed();
protected abstract void DrawGreen();
protected abstract void DrawBlue();
#endregion Protected Methods
#region Protected Helpers
protected void GetPointColor(Point point)
{
lastPos = point;
if (this is ColorBox)
{
GetBoxColor();
}
else
{
GetSliderColor();
}
}
protected Point GetPoint(Point point)
{
2019-05-24 07:59:16 +12:00
return new Point(point.X.Clamp(0, clientWidth - 1), point.Y.Clamp(0, clientHeight - 1));
2013-11-03 23:53:49 +13:00
}
protected int Round(double val)
{
int ret_val = (int)val;
int temp = (int)(val * 100);
if ((temp % 100) >= 50)
ret_val += 1;
return ret_val;
}
#endregion Protected Helpers
}
}