C# 高仿腾讯QQ (QQ皮肤颜色滑动调色器)

       《QQ皮肤颜色滑动调色器》这个控件去年时就发到群共享了,但一直没发到博客上去。主要呢就是一个是没时间去写博客,还有就是程序有很多BUG还没完善,比如拖动下面滑动条时不是十分的顺畅,占用CPU资源也很等,但在这里还是发出来,大家自己去改善吧!


 

       这个控件刚开始做时原本是打算通过截取一张QQ滑动调色器的图片做为控件调色板背景颜色的,但后来,无意间在网上看到一个老外写的基于HSL色调(H)的调色板程序,而QQ滑动调色器改变颜色的方法是基于(HSL)饱和度(S)(HSL:HSL色彩模式是工业界的一种颜色标准,是通过对色调(H)、饱和度(S)、亮度(L)三个颜色通道的变化以及它们相互之间的叠加来得到各式各样的颜色的,HSL即是代表色调,饱和度,亮度三个通道的颜色,而饱和度(S)懂PS的人应该很清楚,我也是直接截个图放到PS里,再改变他的饱和度才知道QQ是基于饱和度)来变换颜色的,所以我变偿试着改了改他的程序,让他基于饱和度的调节而变换颜色达到QQ的效果。

      这是在PS里的颜色变换图:


       控件最主要就是RGB与HSL颜色通道之间的换算,至于算法、原理,我想大家去问问百度大叔、Google大妈理解会来得更容易些,在这里我就不说了,让我说我也说不好,呵呵。

       颜色控件由另两个控件组成,一个是 颜色显示区,我单独做成了一个控件。另一个是滑动模块,也是单独做成了一个控件
    
       还是直接贴源,有兴趣的大家自己研究:

ColorAreaAndSliderUserControl.cs完整控件

 

1 //作者:阿龙(Along)
2  //QQ号:646494711
3  //QQ群1:57218890
4  //QQ群2:57219423
5  //网站:http://www.8timer.com
6  //博客:http://www.cnblogs.com/Along729/
7  //声明:未经作者许可,任何人不得发布出售该源码,请尊重别人的劳动成果,谢谢大家支持
8  using System;
9  using System.Collections.Generic;
10  using System.ComponentModel;
11  using System.Drawing;
12  using System.Data;
13  using System.Linq;
14  using System.Text;
15  using System.Windows.Forms;
16  using ColorCustomize.Colors;
17
18  namespace ColorCustomize
19 {
20 public partial class ColorAreaAndSliderUserControl : UserControl
21 {
22 double h, l, s;
23 public ColorAreaAndSliderUserControl()
24 {
25 InitializeComponent();
26 }
27
28 private void colorAreaUserControl1_HueSaturationChanged(object sender, EventArgs e)
29 {
30
31 colorAreaUserControl.GetHueSaturation(out h,out s, out l);
32 colorSliderUserControl.SetHueSaturation(h, s, l);
33
34 }
35
36 private void colorAreaUserControl1_ValueChangedByUser(object sender, EventArgs e)
37 {
38 notifyColorChanged();
39 notifyValueChangedByUser();
40 }
41
42 private void colorSliderUserControl_ValueChanged(object sender, EventArgs e)
43 {
44 double s;
45 colorSliderUserControl.GetHueSaturation(out s);
46 colorAreaUserControl.SetHueSaturation(s);
47
48 }
49
50 private void colorSliderUserControl_ValueChangedByUser(object sender, EventArgs e)
51 {
52 notifyColorChanged();
53 notifyValueChangedByUser();
54
55 }
56
57 /// <summary>
58 /// 当用户发生改变颜色.
59 /// </summary>
60   public event EventHandler ColorChanged;
61
62 /// <summary>
63 /// 值时发生了改变.
64 /// </summary>
65 public event EventHandler ValueChangedByUser;
66
67 private void notifyColorChanged()
68 {
69 if (ColorChanged != null)
70 {
71 ColorChanged(this, EventArgs.Empty);
72 }
73 }
74
75 private void notifyValueChangedByUser()
76 {
77 if (ValueChangedByUser != null)
78 {
79 ValueChangedByUser(this, EventArgs.Empty);
80 }
81 }
82
83 public void setColor(Color color)
84 {
85 RgbColor rgb = ColorConverting.ColorToRgb(color);
86 HslColor hsl = ColorConverting.RgbToHsl(rgb);
87 colorAreaUserControl.SetColor((double)hsl.Hue,(double)hsl.Saturation,(double)hsl.Light);
88 colorSliderUserControl.SetColorSaturation((double)hsl.Saturation);
89 }
90 public void GetColor(out Color color)
91 {
92 color = ColorConverting.HslToRgb(new HslColor(h,s,l)).ToColor();
93 }
94 }
95 }

ColorAreaUserControl.cs颜色显示区控件

1 //作者:阿龙(Along)
2 //QQ号:646494711
3 //QQ群1:57218890
4 //QQ群2:57219423
5 //网站:http://www.8timer.com
6 //博客:http://www.cnblogs.com/Along729/
7 //声明:未经作者许可,任何人不得发布出售该源码,请尊重别人的劳动成果,谢谢大家支持
8 using System;
9 using System.Collections.Generic;
10 using System.ComponentModel;
11 using System.Drawing;
12 using System.Drawing.Drawing2D;
13 using System.Data;
14 using System.Linq;
15 using System.Text;
16 using System.Windows.Forms;
17 using ColorCustomize.Colors;
18 using System.Threading;
19
20 namespace ColorCustomize
21 {
22 public partial class ColorAreaUserControl : UserControl
23 {
24 private double _h;
25 private double _l;
26 private static double _s=100;
27 private Bitmap _colorBitmap;
28
29 public ColorAreaUserControl()
30 {
31 InitializeComponent();
32 SetStyle(ControlStyles.UserPaint |
33 ControlStyles.DoubleBuffer |
34 ControlStyles.ResizeRedraw|
35 ControlStyles.Selectable |
36 ControlStyles.AllPaintingInWmPaint,
37 true);
38 }
39
40 //public void SetHueSaturation(double h, double l)
41 //{
42 // _h = h;
43 // _l = l;
44 // Invalidate();
45
46 // // notifyHueSaturationChanged();
47 //}
48
49
50 public void SetHueSaturation(double s)
51 {
52 _s = s;
53 Calculate();
54 //ThreadStart threadStart = new ThreadStart(Calculate);
55 //Thread thread = new Thread(threadStart);
56 //thread.Start();
57
58 drawCaret();
59 notifyHueSaturationChanged();
60 }
61 public void Calculate()
62 {
63 _colorBitmap = drawColorBitmap();
64 }
65
66
67
68 public void SetColor(double h,double s,double l)
69 {
70 _h = h;
71 _l = l;
72 _s = s;
73 _colorBitmap = drawColorBitmap();
74 drawCaret();
75 // notifyValueChangedByUser();
76 notifyHueSaturationChanged(); ;
77 }
78
79 public void GetHueSaturation(out double h,out double s, out double l)
80 {
81 h = _h;
82 l = _l;
83 s = _s;
84 }
85
86
87 /// <summary>
88 /// Occurs when the user changed the hue and/or saturation.
89 /// 当用户发生改变色调和/或饱和度
90 /// </summary>
91 public event EventHandler HueSaturationChanged;
92
93 /// <summary>
94 /// Occurs when a value has been changed.
95 /// 值更改时发生事件
96 /// </summary>
97 public event EventHandler ValueChangedByUser;
98
99 private void notifyHueSaturationChanged()
100 {
101 if (HueSaturationChanged != null)
102 {
103 HueSaturationChanged(this, EventArgs.Empty);
104 }
105 }
106
107 private void notifyValueChangedByUser()
108 {
109 if (ValueChangedByUser != null)
110 {
111 ValueChangedByUser(this, EventArgs.Empty);
112 }
113 }
114
115 /// <summary>
116 /// 重绘控件
117 /// </summary>
118 /// <param name="e"></param>
119 protected override void OnPaint(PaintEventArgs e)
120 {
121 base.OnPaint(e);
122 if (_colorBitmap == null)
123 {
124 _colorBitmap = drawColorBitmap();
125 }
126 double facXBmpToScreen = (double)_colorBitmap.Width / ClientSize.Width;
127 double facYBmpToScreen = (double)_colorBitmap.Height / ClientSize.Height;
128
129 var sourceRect = new Rectangle(
130 (int)(facXBmpToScreen * ClientRectangle.Left),
131 (int)(facYBmpToScreen * ClientRectangle.Top),
132 (int)(facXBmpToScreen * ClientRectangle.Width),
133 (int)(facYBmpToScreen * ClientRectangle.Height));
134 //e.Graphics.SmoothingMode = SmoothingMode.HighQuality;
135 e.Graphics.InterpolationMode = InterpolationMode.NearestNeighbor;
136 e.Graphics.DrawImage(
137 _colorBitmap,
138 ClientRectangle,
139 sourceRect,
140 GraphicsUnit.Pixel);
141 drawCaret(e.Graphics);
142 }
143
144 /// <summary>
145 /// 绘制位图的颜色
146 /// </summary>
147 /// <returns></returns>
148 private static Bitmap drawColorBitmap()
149 {
150 const int width = 360;
151 const int height = 100;
152
153 var bmp = new Bitmap(width, height);
154
155 for (int y = 0; y < height; ++y)
156 {
157 for (int x = 0; x < width; ++x)
158 {
159 double h = x;
160 double s = _s;//饱和度
161 double l = 100 - y;
162
163 Color color = new HslColor(h, s, l).ToColor();
164
165 bmp.SetPixel(x, y, color);
166 }
167 }
168
169 return bmp;
170 }
171
172 /// <summary>
173 /// 绘制移动圆点
174 /// </summary>
175 /// <param name="g">The g.</param>
176 private void drawCaret(
177 Graphics g)
178 {
179
180 Point p;
181 translateHueSaturationToCaretPosition(out p, _h, _l);
182 g.DrawImage(global::ColorCustomize.Properties.Resources.colorslider_dragbackground, new Rectangle(new Point(p.X-6,p.Y-6),new Size(12,12)));
183 }
184
185 private void drawCaret()
186 {
187 Invalidate();
188 }
189
190 /// <summary>
191 /// 返回指定的区域内,移动圆点的位置
192 /// </summary>
193 /// <param name="caretPosition"></param>
194 /// <param name="h"></param>
195 /// <param name="s"></param>
196 private void translateHueSaturationToCaretPosition( out Point caretPosition, double h, double l)
197 {
198 double facXBmpToScreen = 360.0 / ClientSize.Width;
199 double facYBmpToScreen = 100.0 / ClientSize.Height;
200
201 h = Math.Max(0.0, h);
202 h = Math.Min(360.0, h);
203 l = Math.Max(0.0, l);
204 l = Math.Min(100.0, l);
205
206 double pX = (h / facXBmpToScreen);
207 double pY = (l / facYBmpToScreen);
208
209 pX = Math.Max(0, pX);
210 pX = Math.Min(ClientSize.Width - 1, pX);
211 pY = Math.Max(0, pY);
212 pY = Math.Min(ClientSize.Height - 1, pY);
213
214 pY = ClientSize.Height - pY;
215
216 caretPosition = new Point((int)pX, (int)pY);
217 }
218
219
220 /// <summary>
221 ///
222 /// </summary>
223 /// <param name="caretPosition"></param>
224 /// <param name="h"></param>
225 /// <param name="s"></param>
226 private void translateCaretPositionToHueSaturation( Point caretPosition,out double h, out double l)
227 {
228 double facXBmpToScreen = 360.0 / ClientSize.Width;
229 double facYBmpToScreen = 100.0 / ClientSize.Height;
230
231 Point p = caretPosition;
232
233 p.X = Math.Max(0, p.X);
234 p.X = Math.Min(ClientSize.Width - 1, p.X);
235 p.Y = Math.Max(0, p.Y);
236 p.Y = Math.Min(ClientSize.Height - 1, p.Y);
237
238 p.Y = ClientSize.Height - p.Y;
239
240 h = (p.X * facXBmpToScreen);
241 l = (p.Y * facYBmpToScreen);
242
243 h = Math.Max(0.0, h);
244 h = Math.Min(360.0, h);
245 l = Math.Max(0.0, l);
246 l = Math.Min(100.0, l);
247 }
248
249 private void ColorAreaUserControl_MouseMove(object sender, MouseEventArgs e)
250 {
251 if (e.Button == MouseButtons.Left)
252 {
253 translateCaretPositionToHueSaturation(e.Location, out _h, out _l);
254 drawCaret();
255
256 notifyValueChangedByUser();
257 notifyHueSaturationChanged();
258 }
259 }
260
261 private void ColorAreaUserControl_MouseClick(object sender, MouseEventArgs e)
262 {
263 if (e.Button == MouseButtons.Left)
264 {
265 translateCaretPositionToHueSaturation(e.Location, out _h, out _l);
266 drawCaret();
267
268 notifyValueChangedByUser();
269 notifyHueSaturationChanged();
270 }
271 }
272
273 private void ColorAreaUserControl_MouseDown(object sender, MouseEventArgs e)
274 {
275
276 if ( e.Button == MouseButtons.Left )
277 {
278 translateCaretPositionToHueSaturation( e.Location, out _h, out _l );
279 drawCaret();
280
281 notifyValueChangedByUser();
282 notifyHueSaturationChanged();
283 //MessageBox.Show(_arvlue.ToString());
284 }
285 }
286
287 private void ColorAreaUserControl_MouseLeave(object sender, EventArgs e)
288 {
289 drawCaret();
290 }
291
292 }
293 }

 ColorSliderUserControl.cs滑动模块控件

1 //作者:阿龙(Along)
2  //QQ号:646494711
3  //QQ群1:57218890
4  //QQ群2:57219423
5  //网站:http://www.8timer.com
6 //博客:http://www.cnblogs.com/Along729/
7 //声明:未经作者许可,任何人不得发布出售该源码,请尊重别人的劳动成果,谢谢大家支持
8 using System;
9 using System.Collections.Generic;
10 using System.ComponentModel;
11 using System.Drawing;
12 using System.Data;
13 using System.Linq;
14 using System.Text;
15 using System.Windows.Forms;
16 using ColorCustomize.Colors;
17 using System.Drawing.Drawing2D;
18
19 namespace ColorCustomize
20 {
21 public partial class ColorSliderUserControl : UserControl
22 {
23 private Bitmap _colorBitmap;
24 private double _h;
25 private double _l;
26 public ColorSliderUserControl()
27 {
28 InitializeComponent();
29 SetStyle(ControlStyles.UserPaint |
30 ControlStyles.DoubleBuffer |
31 ControlStyles.ResizeRedraw |
32 ControlStyles.Selectable |
33 ControlStyles.AllPaintingInWmPaint,
34 true);
35 }
36
37 public void SetHueSaturation(double h, double s,double l)
38 {
39 _h = h;
40 _l = l;
41 _colorBitmap = drawColorBitmap();
42 Invalidate();
43
44 // notifyValueChanged();
45 }
46
47 public void SetColorSaturation(double s)
48 {
49 arrowControl.Location = new Point((100 - (int)s)/100 * this.Width - 6,-1);
50 _colorBitmap = drawColorBitmap();
51 Invalidate();
52
53 // notifyValueChanged();
54 }
55
56 public void GetHueSaturation(out double s)
57 {
58 s =100.0-(double)(arrowControl.Location.X + 6) / (double)this.Width * 100;
59 }
60
61 /// <summary>
62 /// Occurs when a value has been changed.
63 /// 发生在一个值已更改
64 /// </summary>
65 public event EventHandler ValueChangedByUser;
66
67 /// <summary>
68 /// Occurs when a value has been changed.
69 /// </summary>
70 public event EventHandler ValueChanged;
71
72 private void NotifyValueChangedByUser()
73 {
74 if (ValueChangedByUser != null)
75 {
76 ValueChangedByUser(this, EventArgs.Empty);
77 }
78 }
79
80 private void notifyValueChanged()
81 {
82 if (ValueChanged != null)
83 {
84 ValueChanged(this, EventArgs.Empty);
85 }
86 }
87
88 /// <summary>
89 /// Draws the color bitmap.
90 /// </summary>
91 /// <returns></returns>
92 private Bitmap drawColorBitmap()
93 {
94 const int width = 100;
95 const int height = 5;
96 double h = _h;
97 double l = _l;
98
99 var bmp = new Bitmap(width, height);
100
101 for (int x = 0; x < width; ++x)
102 {
103 double s =width-x;
104 Color color = new HslColor(h, s, l).ToColor();
105 for (int y = 0; y < height; ++y)
106 {
107 bmp.SetPixel(x, y, color);
108 }
109
110 }
111 return bmp;
112 }
113
114 protected override void OnPaint(PaintEventArgs e)
115 {
116 base.OnPaint(e);
117 if (_colorBitmap == null)
118 {
119 _colorBitmap = drawColorBitmap();
120 }
121
122 double facXBmpToScreen = (double)_colorBitmap.Width / ClientSize.Width;
123 double facYBmpToScreen = (double)_colorBitmap.Height / ClientSize.Height;
124
125 var sourceRect = new Rectangle(
126 (int)(facXBmpToScreen * ClientRectangle.Left),
127 (int)(facYBmpToScreen * ClientRectangle.Top),
128 (int)(facXBmpToScreen * ClientRectangle.Width),
129 (int)(facYBmpToScreen * ClientRectangle.Height));
130
131 //e.Graphics.SmoothingMode = SmoothingMode.HighQuality;
132 e.Graphics.InterpolationMode = InterpolationMode.NearestNeighbor;
133 e.Graphics.DrawImage(
134 _colorBitmap,
135 ClientRectangle,
136 sourceRect,
137 GraphicsUnit.Pixel);
138
139 }
140 /// <summary>
141 /// 重新定位的箭头。
142 /// </summary>
143 /// <param name="offsetY">The offset X.</param>
144 private void repositionArrow(int offsetX)
145 {
146 offsetX = Math.Max(0, offsetX);
147 offsetX = Math.Min(ClientSize.Width - 1, offsetX);
148
149 arrowControl.Location = new Point(
150 offsetX - (arrowControl.Width / 2), arrowControl.Location.Y);
151 }
152
153 private void arrowControl_MouseMove(object sender, MouseEventArgs e)
154 {
155 if (e.Button == MouseButtons.Left)
156 {
157 repositionArrow(PointToClient(arrowControl.PointToScreen(e.Location)).X);
158 notifyValueChanged();
159 NotifyValueChangedByUser();
160 }
161
162 }
163
164 private void arrowControl_MouseDown(object sender, MouseEventArgs e)
165 {
166 if (e.Button == MouseButtons.Left)
167 {
168 repositionArrow(PointToClient(arrowControl.PointToScreen(e.Location)).X);
169 notifyValueChanged();
170 NotifyValueChangedByUser();
171 }
172 }
173
174 private void ColorSliderUserControl_MouseDown(object sender, MouseEventArgs e)
175 {
176 if (e.Button == MouseButtons.Left)
177 {
178 repositionArrow(PointToClient(this.PointToScreen(e.Location)).X);
179 notifyValueChanged();
180 NotifyValueChangedByUser();
181 }
182 }
183
184 private void ColorSliderUserControl_MouseMove(object sender, MouseEventArgs e)
185 {
186 if (e.Button == MouseButtons.Left)
187 {
188 repositionArrow(PointToClient(this.PointToScreen(e.Location)).X);
189 notifyValueChanged();
190 NotifyValueChangedByUser();
191 Invalidate();
192 }
193 }
194
195 }
196 }

还有几个颜色换算类在这里不贴了,不然这篇幅也太长了点,大家直接下载源码看吧

源码下载

posted @ 2011-03-22 11:58  ALong(阿龙)  阅读(2730)  评论(3编辑  收藏  举报