Hallo,
Da ich mit dem Custom-Colordialog nicht zufrieden war, habe ich mir die Grundlage für einen eigenen geschrieben, ein ColorWheel. Das ColorWheel basiert auf dem HSV Farbraum:
Der Winkel (in Grad) gibt den Hue-Wert an (0-360). Das Verhältnis der Strecke vom Kreismittelpunkt zu Farbpunkt in Hinblick auf den Radius gibt die Sättigung (Saturation an, 0-1). Value ist quasi die Abstufung mit Schwarz. Häufig wird die Value ebenfalls als Prozentzahl (0-1) dargestellt, ich wollte diese allerdings absolut bestimmbar haben.
Grundlage für das ColorWheel ist die Klasse HSVColor, die die Konvertierung der beiden Farbräume ineinander ermöglicht (RGB<->HSV):
HSVColor.vb
ColorPicker.vb
Ich wünsche euch viel Spaß damit .
Da ich mit dem Custom-Colordialog nicht zufrieden war, habe ich mir die Grundlage für einen eigenen geschrieben, ein ColorWheel. Das ColorWheel basiert auf dem HSV Farbraum:
Der Winkel (in Grad) gibt den Hue-Wert an (0-360). Das Verhältnis der Strecke vom Kreismittelpunkt zu Farbpunkt in Hinblick auf den Radius gibt die Sättigung (Saturation an, 0-1). Value ist quasi die Abstufung mit Schwarz. Häufig wird die Value ebenfalls als Prozentzahl (0-1) dargestellt, ich wollte diese allerdings absolut bestimmbar haben.
Grundlage für das ColorWheel ist die Klasse HSVColor, die die Konvertierung der beiden Farbräume ineinander ermöglicht (RGB<->HSV):
VB.NET-Quellcode
- <TypeConverter(GetType(ExpandableObjectConverter))> _
- Public Class HSVColor
- Public Property Hue As Double
- Public Property Saturation As Double
- Public Property Value As Double
- Public Sub New(ByVal hue As Double, ByVal saturation As Double, ByVal value As Double)
- _Hue = hue
- _Saturation = saturation
- _Value = value
- End Sub
- Public Sub FromARGBColor(ByVal col As Color)
- Dim maximum = max({col.R, col.G, col.B})
- Dim minimum = min({col.R, col.G, col.B})
- If maximum = minimum OrElse col.R = col.B AndAlso col.R = col.G AndAlso col.G = col.B Then
- Hue = 0
- ElseIf maximum = col.R Then
- Hue = 60 * ((col.G - col.B) / (maximum - minimum))
- ElseIf maximum = col.G Then
- Hue = 60 * (2 + (col.B - col.R) / (maximum - minimum))
- ElseIf maximum = col.B Then
- Hue = 60 * (4 + (col.R - col.G) / (maximum - minimum))
- End If
- If Hue < 0 Then Hue = Hue + 360
- If maximum = 0 OrElse (col.R = 0 AndAlso col.G = 0 AndAlso col.B = 0) Then
- Saturation = 0
- Else
- Saturation = (maximum - minimum) / maximum
- End If
- Value = maximum
- End Sub
- Public Function min(ByVal arg() As Double) As Double
- Dim lowest As Double = 255
- For Each ar As Double In arg
- If ar < lowest Then
- lowest = ar
- End If
- Next
- Return lowest
- End Function
- Public Function max(ByVal arg() As Double) As Double
- Dim highest As Double = 0
- For Each ar As Double In arg
- If ar > highest Then
- highest = ar
- End If
- Next
- Return highest
- End Function
- Public Function ToColor() As Color
- Dim hi As Integer = Convert.ToInt32(Math.Floor(Hue / 60))
- Dim f As Double = Hue / 60 - hi
- Dim p As Integer = Convert.ToInt32(Value * (1 - Saturation))
- Dim q As Integer = Convert.ToInt32(Value * (1 - Saturation * f))
- Dim t As Integer = Convert.ToInt32(Value * (1 - Saturation * (1 - f)))
- Dim val As Integer = Convert.ToInt32(Value)
- Select Case hi
- Case 0
- Return Color.FromArgb(val, t, p)
- Case 1
- Return Color.FromArgb(q, val, p)
- Case 2
- Return Color.FromArgb(p, val, t)
- Case 3
- Return Color.FromArgb(p, q, val)
- Case 4
- Return Color.FromArgb(t, p, val)
- Case 5
- Return Color.FromArgb(val, p, q)
- Case 6
- Return Color.FromArgb(val, t, p)
- End Select
- End Function
- Public Overrides Function ToString() As String
- Return String.Format("HSVColor [H={0}, S={1}, V={2}]", {Hue, Saturation, Value})
- End Function
- End Class
- Public Class HSVEventArgs
- Inherits EventArgs
- Private _HSVColor As HSVColor
- Public ReadOnly Property HSVColor As HSVColor
- Get
- Return _HSVColor
- End Get
- End Property
- Public Sub New(col As HSVColor)
- _HSVColor = col
- End Sub
- End Class
VB.NET-Quellcode
- Imports System.Drawing
- Imports System.ComponentModel
- Imports System.Windows.Forms
- Imports System.Drawing.Drawing2D
- <DefaultEvent("ColorChanged")>
- <ToolboxBitmap(GetType(ColorDialog))>
- Public Class Colorpicker
- Inherits UserControl
- Protected Overrides ReadOnly Property CreateParams() As CreateParams
- Get
- Dim cp As CreateParams = MyBase.CreateParams
- cp.ExStyle = cp.ExStyle Or &H20
- Return cp
- End Get
- End Property
- Public Event ColorChanged As EventHandler(Of HSVEventArgs)
- Sub New()
- MyBase.SetStyle(ControlStyles.SupportsTransparentBackColor, True)
- MyBase.SetStyle(ControlStyles.OptimizedDoubleBuffer, True)
- End Sub
- 'das rectangle das den kreis beinhaltet
- Dim ellipserectangle As New Rectangle(2, 2, 200, 200)
- 'das rectangle das den valueregler beinhaltet
- Dim valuerectangle As New Rectangle(250, 2, 20, 200)
- 'Mittelpunkt des Wheels
- Dim middlepoint As PointF = New PointF(Convert.ToInt32(ellipserectangle.X + ellipserectangle.Width / 2), Convert.ToInt32(ellipserectangle.Y + ellipserectangle.Height / 2))
- 'Momentaner Cursor Standort auf den Reglern
- Dim ellipsept As PointF = middlepoint
- Dim rectanglept As New PointF()
- 'das Makierende Rectangle auf den Reglern
- Dim ellipsepointerrectangle As New Rectangle()
- Dim rectanglepointrectangle As New Rectangle()
- Private _hsvcolor As New HSVColor(0, 0, 255)
- Public Property HSVColor As HSVColor
- Get
- Return _hsvcolor
- End Get
- Set(value As HSVColor)
- _hsvcolor = value
- Me.Invalidate(New Rectangle(Convert.ToInt32(ellipsept.X - 3), Convert.ToInt32(ellipsept.Y - 3), 7, 7))
- If HSVColor.Saturation > 0 Then
- Dim angle As Double = value.Hue * (Math.PI / 180)
- Dim r As Double = ellipserectangle.Width / 2 * HSVColor.Saturation
- Dim xkoor As Double = Math.Cos(angle) * r + middlepoint.X
- Dim ykoor As Double = Math.Sin(angle) * r + middlepoint.Y
- ellipsept = New Point(Convert.ToInt32(xkoor), Convert.ToInt32(ykoor))
- Else
- ellipsept = middlepoint
- End If
- ellipsepointerrectangle = New Rectangle(Convert.ToInt32(ellipsept.X - 3), Convert.ToInt32(ellipsept.Y - 3), 6, 6)
- Me.Invalidate(New Rectangle(Convert.ToInt32(ellipsept.X - 3), Convert.ToInt32(ellipsept.Y - 3), 7, 7))
- Dim mouseheight As Integer = Convert.ToInt32(((-1 * HSVColor.Value + 255) / 255) * valuerectangle.Height + valuerectangle.Y)
- Me.Invalidate(New Rectangle(Convert.ToInt32(rectanglept.X - 3), Convert.ToInt32(rectanglept.Y - 3), 7, 7))
- rectanglept = New Point(Convert.ToInt32(valuerectangle.X + valuerectangle.Width / 2), mouseheight)
- rectanglepointrectangle = New Rectangle(Convert.ToInt32(rectanglept.X - 3), Convert.ToInt32(rectanglept.Y - 3), 6, 6)
- Me.Invalidate(valuerectangle)
- RaiseEvent ColorChanged(Me, New HSVEventArgs(Me._hsvcolor))
- End Set
- End Property
- Protected Overrides Sub OnPaint(e As PaintEventArgs)
- MyBase.OnPaint(e)
- With e.Graphics
- .SmoothingMode = Drawing2D.SmoothingMode.HighSpeed
- .CompositingQuality = CompositingQuality.HighQuality
- .DrawEllipse(Pens.Gray, ellipserectangle)
- 'Hier das eigentliche Wheel mit Farbe je nach Winkel
- Dim hsv As New HSVColor(0, 1, 255)
- Dim angle As Double
- Dim outherpoint As PointF
- For u = 0 To 360 Step 1
- hsv.Hue = u
- angle = Math.PI / 180 * u
- outherpoint = New PointF(Convert.ToSingle(Math.Cos(angle) * (ellipserectangle.Width / 2) + middlepoint.X), Convert.ToSingle(Math.Sin(angle) * (ellipserectangle.Width / 2) + middlepoint.Y))
- Using lbg As New LinearGradientBrush(middlepoint, outherpoint, Color.White, hsv.ToColor)
- Dim pt As New GraphicsPath
- pt.AddPie(ellipserectangle, u, 1.5)
- .FillPath(lbg, pt)
- End Using
- Next
- 'Schwarzen Punkt in der Mitte entfernen
- .FillRectangle(Brushes.White, New Rectangle(Convert.ToInt32(middlepoint.X - 1), Convert.ToInt32(middlepoint.Y - 1), 2, 2))
- 'Hier wird der Regler für Value gezeichnet
- hsv.Hue = HSVColor.Hue
- hsv.Saturation = HSVColor.Saturation
- Dim uppercolor = hsv.ToColor
- hsv.Value = 0
- Using lgb As New LinearGradientBrush(valuerectangle, uppercolor, hsv.ToColor, LinearGradientMode.Vertical)
- .FillRectangle(lgb, valuerectangle)
- End Using
- .DrawRectangle(Pens.Black, ellipsepointerrectangle)
- .DrawRectangle(Pens.Black, rectanglepointrectangle)
- End With
- End Sub
- Private _Color As Color
- Public Property [Color] As Color
- Get
- _Color = HSVColor.ToColor
- Return _Color
- End Get
- Set(value As Color)
- _Color = value
- Dim hsv As New HSVColor(0, 0, 0)
- hsv.FromARGBColor(value)
- HSVColor = New HSVColor(hsv.Hue, hsv.Saturation, hsv.Value)
- End Set
- End Property
- Private Sub Colorpicker_MouseClick(sender As Object, e As MouseEventArgs) Handles Me.MouseClick
- Dim distance As Double = Math.Sqrt(Math.Pow(middlepoint.X - e.X, 2) + Math.Pow(middlepoint.Y - e.Y, 2))
- Dim radius As Double = ellipserectangle.Width / 2
- If radius > distance Then
- Dim Saturation As Double = distance / radius
- Dim angle = Math.Atan2(e.Y - middlepoint.Y, e.X - middlepoint.X) / Math.PI * 180
- If angle <= 0 Then angle = angle + 2 * 180
- _hsvcolor.Saturation = Saturation
- _hsvcolor.Hue = angle
- _hsvcolor.Value = 255
- HSVColor = New HSVColor(angle, Saturation, 255)
- ElseIf valuerectangle.Contains(e.Location) Then
- Dim val As Double = 255 - 255 * ((e.Y - valuerectangle.Y) / valuerectangle.Height)
- HSVColor = New HSVColor(_hsvcolor.Hue, _hsvcolor.Saturation, val)
- End If
- End Sub
- End Class
Ich wünsche euch viel Spaß damit .
faxe1008
Dieser Beitrag wurde bereits 6 mal editiert, zuletzt von „faxe1008“ ()