zoukankan      html  css  js  c++  java
  • [原创]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在滚动控制方面给予的帮助。

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

    新站上线--咱地里 www.zandili.com 科技博客
  • 相关阅读:
    时间线 | timeline | 简易GitHub部署
    名词解释 | Lead SNPs | credible SNPs | Polygenicity | Discoverability
    Phenome-wide association studies | PheWAS
    孟德尔随机化 | Mendelian randomization
    探索性因子分析法 | exploratory factor analysis | EFA | Genomic Structural Equation Modelling | SEM
    漫画 | 到底是什么让IT人如此苦逼???
    国产Java代码补全神器,aiXcoder 2.0实测
    Dubbo学习(一) Dubbo原理浅析【转】
    Dubbo架构与底层实现【转】
    HAproxy 默认短连接,特殊域名开启长连接的配置方法【转】
  • 原文地址:https://www.cnblogs.com/airfey/p/1427590.html
Copyright © 2011-2022 走看看