别人是说了再做,我是做了再说;别人说了不一定做,我是做了不一定说。

[原创]WinForm中重绘滚动条以及用重绘的滚动条控制ListBox的滚动

在本人的上一篇随笔<<高仿QQMusic播放器,浅谈WinForm关于UI的制作>>一文中,本人对播放器列表右边的灰色滚动条极为不满意,也影响到整个软件UI的协调性,遂下决心要重绘一个符合自己UI风格的滚动条.

查了很多资料,都找不到直接重写ListBox滚动条的方法,只能曲线救国,先自己重绘一个带皮肤的滚动条,然后让它取代ListBox现有的滚动条.
老习惯,先传个效果图,你觉得感兴趣就继续看下去,不喜欢的话就此打住,懒得耽误你宝

贵的时间,嘿嘿

注意,此图中的滚动条宽度明显小于ListBox本身滚动条的宽度,我目前只顾着实现功能了,毕竟,宽度调整相当简单哈。

下面简单介绍下重绘系统滚动条的详细步骤:

1.在项目中添加新项--用户控件,我们命名为CustomScrollbar.cs

2.准备几张图片添加进项目资源作为滚动条重绘时要用的背景,我用的图片如下:

 

     uparrow.png资源名称为uparrow   ,滚动条的上箭头

     ThumbBottom.png资源名称为ThumbBottom  ,滚动条中间滑道的背景


    ThumbMiddle.png资源名称为ThumbMiddle  ,滚动条的中间的拖动块


    downarrow.png资源名称为downarrow   ,滚动条的下箭头

3.然后就是利用上面图片做背景重画滚动条背景了,直接给出CustomScrollbar.cs的代码吧

 

代码
  1 using System;
  2 using System.Collections.Generic;
  3 using System.ComponentModel;
  4 using System.Drawing;
  5 using System.Data;
  6 using System.Text;
  7 using System.Windows.Forms;
  8 using System.Windows.Forms.Design;
  9 using System.Diagnostics;
 10 namespace Winamp
 11 {
 12     [Designer(typeof(ScrollbarControlDesigner))]
 13     public partial class CustomScrollbar : UserControl
 14     {
 15 
 16         protected Color moChannelColor = Color.Empty;
 17         protected Image moUpArrowImage = null;
 18                protected Image moDownArrowImage = null;
 19                 protected Image moThumbArrowImage = null;
 20 
 21         protected Image moThumbTopImage = null;
 22         protected Image moThumbTopSpanImage = null;
 23         protected Image moThumbBottomImage = null;
 24         protected Image moThumbBottomSpanImage = null;
 25         protected Image moThumbMiddleImage = null;
 26 
 27         protected int moLargeChange = 10;
 28         protected int moSmallChange = 1;
 29         protected int moMinimum = 0;
 30         protected int moMaximum = 100;
 31         protected int moValue = 0;
 32         private int nClickPoint;
 33 
 34         protected int moThumbTop = 0;
 35 
 36         protected bool moAutoSize = false;
 37 
 38         private bool moThumbDown = false;
 39         private bool moThumbDragging = false;
 40 
 41         public new event EventHandler Scroll = null;
 42         public event EventHandler ValueChanged = null;
 43 
 44         private int GetThumbHeight()
 45         {
 46             int nTrackHeight = (this.Height - (UpArrowImage.Height + DownArrowImage.Height));
 47             float fThumbHeight = ((float)LargeChange / (float)Maximum) * nTrackHeight;
 48             int nThumbHeight = (int)fThumbHeight;
 49 
 50             if (nThumbHeight > nTrackHeight)
 51             {
 52                 nThumbHeight = nTrackHeight;
 53                 fThumbHeight = nTrackHeight;
 54             }
 55             if (nThumbHeight < 56)
 56             {
 57                 nThumbHeight = 56;
 58                 fThumbHeight = 56;
 59             }
 60 
 61             return nThumbHeight;
 62         }
 63 
 64         public CustomScrollbar()
 65         {
 66 
 67             InitializeComponent();
 68             SetStyle(ControlStyles.ResizeRedraw, true);
 69             SetStyle(ControlStyles.AllPaintingInWmPaint, true);
 70             SetStyle(ControlStyles.DoubleBuffer, true);
 71 
 72             moChannelColor = Color.FromArgb(511663);
 73             UpArrowImage = BASSSkin.uparrow;
 74             DownArrowImage = BASSSkin.downarrow;
 75 
 76 
 77             ThumbBottomImage = BASSSkin.ThumbBottom;
 78 
 79             ThumbMiddleImage = BASSSkin.ThumbMiddle;
 80 
 81             this.Width = UpArrowImage.Width;
 82             base.MinimumSize = new Size(UpArrowImage.Width, UpArrowImage.Height + DownArrowImage.Height + GetThumbHeight());
 83         }
 84 
 85         [EditorBrowsable(EditorBrowsableState.Always), Browsable(true), DefaultValue(false), Category("Behavior"), Description
 86 
 87 ("LargeChange")]
 88         public int LargeChange
 89         {
 90             get { return moLargeChange; }
 91             set
 92             {
 93                 moLargeChange = value;
 94                 Invalidate();
 95             }
 96         }
 97 
 98         [EditorBrowsable(EditorBrowsableState.Always), Browsable(true), DefaultValue(false), Category("Behavior"), Description
 99 
100 ("SmallChange")]
101         public int SmallChange
102         {
103             get { return moSmallChange; }
104             set
105             {
106                 moSmallChange = value;
107                 Invalidate();
108             }
109         }
110 
111         [EditorBrowsable(EditorBrowsableState.Always), Browsable(true), DefaultValue(false), Category("Behavior"), Description("Minimum")]
112         public int Minimum
113         {
114             get { return moMinimum; }
115             set
116             {
117                 moMinimum = value;
118                 Invalidate();
119             }
120         }
121 
122         [EditorBrowsable(EditorBrowsableState.Always), Browsable(true), DefaultValue(false), Category("Behavior"), Description("Maximum")]
123         public int Maximum
124         {
125             get { return moMaximum; }
126             set
127             {
128                 moMaximum = value;
129                 Invalidate();
130             }
131         }
132 
133         [EditorBrowsable(EditorBrowsableState.Always), Browsable(true), DefaultValue(false), Category("Behavior"), Description("Value")]
134         public int Value
135         {
136             get { return moValue; }
137             set
138             {
139                 moValue = value;
140 
141                 int nTrackHeight = (this.Height - (UpArrowImage.Height + DownArrowImage.Height));
142                 float fThumbHeight = ((float)LargeChange / (float)Maximum) * nTrackHeight;
143                 int nThumbHeight = (int)fThumbHeight;
144 
145                 if (nThumbHeight > nTrackHeight)
146                 {
147                     nThumbHeight = nTrackHeight;
148                     fThumbHeight = nTrackHeight;
149                 }
150                 if (nThumbHeight < 56)
151                 {
152                     nThumbHeight = 56;
153                     fThumbHeight = 56;
154                 }
155 
156                 
157                 int nPixelRange = nTrackHeight - nThumbHeight;
158                 int nRealRange = (Maximum - Minimum) - LargeChange;
159                 float fPerc = 0.0f;
160                 if (nRealRange != 0)
161                 {
162                     fPerc = (float)moValue / (float)nRealRange;
163 
164                 }
165 
166                 float fTop = fPerc * nPixelRange;
167                 moThumbTop = (int)fTop;
168 
169 
170                 Invalidate();
171             }
172         }
173 
174         [EditorBrowsable(EditorBrowsableState.Always), Browsable(true), DefaultValue(false), Category("Skin"), Description("Channel Color")]
175         public Color ChannelColor
176         {
177             get { return moChannelColor; }
178             set { moChannelColor = value; }
179         }
180 
181         [EditorBrowsable(EditorBrowsableState.Always), Browsable(true), DefaultValue(false), Category("Skin"), Description("Up Arrow 
182 
183 Graphic")]
184         public Image UpArrowImage
185         {
186             get { return moUpArrowImage; }
187             set { moUpArrowImage = value; }
188         }
189 
190         [EditorBrowsable(EditorBrowsableState.Always), Browsable(true), DefaultValue(false), Category("Skin"), Description("Up Arrow 
191 
192 Graphic")]
193         public Image DownArrowImage
194         {
195             get { return moDownArrowImage; }
196             set { moDownArrowImage = value; }
197         }
198 
199 
200 
201 
202         [EditorBrowsable(EditorBrowsableState.Always), Browsable(true), DefaultValue(false), Category("Skin"), Description("Up Arrow 
203 
204 Graphic")]
205         public Image ThumbBottomImage
206         {
207             get { return moThumbBottomImage; }
208             set { moThumbBottomImage = value; }
209         }
210 
211 
212 
213         [EditorBrowsable(EditorBrowsableState.Always), Browsable(true), DefaultValue(false), Category("Skin"), Description("Up Arrow 
214 
215 Graphic")]
216         public Image ThumbMiddleImage
217         {
218             get { return moThumbMiddleImage; }
219             set { moThumbMiddleImage = value; }
220         }
221 
222         protected override void OnPaint(PaintEventArgs e)
223         {
224 
225             e.Graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.NearestNeighbor;
226 
227             if (UpArrowImage != null)
228             {
229                 e.Graphics.DrawImage(UpArrowImage, new Rectangle(new Point(00), new Size(this.Width, UpArrowImage.Height)));
230             }
231 
232             Brush oBrush = new SolidBrush(moChannelColor);
233             Brush oWhiteBrush = new SolidBrush(Color.FromArgb(255255255));
234             
235             e.Graphics.FillRectangle(oWhiteBrush, new Rectangle(0, UpArrowImage.Height, 1, (this.Height - DownArrowImage.Height)));
236             e.Graphics.FillRectangle(oWhiteBrush, new Rectangle(this.Width - 1, UpArrowImage.Height, 1, (this.Height - 
237 
238 DownArrowImage.Height)));
239 
240            
241             e.Graphics.DrawImage(ThumbBottomImage, new Rectangle(0, UpArrowImage.Height, this.Width, (this.Height - DownArrowImage.Height)));
242          
243             int nTrackHeight = (this.Height - (UpArrowImage.Height + DownArrowImage.Height));
244             float fThumbHeight = ((float)LargeChange / (float)Maximum) * nTrackHeight;
245             int nThumbHeight = (int)fThumbHeight;
246 
247             if (nThumbHeight > nTrackHeight)
248             {
249                 nThumbHeight = nTrackHeight;
250                 fThumbHeight = nTrackHeight;
251             }
252          
253             if (nThumbHeight < 56)
254             {
255                 nThumbHeight = 56;
256                 fThumbHeight = 56;
257             }
258 
259             
260             int nTop = moThumbTop;//0
261             nTop += UpArrowImage.Height;//9px
262 
263             
264             e.Graphics.DrawImage(ThumbMiddleImage, new Rectangle(0, nTop, this.Width, ThumbMiddleImage.Height));
265 
266 
267             
268             if (DownArrowImage != null)
269             {
270                 e.Graphics.DrawImage(DownArrowImage, new Rectangle(new Point(0, (this.Height - DownArrowImage.Height)), new Size(this.Width, 
271 
272 DownArrowImage.Height)));
273             }
274 
275         }
276 
277 
278         public override bool AutoSize
279         {
280             get
281             {
282                 return base.AutoSize;
283             }
284             set
285             {
286                 base.AutoSize = value;
287                 if (base.AutoSize)
288                 {
289                     this.Width = moUpArrowImage.Width;
290                 }
291             }
292         }
293 
294         private void InitializeComponent()
295         {
296             this.SuspendLayout();
297           
298             this.Name = "CustomScrollbar";
299             this.MouseDown += new System.Windows.Forms.MouseEventHandler(this.CustomScrollbar_MouseDown);
300             this.MouseMove += new System.Windows.Forms.MouseEventHandler(this.CustomScrollbar_MouseMove);
301             this.MouseUp += new System.Windows.Forms.MouseEventHandler(this.CustomScrollbar_MouseUp);
302             this.ResumeLayout(false);
303 
304         }
305 
306         private void CustomScrollbar_MouseDown(object sender, MouseEventArgs e)
307         {
308             Point ptPoint = this.PointToClient(Cursor.Position);
309             int nTrackHeight = (this.Height - (UpArrowImage.Height + DownArrowImage.Height));
310             float fThumbHeight = ((float)LargeChange / (float)Maximum) * nTrackHeight;
311             int nThumbHeight = (int)fThumbHeight;
312 
313             if (nThumbHeight > nTrackHeight)
314             {
315                 nThumbHeight = nTrackHeight;
316                 fThumbHeight = nTrackHeight;
317             }
318             if (nThumbHeight < 56)
319             {
320                 nThumbHeight = 56;
321                 fThumbHeight = 56;
322             }
323 
324             int nTop = moThumbTop;
325             nTop += UpArrowImage.Height;
326 
327 
328             Rectangle thumbrect = new Rectangle(new Point(1, nTop), new Size(ThumbMiddleImage.Width, nThumbHeight));
329             if (thumbrect.Contains(ptPoint))
330             {
331 
332              
333                 nClickPoint = (ptPoint.Y - nTop);
334                
335                 this.moThumbDown = true;
336             }
337 
338             Rectangle uparrowrect = new Rectangle(new Point(10), new Size(UpArrowImage.Width, UpArrowImage.Height));
339             if (uparrowrect.Contains(ptPoint))
340             {
341 
342                 int nRealRange = (Maximum - Minimum) - LargeChange;
343                 int nPixelRange = (nTrackHeight - nThumbHeight);
344                 if (nRealRange > 0)
345                 {
346                     if (nPixelRange > 0)
347                     {
348                         if ((moThumbTop - SmallChange) < 0)
349                             moThumbTop = 0;
350                         else
351                             moThumbTop -= SmallChange;
352 
353                       
354                         float fPerc = (float)moThumbTop / (float)nPixelRange;
355                         float fValue = fPerc * (Maximum - LargeChange);
356 
357                         moValue = (int)fValue;
358                         Debug.WriteLine(moValue.ToString());
359 
360                         if (ValueChanged != null)
361                             ValueChanged(thisnew EventArgs());
362 
363                         if (Scroll != null)
364                             Scroll(thisnew EventArgs());
365 
366                         Invalidate();
367                     }
368                 }
369             }
370 
371             Rectangle downarrowrect = new Rectangle(new Point(1, UpArrowImage.Height + nTrackHeight), new Size(UpArrowImage.Width, 
372 
373 UpArrowImage.Height));
374             if (downarrowrect.Contains(ptPoint))
375             {
376                 int nRealRange = (Maximum - Minimum) - LargeChange;
377                 int nPixelRange = (nTrackHeight - nThumbHeight);
378                 if (nRealRange > 0)
379                 {
380                     if (nPixelRange > 0)
381                     {
382                         if ((moThumbTop + SmallChange) > nPixelRange)
383                             moThumbTop = nPixelRange;
384                         else
385                             moThumbTop += SmallChange;
386 
387                     
388                         float fPerc = (float)moThumbTop / (float)nPixelRange;
389                         float fValue = fPerc * (Maximum - LargeChange);
390 
391                         moValue = (int)fValue;
392                         Debug.WriteLine(moValue.ToString());
393 
394                         if (ValueChanged != null)
395                             ValueChanged(thisnew EventArgs());
396 
397                         if (Scroll != null)
398                             Scroll(thisnew EventArgs());
399 
400                         Invalidate();
401                     }
402                 }
403             }
404         }
405 
406         private void CustomScrollbar_MouseUp(object sender, MouseEventArgs e)
407         {
408             this.moThumbDown = false;
409             this.moThumbDragging = false;
410         }
411 
412         private void MoveThumb(int y)
413         {
414             int nRealRange = Maximum - Minimum;
415             int nTrackHeight = (this.Height - (UpArrowImage.Height + DownArrowImage.Height));
416             float fThumbHeight = ((float)LargeChange / (float)Maximum) * nTrackHeight;
417             int nThumbHeight = (int)fThumbHeight;
418 
419             if (nThumbHeight > nTrackHeight)
420             {
421                 nThumbHeight = nTrackHeight;
422                 fThumbHeight = nTrackHeight;
423             }
424             if (nThumbHeight < 56)
425             {
426                 nThumbHeight = 56;
427                 fThumbHeight = 56;
428             }
429 
430             int nSpot = nClickPoint;
431 
432             int nPixelRange = (nTrackHeight - nThumbHeight);
433             if (moThumbDown && nRealRange > 0)
434             {
435                 if (nPixelRange > 0)
436                 {
437                     int nNewThumbTop = y - (UpArrowImage.Height + nSpot);
438 
439                     if (nNewThumbTop < 0)
440                     {
441                         moThumbTop = nNewThumbTop = 0;
442                     }
443                     else if (nNewThumbTop > nPixelRange)
444                     {
445                         moThumbTop = nNewThumbTop = nPixelRange;
446                     }
447                     else
448                     {
449                         moThumbTop = y - (UpArrowImage.Height + nSpot);
450                     }
451 
452                   
453                     float fPerc = (float)moThumbTop / (float)nPixelRange;
454                     float fValue = fPerc * (Maximum - LargeChange);
455                     moValue = (int)fValue;
456                     Debug.WriteLine(moValue.ToString());
457 
458                     Application.DoEvents();
459 
460                     Invalidate();
461                 }
462             }
463         }
464 
465         private void CustomScrollbar_MouseMove(object sender, MouseEventArgs e)
466         {
467             if (moThumbDown == true)
468             {
469                 this.moThumbDragging = true;
470             }
471 
472             if (this.moThumbDragging)
473             {
474 
475                 MoveThumb(e.Y);
476             }
477 
478             if (ValueChanged != null)
479                 ValueChanged(thisnew EventArgs());
480 
481             if (Scroll != null)
482                 Scroll(thisnew EventArgs());
483         }
484 
485     }
486 
487     internal class ScrollbarControlDesigner : System.Windows.Forms.Design.ControlDesigner
488     {
489 
490 
491 
492         public override SelectionRules SelectionRules
493         {
494             get
495             {
496                 SelectionRules selectionRules = base.SelectionRules;
497                 PropertyDescriptor propDescriptor = TypeDescriptor.GetProperties(this.Component)["AutoSize"];
498                 if (propDescriptor != null)
499                 {
500                     bool autoSize = (bool)propDescriptor.GetValue(this.Component);
501                     if (autoSize)
502                     {
503                         selectionRules = SelectionRules.Visible | SelectionRules.Moveable | SelectionRules.BottomSizeable | 
504 
505 SelectionRules.TopSizeable;
506                     }
507                     else
508                     {
509                         selectionRules = SelectionRules.Visible | SelectionRules.AllSizeable | SelectionRules.Moveable;
510                     }
511                 }
512                 return selectionRules;
513             }
514         }
515     }
516 }

 

 

目前只想简单实现滚动条中上箭头/下箭头/滑道/拖动块的重写,所以以上代码中OnPaint函数里的部分内容被我注释了,好了,这个滚动条控件已经做好了,一个控件而已,你应该会使用它,我就不罗嗦了。

 

接下来就是怎么用它来控制ListBox的内容滚动的问题了,这需要调用API函数来实现,同时又不能设置ListBox无滚动条,因为ListBox没有滚动条也就没有滚动的事件可捕获,那就达不到滚动的效果了。

在你的窗体里拖一个listbox控件和一个上边我们制作好的用户控件,分明命名为listBox和customScrollbar1,

然后往listBox中随便多弄写内容,使之出现滚动条即可。调整customScrollbar1的位置使之覆盖在listBox的滚动条上,呵呵,这方法不错吧?

然后我们定义一下Win32API,代码如下:

 

Code

 

定义customScrollbar1的滚动事件函数customScrollbar1_Scroll,实现在滚动条滚动的同时发消息给listBox使之同步滚动

 

Code

 

 

感谢博友Yellowyu在滚动控制方面给予的帮助。

调整了一下滚动条重绘所用到的图片的尺寸,看起来效果好多了!!!

posted @ 2009-04-01 22:46  碧血黄沙-java、c#  阅读(14990)  评论(21编辑  收藏  举报