主頁 > .NET開發 > (六十九)c#Winform自定義控制元件-垂直滾動條-HZHControls

(六十九)c#Winform自定義控制元件-垂直滾動條-HZHControls

2020-09-11 17:38:15 .NET開發

官網

http://www.hzhcontrols.com

前提

入行已經7,8年了,一直想做一套漂亮點的自定義控制元件,于是就有了本系列文章,

GitHub:https://github.com/kwwwvagaa/NetWinformControl

碼云:https://gitee.com/kwwwvagaa/net_winform_custom_control.git

如果覺得寫的還行,請點個 star 支持一下吧

歡迎前來交流探討: 企鵝群568015492 企鵝群568015492

麻煩博客下方點個【推薦】,謝謝

NuGet

Install-Package HZH_Controls

目錄

https://www.cnblogs.com/bfyx/p/11364884.html

用處及效果

 

 

 

 目前支持ScrollableControl,TreeView,TextBox的滾動條,只需要在相應的界面上添加組件ScrollbarComponent即可

準備作業

用到了(一)c#Winform自定義控制元件-基類控制元件 ,如果你還不了解,可以先去看一下

自定義滾動條有2種方式,1:攔截windows訊息,重繪,2:做一個新的,蓋上去擋著,這里我們采用的是第二種,

開始

添加一個類UCVScrollbar,繼承UCControlBase

一些屬性

  1  /// <summary>  2         /// The mo large change  3         /// </summary>  4         protected int moLargeChange = 10;  5         /// <summary>  6         /// The mo small change  7         /// </summary>  8         protected int moSmallChange = 1;  9         /// <summary> 10         /// The mo minimum 11         /// </summary> 12         protected int moMinimum = 0; 13         /// <summary> 14         /// The mo maximum 15         /// </summary> 16         protected int moMaximum = 100; 17         /// <summary> 18         /// The mo value 19         /// </summary> 20         protected int moValue = https://www.cnblogs.com/bfyx/p/0; 21         /// <summary> 22         /// The n click point 23         /// </summary> 24         private int nClickPoint; 25         /// <summary> 26         /// The mo thumb top 27         /// </summary> 28         protected int moThumbTop = 0; 29         /// <summary> 30         /// The mo automatic size 31         /// </summary> 32         protected bool moAutoSize = false; 33         /// <summary> 34         /// The mo thumb down 35         /// </summary> 36         private bool moThumbDown = false; 37         /// <summary> 38         /// The mo thumb dragging 39         /// </summary> 40         private bool moThumbDragging = false; 41         /// <summary> 42         /// Occurs when [scroll]. 43         /// </summary> 44         public new event EventHandler Scroll = null; 45         /// <summary> 46         /// Occurs when [value changed]. 47         /// </summary> 48         public event EventHandler ValueChanged = null; 49  50         /// <summary> 51         /// The BTN height 52         /// </summary> 53         private int btnHeight = 18; 54         /// <summary> 55         /// The m int thumb minimum height 56         /// </summary> 57         private int m_intThumbMinHeight = 15; 58  59         /// <summary> 60         /// Gets or sets the height of the BTN. 61         /// </summary> 62         /// <value>The height of the BTN.</value> 63         public int BtnHeight 64         { 65             get { return btnHeight; } 66             set { btnHeight = value; } 67         } 68         /// <summary> 69         /// Gets or sets the large change. 70         /// </summary> 71         /// <value>The large change.</value> 72         [EditorBrowsable(EditorBrowsableState.Always), Browsable(true), DefaultValue(false), Category("自定義"), Description("LargeChange")] 73         public int LargeChange 74         { 75             get { return moLargeChange; } 76             set 77             { 78                 moLargeChange = value; 79                 Invalidate(); 80             } 81         } 82  83         /// <summary> 84         /// Gets or sets the small change. 85         /// </summary> 86         /// <value>The small change.</value> 87         [EditorBrowsable(EditorBrowsableState.Always), Browsable(true), DefaultValue(false), Category("自定義"), Description("SmallChange")] 88         public int SmallChange 89         { 90             get { return moSmallChange; } 91             set 92             { 93                 moSmallChange = value; 94                 Invalidate(); 95             } 96         } 97  98         /// <summary> 99         /// Gets or sets the minimum.100         /// </summary>101         /// <value>The minimum.</value>102         [EditorBrowsable(EditorBrowsableState.Always), Browsable(true), DefaultValue(false), Category("自定義"), Description("Minimum")]103         public int Minimum104         {105             get { return moMinimum; }106             set107             {108                 moMinimum = value;109                 Invalidate();110             }111         }112 113         /// <summary>114         /// Gets or sets the maximum.115         /// </summary>116         /// <value>The maximum.</value>117         [EditorBrowsable(EditorBrowsableState.Always), Browsable(true), DefaultValue(false), Category("自定義"), Description("Maximum")]118         public int Maximum119         {120             get { return moMaximum; }121             set122             {123                 moMaximum = value;124                 Invalidate();125             }126         }127 128         /// <summary>129         /// Gets or sets the value.130         /// </summary>131         /// <value>The value.</value>132         [EditorBrowsable(EditorBrowsableState.Always), Browsable(true), DefaultValue(false), Category("自定義"), Description("Value")]133         public int Value134         {135             get { return moValue; }136             set137             {138                 moValue =https://www.cnblogs.com/bfyx/p/ value;139 140                 int nTrackHeight = (this.Height - btnHeight * 2);141                 float fThumbHeight = ((float)LargeChange / (float)Maximum) * nTrackHeight;142                 int nThumbHeight = (int)fThumbHeight;143 144                 if (nThumbHeight > nTrackHeight)145                 {146                     nThumbHeight = nTrackHeight;147                     fThumbHeight = nTrackHeight;148                 }149                 if (nThumbHeight < m_intThumbMinHeight)150                 {151                     nThumbHeight = m_intThumbMinHeight;152                     fThumbHeight = m_intThumbMinHeight;153                 }154 155                 //figure out value156                 int nPixelRange = nTrackHeight - nThumbHeight;157                 int nRealRange = (Maximum - Minimum) - LargeChange;158                 float fPerc = 0.0f;159                 if (nRealRange != 0)160                 {161                     fPerc = (float)moValue / (float)nRealRange;162 163                 }164 165                 float fTop = fPerc * nPixelRange;166                 moThumbTop = (int)fTop;167 168 169                 Invalidate();170             }171         }172 173         /// <summary>174         /// Gets or sets a value indicating whether [automatic size].175         /// </summary>176         /// <value><c>true</c> if [automatic size]; otherwise, <c>false</c>.</value>177         public override bool AutoSize178         {179             get180             {181                 return base.AutoSize;182             }183             set184             {185                 base.AutoSize = value;186                 if (base.AutoSize)187                 {188                     this.Width = 15;189                 }190             }191         }192 193         /// <summary>194         /// The thumb color195         /// </summary>196         private Color thumbColor = Color.FromArgb(255, 77, 58);197 198         /// <summary>199         /// Gets or sets the color of the thumb.200         /// </summary>201         /// <value>The color of the thumb.</value>202         public Color ThumbColor203         {204             get { return thumbColor; }205             set { thumbColor = value; }206         }

重繪

 1  protected override void OnPaint(PaintEventArgs e) 2         { 3             base.OnPaint(e); 4             e.Graphics.SetGDIHigh(); 5  6             //draw thumb 7             int nTrackHeight = (this.Height - btnHeight * 2); 8             float fThumbHeight = ((float)LargeChange / (float)Maximum) * nTrackHeight; 9             int nThumbHeight = (int)fThumbHeight;10 11             if (nThumbHeight > nTrackHeight)12             {13                 nThumbHeight = nTrackHeight;14                 fThumbHeight = nTrackHeight;15             }16             if (nThumbHeight < m_intThumbMinHeight)17             {18                 nThumbHeight = m_intThumbMinHeight;19                 fThumbHeight = m_intThumbMinHeight;20             }21             int nTop = moThumbTop;22             nTop += btnHeight;23             e.Graphics.FillPath(new SolidBrush(thumbColor), new Rectangle(1, nTop, this.Width - 3, nThumbHeight).CreateRoundedRectanglePath(this.ConerRadius));24 25             ControlHelper.PaintTriangle(e.Graphics, new SolidBrush(thumbColor), new Point(this.Width / 2, btnHeight - Math.Min(5, this.Width / 2)), Math.Min(5, this.Width / 2), GraphDirection.Upward);26             ControlHelper.PaintTriangle(e.Graphics, new SolidBrush(thumbColor), new Point(this.Width / 2, this.Height - (btnHeight - Math.Min(5, this.Width / 2))), Math.Min(5, this.Width / 2), GraphDirection.Downward);27 28         }

處理下滑鼠事件

  1  /// <summary>  2         /// Handles the MouseDown event of the CustomScrollbar control.  3         /// </summary>  4         /// <param name="sender">The source of the event.</param>  5         /// <param name="e">The <see cref="MouseEventArgs"/> instance containing the event data.</param>  6         private void CustomScrollbar_MouseDown(object sender, MouseEventArgs e)  7         {  8             Point ptPoint = this.PointToClient(Cursor.Position);  9             int nTrackHeight = (this.Height - btnHeight * 2); 10             float fThumbHeight = ((float)LargeChange / (float)Maximum) * nTrackHeight; 11             int nThumbHeight = (int)fThumbHeight; 12  13             if (nThumbHeight > nTrackHeight) 14             { 15                 nThumbHeight = nTrackHeight; 16                 fThumbHeight = nTrackHeight; 17             } 18             if (nThumbHeight < m_intThumbMinHeight) 19             { 20                 nThumbHeight = m_intThumbMinHeight; 21                 fThumbHeight = m_intThumbMinHeight; 22             } 23  24             int nTop = moThumbTop; 25             nTop += btnHeight; 26  27  28             Rectangle thumbrect = new Rectangle(new Point(1, nTop), new Size(this.Width - 2, nThumbHeight)); 29             if (thumbrect.Contains(ptPoint)) 30             { 31  32                 //hit the thumb 33                 nClickPoint = (ptPoint.Y - nTop); 34                 //MessageBox.Show(Convert.ToString((ptPoint.Y - nTop))); 35                 this.moThumbDown = true; 36             } 37  38             Rectangle uparrowrect = new Rectangle(new Point(1, 0), new Size(this.Width, btnHeight)); 39             if (uparrowrect.Contains(ptPoint)) 40             { 41  42                 int nRealRange = (Maximum - Minimum) - LargeChange; 43                 int nPixelRange = (nTrackHeight - nThumbHeight); 44                 if (nRealRange > 0) 45                 { 46                     if (nPixelRange > 0) 47                     { 48                         if ((moThumbTop - SmallChange) < 0) 49                             moThumbTop = 0; 50                         else 51                             moThumbTop -= SmallChange; 52  53                         //figure out value 54                         float fPerc = (float)moThumbTop / (float)nPixelRange; 55                         float fValue = https://www.cnblogs.com/bfyx/p/fPerc * (Maximum - LargeChange); 56  57                         moValue = https://www.cnblogs.com/bfyx/p/(int)fValue; 58  59                         if (ValueChanged != null) 60                             ValueChanged(this, new EventArgs()); 61  62                         if (Scroll != null) 63                             Scroll(this, new EventArgs()); 64  65                         Invalidate(); 66                     } 67                 } 68             } 69  70             Rectangle downarrowrect = new Rectangle(new Point(1, btnHeight + nTrackHeight), new Size(this.Width, btnHeight)); 71             if (downarrowrect.Contains(ptPoint)) 72             { 73                 int nRealRange = (Maximum - Minimum) - LargeChange; 74                 int nPixelRange = (nTrackHeight - nThumbHeight); 75                 if (nRealRange > 0) 76                 { 77                     if (nPixelRange > 0) 78                     { 79                         if ((moThumbTop + SmallChange) > nPixelRange) 80                             moThumbTop = nPixelRange; 81                         else 82                             moThumbTop += SmallChange; 83  84                         //figure out value 85                         float fPerc = (float)moThumbTop / (float)nPixelRange; 86                         float fValue = https://www.cnblogs.com/bfyx/p/fPerc * (Maximum - LargeChange); 87  88                         moValue = https://www.cnblogs.com/bfyx/p/(int)fValue; 89  90                         if (ValueChanged != null) 91                             ValueChanged(this, new EventArgs()); 92  93                         if (Scroll != null) 94                             Scroll(this, new EventArgs()); 95  96                         Invalidate(); 97                     } 98                 } 99             }100         }101 102         /// <summary>103         /// Handles the MouseUp event of the CustomScrollbar control.104         /// </summary>105         /// <param name="sender">The source of the event.</param>106         /// <param name="e">The <see cref="MouseEventArgs"/> instance containing the event data.</param>107         private void CustomScrollbar_MouseUp(object sender, MouseEventArgs e)108         {109             this.moThumbDown = false;110             this.moThumbDragging = false;111         }112 113         /// <summary>114         /// Moves the thumb.115         /// </summary>116         /// <param name="y">The y.</param>117         private void MoveThumb(int y)118         {119             int nRealRange = Maximum - Minimum;120             int nTrackHeight = (this.Height - btnHeight * 2);121             float fThumbHeight = ((float)LargeChange / (float)Maximum) * nTrackHeight;122             int nThumbHeight = (int)fThumbHeight;123 124             if (nThumbHeight > nTrackHeight)125             {126                 nThumbHeight = nTrackHeight;127                 fThumbHeight = nTrackHeight;128             }129             if (nThumbHeight < m_intThumbMinHeight)130             {131                 nThumbHeight = m_intThumbMinHeight;132                 fThumbHeight = m_intThumbMinHeight;133             }134 135             int nSpot = nClickPoint;136 137             int nPixelRange = (nTrackHeight - nThumbHeight);138             if (moThumbDown && nRealRange > 0)139             {140                 if (nPixelRange > 0)141                 {142                     int nNewThumbTop = y - (btnHeight + nSpot);143 144                     if (nNewThumbTop < 0)145                     {146                         moThumbTop = nNewThumbTop = 0;147                     }148                     else if (nNewThumbTop > nPixelRange)149                     {150                         moThumbTop = nNewThumbTop = nPixelRange;151                     }152                     else153                     {154                         moThumbTop = y - (btnHeight + nSpot);155                     }156 157 158                     float fPerc = (float)moThumbTop / (float)nPixelRange;159                     float fValue = https://www.cnblogs.com/bfyx/p/fPerc * (Maximum - LargeChange);160                     moValue = https://www.cnblogs.com/bfyx/p/(int)fValue;161 162                     Application.DoEvents();163 164                     Invalidate();165                 }166             }167         }168 169         /// <summary>170         /// Handles the MouseMove event of the CustomScrollbar control.171         /// </summary>172         /// <param name="sender">The source of the event.</param>173         /// <param name="e">The <see cref="MouseEventArgs"/> instance containing the event data.</param>174         private void CustomScrollbar_MouseMove(object sender, MouseEventArgs e)175         {176             if (!moThumbDown)177                 return;178 179             if (moThumbDown == true)180             {181                 this.moThumbDragging = true;182             }183 184             if (this.moThumbDragging)185             {186                 MoveThumb(e.Y);187             }188 189             if (ValueChanged != null)190                 ValueChanged(this, new EventArgs());191 192             if (Scroll != null)193                 Scroll(this, new EventArgs());194         }

完整代碼

  1 // ***********************************************************************  2 // Assembly         : HZH_Controls  3 // Created          : 2019-09-19  4 //  5 // ***********************************************************************  6 // <copyright file="UCVScrollbar.cs">  7 //     Copyright by Huang Zhenghui(黃正輝) All, QQ group:568015492 QQ:623128629 Email:[email protected]  8 // </copyright>  9 // 10 // Blog: https://www.cnblogs.com/bfyx 11 // GitHub:https://github.com/kwwwvagaa/NetWinformControl 12 // gitee:https://gitee.com/kwwwvagaa/net_winform_custom_control.git 13 // 14 // If you use this code, please keep this note. 15 // *********************************************************************** 16 using System; 17 using System.Collections.Generic; 18 using System.ComponentModel; 19 using System.Drawing; 20 using System.Data; 21 using System.Text; 22 using System.Windows.Forms; 23 using System.Windows.Forms.Design; 24 using System.Diagnostics; 25  26  27 namespace HZH_Controls.Controls 28 { 29  30     /// <summary> 31     /// Class UCVScrollbar. 32     /// Implements the <see cref="HZH_Controls.Controls.UCControlBase" /> 33     /// </summary> 34     /// <seealso cref="HZH_Controls.Controls.UCControlBase" /> 35     [Designer(typeof(ScrollbarControlDesigner))] 36     [DefaultEvent("Scroll")] 37     public class UCVScrollbar : UCControlBase 38     {         39         /// <summary> 40         /// The mo large change 41         /// </summary> 42         protected int moLargeChange = 10; 43         /// <summary> 44         /// The mo small change 45         /// </summary> 46         protected int moSmallChange = 1; 47         /// <summary> 48         /// The mo minimum 49         /// </summary> 50         protected int moMinimum = 0; 51         /// <summary> 52         /// The mo maximum 53         /// </summary> 54         protected int moMaximum = 100; 55         /// <summary> 56         /// The mo value 57         /// </summary> 58         protected int moValue = https://www.cnblogs.com/bfyx/p/0; 59         /// <summary> 60         /// The n click point 61         /// </summary> 62         private int nClickPoint; 63         /// <summary> 64         /// The mo thumb top 65         /// </summary> 66         protected int moThumbTop = 0; 67         /// <summary> 68         /// The mo automatic size 69         /// </summary> 70         protected bool moAutoSize = false; 71         /// <summary> 72         /// The mo thumb down 73         /// </summary> 74         private bool moThumbDown = false; 75         /// <summary> 76         /// The mo thumb dragging 77         /// </summary> 78         private bool moThumbDragging = false; 79         /// <summary> 80         /// Occurs when [scroll]. 81         /// </summary> 82         public new event EventHandler Scroll = null; 83         /// <summary> 84         /// Occurs when [value changed]. 85         /// </summary> 86         public event EventHandler ValueChanged = null; 87  88         /// <summary> 89         /// The BTN height 90         /// </summary> 91         private int btnHeight = 18; 92         /// <summary> 93         /// The m int thumb minimum height 94         /// </summary> 95         private int m_intThumbMinHeight = 15; 96  97         /// <summary> 98         /// Gets or sets the height of the BTN. 99         /// </summary>100         /// <value>The height of the BTN.</value>101         public int BtnHeight102         {103             get { return btnHeight; }104             set { btnHeight = value; }105         }106         /// <summary>107         /// Gets or sets the large change.108         /// </summary>109         /// <value>The large change.</value>110         [EditorBrowsable(EditorBrowsableState.Always), Browsable(true), DefaultValue(false), Category("自定義"), Description("LargeChange")]111         public int LargeChange112         {113             get { return moLargeChange; }114             set115             {116                 moLargeChange = value;117                 Invalidate();118             }119         }120 121         /// <summary>122         /// Gets or sets the small change.123         /// </summary>124         /// <value>The small change.</value>125         [EditorBrowsable(EditorBrowsableState.Always), Browsable(true), DefaultValue(false), Category("自定義"), Description("SmallChange")]126         public int SmallChange127         {128             get { return moSmallChange; }129             set130             {131                 moSmallChange = value;132                 Invalidate();133             }134         }135 136         /// <summary>137         /// Gets or sets the minimum.138         /// </summary>139         /// <value>The minimum.</value>140         [EditorBrowsable(EditorBrowsableState.Always), Browsable(true), DefaultValue(false), Category("自定義"), Description("Minimum")]141         public int Minimum142         {143             get { return moMinimum; }144             set145             {146                 moMinimum = value;147                 Invalidate();148             }149         }150 151         /// <summary>152         /// Gets or sets the maximum.153         /// </summary>154         /// <value>The maximum.</value>155         [EditorBrowsable(EditorBrowsableState.Always), Browsable(true), DefaultValue(false), Category("自定義"), Description("Maximum")]156         public int Maximum157         {158             get { return moMaximum; }159             set160             {161                 moMaximum = value;162                 Invalidate();163             }164         }165 166         /// <summary>167         /// Gets or sets the value.168         /// </summary>169         /// <value>The value.</value>170         [EditorBrowsable(EditorBrowsableState.Always), Browsable(true), DefaultValue(false), Category("自定義"), Description("Value")]171         public int Value172         {173             get { return moValue; }174             set175             {176                 moValue =https://www.cnblogs.com/bfyx/p/ value;177 178                 int nTrackHeight = (this.Height - btnHeight * 2);179                 float fThumbHeight = ((float)LargeChange / (float)Maximum) * nTrackHeight;180                 int nThumbHeight = (int)fThumbHeight;181 182                 if (nThumbHeight > nTrackHeight)183                 {184                     nThumbHeight = nTrackHeight;185                     fThumbHeight = nTrackHeight;186                 }187                 if (nThumbHeight < m_intThumbMinHeight)188                 {189                     nThumbHeight = m_intThumbMinHeight;190                     fThumbHeight = m_intThumbMinHeight;191                 }192 193                 //figure out value194                 int nPixelRange = nTrackHeight - nThumbHeight;195                 int nRealRange = (Maximum - Minimum) - LargeChange;196                 float fPerc = 0.0f;197                 if (nRealRange != 0)198                 {199                     fPerc = (float)moValue / (float)nRealRange;200 201                 }202 203                 float fTop = fPerc * nPixelRange;204                 moThumbTop = (int)fTop;205 206 207                 Invalidate();208             }209         }210 211         /// <summary>212         /// Gets or sets a value indicating whether [automatic size].213         /// </summary>214         /// <value><c>true</c> if [automatic size]; otherwise, <c>false</c>.</value>215         public override bool AutoSize216         {217             get218             {219                 return base.AutoSize;220             }221             set222             {223                 base.AutoSize = value;224                 if (base.AutoSize)225                 {226                     this.Width = 15;227                 }228             }229         }230 231         /// <summary>232         /// The thumb color233         /// </summary>234         private Color thumbColor = Color.FromArgb(255, 77, 58);235 236         /// <summary>237         /// Gets or sets the color of the thumb.238         /// </summary>239         /// <value>The color of the thumb.</value>240         public Color ThumbColor241         {242             get { return thumbColor; }243             set { thumbColor = value; }244         }245 246         /// <summary>247         /// Initializes a new instance of the <see cref="UCVScrollbar"/> class.248         /// </summary>249         public UCVScrollbar()250         {251             InitializeComponent();252             ConerRadius = 2;253             FillColor = Color.FromArgb(239, 239, 239);254             IsShowRect = false;255             IsRadius = true;256             this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);257             this.SetStyle(ControlStyles.DoubleBuffer, true);258             this.SetStyle(ControlStyles.ResizeRedraw, true);259             this.SetStyle(ControlStyles.Selectable, true);260             this.SetStyle(ControlStyles.SupportsTransparentBackColor, true);261             this.SetStyle(ControlStyles.UserPaint, true);262         }263 264 265 266 267         /// <summary>268         /// 引發 <see cref="E:System.Windows.Forms.Control.Paint" /> 事件,269         /// </summary>270         /// <param name="e">包含事件資料的 <see cref="T:System.Windows.Forms.PaintEventArgs" /></param>271         protected override void OnPaint(PaintEventArgs e)272         {273             base.OnPaint(e);274             e.Graphics.SetGDIHigh();275 276             //draw thumb277             int nTrackHeight = (this.Height - btnHeight * 2);278             float fThumbHeight = ((float)LargeChange / (float)Maximum) * nTrackHeight;279             int nThumbHeight = (int)fThumbHeight;280 281             if (nThumbHeight > nTrackHeight)282             {283                 nThumbHeight = nTrackHeight;284                 fThumbHeight = nTrackHeight;285             }286             if (nThumbHeight < m_intThumbMinHeight)287             {288                 nThumbHeight = m_intThumbMinHeight;289                 fThumbHeight = m_intThumbMinHeight;290             }291             int nTop = moThumbTop;292             nTop += btnHeight;293             e.Graphics.FillPath(new SolidBrush(thumbColor), new Rectangle(1, nTop, this.Width - 3, nThumbHeight).CreateRoundedRectanglePath(this.ConerRadius));294 295             ControlHelper.PaintTriangle(e.Graphics, new SolidBrush(thumbColor), new Point(this.Width / 2, btnHeight - Math.Min(5, this.Width / 2)), Math.Min(5, this.Width / 2), GraphDirection.Upward);296             ControlHelper.PaintTriangle(e.Graphics, new SolidBrush(thumbColor), new Point(this.Width / 2, this.Height - (btnHeight - Math.Min(5, this.Width / 2))), Math.Min(5, this.Width / 2), GraphDirection.Downward);297 298         }299 300         /// <summary>301         /// Initializes the component.302         /// </summary>303         private void InitializeComponent()304         {305             this.SuspendLayout();306             // 307             // UCVScrollbar308             // 309             this.MinimumSize = new System.Drawing.Size(10, 0);310             this.Name = "UCVScrollbar";311             this.Size = new System.Drawing.Size(18, 150);312             this.MouseDown += new System.Windows.Forms.MouseEventHandler(this.CustomScrollbar_MouseDown);313             this.MouseMove += new System.Windows.Forms.MouseEventHandler(this.CustomScrollbar_MouseMove);314             this.MouseUp += new System.Windows.Forms.MouseEventHandler(this.CustomScrollbar_MouseUp);315             this.ResumeLayout(false);316 317         }318 319         /// <summary>320         /// Handles the MouseDown event of the CustomScrollbar control.321         /// </summary>322         /// <param name="sender">The source of the event.</param>323         /// <param name="e">The <see cref="MouseEventArgs"/> instance containing the event data.</param>324         private void CustomScrollbar_MouseDown(object sender, MouseEventArgs e)325         {326             Point ptPoint = this.PointToClient(Cursor.Position);327             int nTrackHeight = (this.Height - btnHeight * 2);328             float fThumbHeight = ((float)LargeChange / (float)Maximum) * nTrackHeight;329             int nThumbHeight = (int)fThumbHeight;330 331             if (nThumbHeight > nTrackHeight)332             {333                 nThumbHeight = nTrackHeight;334                 fThumbHeight = nTrackHeight;335             }336             if (nThumbHeight < m_intThumbMinHeight)337             {338                 nThumbHeight = m_intThumbMinHeight;339                 fThumbHeight = m_intThumbMinHeight;340             }341 342             int nTop = moThumbTop;343             nTop += btnHeight;344 345 346             Rectangle thumbrect = new Rectangle(new Point(1, nTop), new Size(this.Width - 2, nThumbHeight));347             if (thumbrect.Contains(ptPoint))348             {349 350                 //hit the thumb351                 nClickPoint = (ptPoint.Y - nTop);352                 //MessageBox.Show(Convert.ToString((ptPoint.Y - nTop)));353                 this.moThumbDown = true;354             }355 356             Rectangle uparrowrect = new Rectangle(new Point(1, 0), new Size(this.Width, btnHeight));357             if (uparrowrect.Contains(ptPoint))358             {359 360                 int nRealRange = (Maximum - Minimum) - LargeChange;361                 int nPixelRange = (nTrackHeight - nThumbHeight);362                 if (nRealRange > 0)363                 {364                     if (nPixelRange > 0)365                     {366                         if ((moThumbTop - SmallChange) < 0)367                             moThumbTop = 0;368                         else369                             moThumbTop -= SmallChange;370 371                         //figure out value372                         float fPerc = (float)moThumbTop / (float)nPixelRange;373                         float fValue = https://www.cnblogs.com/bfyx/p/fPerc * (Maximum - LargeChange);374 375                         moValue = https://www.cnblogs.com/bfyx/p/(int)fValue;376 377                         if (ValueChanged != null)378                             ValueChanged(this, new EventArgs());379 380                         if (Scroll != null)381                             Scroll(this, new EventArgs());382 383                         Invalidate();384                     }385                 }386             }387 388             Rectangle downarrowrect = new Rectangle(new Point(1, btnHeight + nTrackHeight), new Size(this.Width, btnHeight));389             if (downarrowrect.Contains(ptPoint))390             {391                 int nRealRange = (Maximum - Minimum) - LargeChange;392                 int nPixelRange = (nTrackHeight - nThumbHeight);393                 if (nRealRange > 0)394                 {395                     if (nPixelRange > 0)396                     {397                         if ((moThumbTop + SmallChange) > nPixelRange)398                             moThumbTop = nPixelRange;399                         else400                             moThumbTop += SmallChange;401 402                         //figure out value403                         float fPerc = (float)moThumbTop / (float)nPixelRange;404                         float fValue = https://www.cnblogs.com/bfyx/p/fPerc * (Maximum - LargeChange);405 406                         moValue = https://www.cnblogs.com/bfyx/p/(int)fValue;407 408                         if (ValueChanged != null)409                             ValueChanged(this, new EventArgs());410 411                         if (Scroll != null)412                             Scroll(this, new EventArgs());413 414                         Invalidate();415                     }416                 }417             }418         }419 420         /// <summary>421         /// Handles the MouseUp event of the CustomScrollbar control.422         /// </summary>423         /// <param name="sender">The source of the event.</param>424         /// <param name="e">The <see cref="MouseEventArgs"/> instance containing the event data.</param>425         private void CustomScrollbar_MouseUp(object sender, MouseEventArgs e)426         {427             this.moThumbDown = false;428             this.moThumbDragging = false;429         }430 431         /// <summary>432         /// Moves the thumb.433         /// </summary>434         /// <param name="y">The y.</param>435         private void MoveThumb(int y)436         {437             int nRealRange = Maximum - Minimum;438             int nTrackHeight = (this.Height - btnHeight * 2);439             float fThumbHeight = ((float)LargeChange / (float)Maximum) * nTrackHeight;440             int nThumbHeight = (int)fThumbHeight;441 442             if (nThumbHeight > nTrackHeight)443             {444                 nThumbHeight = nTrackHeight;445                 fThumbHeight = nTrackHeight;446             }447             if (nThumbHeight < m_intThumbMinHeight)448             {449                 nThumbHeight = m_intThumbMinHeight;450                 fThumbHeight = m_intThumbMinHeight;451             }452 453             int nSpot = nClickPoint;454 455             int nPixelRange = (nTrackHeight - nThumbHeight);456             if (moThumbDown && nRealRange > 0)457             {458                 if (nPixelRange > 0)459                 {460                     int nNewThumbTop = y - (btnHeight + nSpot);461 462                     if (nNewThumbTop < 0)463                     {464                         moThumbTop = nNewThumbTop = 0;465                     }466                     else if (nNewThumbTop > nPixelRange)467                     {468                         moThumbTop = nNewThumbTop = nPixelRange;469                     }470                     else471                     {472                         moThumbTop = y - (btnHeight + nSpot);473                     }474 475 476                     float fPerc = (float)moThumbTop / (float)nPixelRange;477                     float fValue = https://www.cnblogs.com/bfyx/p/fPerc * (Maximum - LargeChange);478                     moValue = https://www.cnblogs.com/bfyx/p/(int)fValue;479 480                     Application.DoEvents();481 482                     Invalidate();483                 }484             }485         }486 487         /// <summary>488         /// Handles the MouseMove event of the CustomScrollbar control.489         /// </summary>490         /// <param name="sender">The source of the event.</param>491         /// <param name="e">The <see cref="MouseEventArgs"/> instance containing the event data.</param>492         private void CustomScrollbar_MouseMove(object sender, MouseEventArgs e)493         {494             if (!moThumbDown)495                 return;496 497             if (moThumbDown == true)498             {499                 this.moThumbDragging = true;500             }501 502             if (this.moThumbDragging)503             {504                 MoveThumb(e.Y);505             }506 507             if (ValueChanged != null)508                 ValueChanged(this, new EventArgs());509 510             if (Scroll != null)511                 Scroll(this, new EventArgs());512         }513 514     }515 516     /// <summary>517     /// Class ScrollbarControlDesigner.518     /// Implements the <see cref="System.Windows.Forms.Design.ControlDesigner" />519     /// </summary>520     /// <seealso cref="System.Windows.Forms.Design.ControlDesigner" />521     internal class ScrollbarControlDesigner : System.Windows.Forms.Design.ControlDesigner522     {523         /// <summary>524         /// 獲取指示組件的移動功能的選擇規則,525         /// </summary>526         /// <value>The selection rules.</value>527         public override SelectionRules SelectionRules528         {529             get530             {531                 SelectionRules selectionRules = base.SelectionRules;532                 PropertyDescriptor propDescriptor = TypeDescriptor.GetProperties(this.Component)["AutoSize"];533                 if (propDescriptor != null)534                 {535                     bool autoSize = (bool)propDescriptor.GetValue(this.Component);536                     if (autoSize)537                     {538                         selectionRules = SelectionRules.Visible | SelectionRules.Moveable | SelectionRules.BottomSizeable | SelectionRules.TopSizeable;539                     }540                     else541                     {542                         selectionRules = SelectionRules.Visible | SelectionRules.AllSizeable | SelectionRules.Moveable;543                     }544                 }545                 return selectionRules;546             }547         }548     }549 }
View Code

 

為了方便使用,我們添加一個組件

新增類ScrollbarComponent,繼承 Component, IExtenderProvider

實作介面方法

 1  public bool CanExtend(object extendee) 2         { 3             if (extendee is ScrollableControl) 4             { 5                 ScrollableControl control = (ScrollableControl)extendee; 6                 if (control.AutoScroll == true) 7                 { 8                     return true; 9                 }10             }11             else if (extendee is TreeView)12             {13                 TreeView control = (TreeView)extendee;14                 if (control.Scrollable)15                 {16                     return true;17                 }18             }19             else if (extendee is TextBox)20             {21                 TextBox control = (TextBox)extendee;22                 if (control.Multiline && control.ScrollBars != ScrollBars.None)23                 {24                     return true;25                 }26             }27             return false;28         }

擴展控制元件屬性

 1   [Browsable(true), Category("自定義屬性"), Description("是否使用自定義滾動條"), DisplayName("UserCustomScrollbar"), Localizable(true)] 2         public bool GetUserCustomScrollbar(Control control) 3         { 4             return m_blnUserCustomScrollbar; 5         } 6  7         public void SetUserCustomScrollbar(Control control, bool blnUserCustomScrollbar) 8         { 9             m_blnUserCustomScrollbar = blnUserCustomScrollbar;10             control.VisibleChanged += control_VisibleChanged;11             control.SizeChanged += control_SizeChanged;12             control.LocationChanged += control_LocationChanged;13             control.Disposed += control_Disposed;14             15             if (control is TreeView)16             {17                 TreeView tv = (TreeView)control;18                 tv.MouseWheel += tv_MouseWheel;                19                 tv.AfterSelect += tv_AfterSelect;20                 tv.AfterExpand += tv_AfterExpand;21                 tv.AfterCollapse += tv_AfterCollapse;22             }23             else if (control is TextBox)24             {25                 TextBox txt = (TextBox)control;26                 txt.MouseWheel += txt_MouseWheel;27                 txt.TextChanged += txt_TextChanged;28                29                 txt.KeyDown += txt_KeyDown;30             }31             control_SizeChanged(control, null);32         }33        

處理一下控制元件什么時候添加滾動條,什么時候移除滾動條,以及滾動條位置大小的改變等

  1  void control_Disposed(object sender, EventArgs e)  2         {  3             Control control = (Control)sender;  4             if (m_lstVCache.ContainsKey(control) && m_lstVCache[control].Parent != null)  5             {  6                 m_lstVCache[control].Parent.Controls.Remove(m_lstVCache[control]);  7                 m_lstVCache.Remove(control);  8             }  9         } 10  11         void control_LocationChanged(object sender, EventArgs e) 12         { 13             ResetVScrollLocation(sender); 14         } 15  16         void control_SizeChanged(object sender, EventArgs e) 17         { 18             if (ControlHelper.IsDesignMode()) 19             { 20                 return; 21             } 22             else 23             { 24                 var control = sender as Control; 25  26                 bool blnHasVScrollbar = control.IsHandleCreated && (ControlHelper.GetWindowLong(control.Handle, STYLE) & VSCROLL) != 0; 27                 bool blnHasHScrollbar = control.IsHandleCreated && (ControlHelper.GetWindowLong(control.Handle, STYLE) & HSCROLL) != 0; 28                 if (blnHasVScrollbar) 29                 { 30                     if (!m_lstVCache.ContainsKey(control)) 31                     { 32                         if (control.Parent != null) 33                         { 34                             UCVScrollbar barV = new UCVScrollbar(); 35                             barV.Scroll += barV_Scroll; 36                             m_lstVCache[control] = barV; 37                             if (blnHasHScrollbar) 38                             { 39                                 barV.Height = control.Height - barV.Width - 2; 40                             } 41                             else 42                             { 43                                 barV.Height = control.Height - 2; 44                             } 45                             SetVMaxNum(control); 46                             barV.Location = new System.Drawing.Point(control.Right - barV.Width - 1, control.Top + 1); 47                             control.Parent.Controls.Add(barV); 48                             int intControlIndex = control.Parent.Controls.GetChildIndex(control); 49                             control.Parent.Controls.SetChildIndex(barV, intControlIndex); 50                         } 51                     } 52                     else 53                     { 54                         SetVMaxNum(control); 55                     } 56                 } 57                 else 58                 { 59                     if (m_lstVCache.ContainsKey(control) && m_lstVCache[control].Parent != null) 60                     { 61                         m_lstVCache[control].Parent.Controls.Remove(m_lstVCache[control]); 62                         m_lstVCache.Remove(control); 63                     } 64                 } 65  66                 //if (blnHasHScrollbar) 67                 //{ 68                 //    if (control.Parent != null) 69                 //    { 70  71                 //    } 72                 //} 73                 //else 74                 //{ 75                 //    if (m_lstHCache.ContainsKey(control)) 76                 //    { 77                 //        if (m_lstHCache[control].Visible) 78                 //        { 79                 //            m_lstHCache[control].Parent.Controls.Remove(m_lstHCache[control]); 80                 //        } 81                 //    } 82                 //} 83             } 84             ResetVScrollLocation(sender); 85         } 86  87         private void SetVMaxNum(Control control) 88         { 89             if (!m_lstVCache.ContainsKey(control)) 90                 return; 91             UCVScrollbar barV = m_lstVCache[control]; 92             if (control is ScrollableControl) 93             { 94                 barV.Maximum = (control as ScrollableControl).VerticalScroll.Maximum; 95                 barV.Value = https://www.cnblogs.com/bfyx/p/(control as ScrollableControl).VerticalScroll.Value; 96             } 97             else if (control is TreeView) 98             { 99                 barV.Maximum = GetTreeNodeMaxY(control as TreeView);100                 barV.Value = https://www.cnblogs.com/bfyx/p/(control as TreeView).AutoScrollOffset.Y;101             }102             else if (control is TextBox)103             {104                 TextBox txt = (TextBox)control;105                 int intTxtMaxHeight = 0;106                 int intTextHeight = 0;107                 using (var g = txt.CreateGraphics())108                 {109                     intTxtMaxHeight = (int)g.MeasureString(txt.Text, txt.Font).Height;110                     intTextHeight = (int)g.MeasureString(txt.Text.Substring(0, txt.SelectionStart), txt.Font).Height;111                 }112                 barV.Maximum = intTxtMaxHeight;113                 barV.Value = https://www.cnblogs.com/bfyx/p/(control as TextBox).AutoScrollOffset.Y;114             }115         }116         /// <summary>117         /// Resets the v scroll location.118         /// </summary>119         /// <param name="sender">The sender.</param>120         private void ResetVScrollLocation(object sender)121         {122             Control control = (Control)sender;123             bool blnHasVScrollbar = control.IsHandleCreated && (ControlHelper.GetWindowLong(control.Handle, STYLE) & VSCROLL) != 0;124             bool blnHasHScrollbar = control.IsHandleCreated && (ControlHelper.GetWindowLong(control.Handle, STYLE) & HSCROLL) != 0;125             if (control.Visible)126             {127                 if (m_lstVCache.ContainsKey(control))128                 {129                     m_lstVCache[control].Location = new System.Drawing.Point(control.Right - m_lstVCache[control].Width - 1, control.Top + 1);130                     if (blnHasHScrollbar)131                     {132                         m_lstVCache[control].Height = control.Height - m_lstVCache[control].Width - 2;133                     }134                     else135                     {136                         m_lstVCache[control].Height = control.Height - 2;137                     }138                 }139             }140         }141         /// <summary>142         /// Handles the VisibleChanged event of the control control.143         /// </summary>144         /// <param name="sender">The source of the event.</param>145         /// <param name="e">The <see cref="EventArgs"/> instance containing the event data.</param>146         void control_VisibleChanged(object sender, EventArgs e)147         {148             Control control = (Control)sender;149             if (!control.Visible)150             {151                 if (m_lstVCache.ContainsKey(control) && m_lstVCache[control].Parent != null)152                 {153                     m_lstVCache[control].Parent.Controls.Remove(m_lstVCache[control]);154                     m_lstVCache.Remove(control);155                 }156             }157         }158 159         private const int HSCROLL = 0x100000;160         private const int VSCROLL = 0x200000;161         private const int STYLE = -16;162 163         private Dictionary<Control, UCVScrollbar> m_lstVCache = new Dictionary<Control, UCVScrollbar>();164         //private Dictionary<ScrollableControl, UCVScrollbar> m_lstHCache = new Dictionary<ScrollableControl, UCVScrollbar>();165 166         void barV_Scroll(object sender, EventArgs e)167         {168             UCVScrollbar bar = (UCVScrollbar)sender;169             if (m_lstVCache.ContainsValue(bar))170             {171                 Control c = m_lstVCache.FirstOrDefault(p => p.Value =https://www.cnblogs.com/bfyx/p/= bar).Key;172                 if (c is ScrollableControl)173                 {174                     (c as ScrollableControl).AutoScrollPosition = new Point(0, bar.Value);175                 }176                 else if (c is TreeView)177                 {178                     TreeView tv = (c as TreeView);179                     SetTreeViewScrollLocation(tv, tv.Nodes, bar.Value);180                 }181                 else if (c is TextBox)182                 {183                     TextBox txt = (c as TextBox);184                     SetTextBoxScrollLocation(txt, bar.Value);185                 }186             }187         }188 189         #region Treeview處理    English:Treeview\u5904\u7406190         void tv_AfterCollapse(object sender, TreeViewEventArgs e)191         {192             control_SizeChanged(sender as Control, null);193         }194 195         void tv_AfterExpand(object sender, TreeViewEventArgs e)196         {197             control_SizeChanged(sender as Control, null);198         }199         /// <summary>200         /// Gets the tree node 最大高度201         /// </summary>202         /// <param name="tv">The tv.</param>203         /// <returns>System.Int32.</returns>204         private int GetTreeNodeMaxY(TreeView tv)205         {206             TreeNode tnLast = tv.Nodes[tv.Nodes.Count - 1];207         begin:208             if (tnLast.IsExpanded && tnLast.Nodes.Count > 0)209             {210                 tnLast = tnLast.LastNode;211                 goto begin;212             }213             return tnLast.Bounds.Bottom;214         }215         void tv_AfterSelect(object sender, TreeViewEventArgs e)216         {217             TreeView tv = (TreeView)sender;218             if (m_lstVCache.ContainsKey(tv))219             {220                 m_lstVCache[tv].Value = https://www.cnblogs.com/bfyx/p/tv.Nodes.Count > 0 ? Math.Abs(tv.Nodes[0].Bounds.Top) : 0;221             }222         }223 224         void tv_MouseWheel(object sender, MouseEventArgs e)225         {226             TreeView tv = (TreeView)sender;227             if (m_lstVCache.ContainsKey(tv))228             {229                 m_lstVCache[tv].Value = https://www.cnblogs.com/bfyx/p/tv.Nodes.Count > 0 ? Math.Abs(tv.Nodes[0].Bounds.Top) : 0;230             }231         }232         /// <summary>233         /// Sets the TreeView scroll location.234         /// </summary>235         /// <param name="tv">The tv.</param>236         /// <param name="tns">The TNS.</param>237         /// <param name="intY">The int y.</param>238         /// <returns><c>true</c> if XXXX, <c>false</c> otherwise.</returns>239         private bool SetTreeViewScrollLocation(TreeView tv, TreeNodeCollection tns, int intY)240         {241             for (int i = 0; i < tns.Count; i++)242             {243                 if (intY >= tns[i].Bounds.Top - tv.Nodes[0].Bounds.Top - 3 && intY <= tns[i].Bounds.Bottom - tv.Nodes[0].Bounds.Top + 3)244                 {245                     tns[i].EnsureVisible();                   246                     return true;247                 }248                 else if (tns[i].IsExpanded && tns[i].Nodes.Count > 0)249                 {250                     bool bln = SetTreeViewScrollLocation(tv, tns[i].Nodes, intY);251                     if (bln)252                         return true;253                 }254             }255             return false;256         }257         #endregion258 259         #region TextBox處理    English:TextBox Processing260 261         void txt_TextChanged(object sender, EventArgs e)262         {263             TextBox txt = sender as TextBox;264             control_SizeChanged(txt, null);265             SetVMaxNum(txt);266             if (m_lstVCache.ContainsKey(txt))267             {268                 using (var g = txt.CreateGraphics())269                 {270                     var size = g.MeasureString(txt.Text.Substring(0, txt.SelectionStart), txt.Font);271                     m_lstVCache[txt].Value = https://www.cnblogs.com/bfyx/p/(int)size.Height;272                 }273             }274         }275         private void SetTextBoxScrollLocation(TextBox txt, int intY)276         {277             using (var g = txt.CreateGraphics())278             {279                 for (int i = 0; i < txt.Lines.Length; i++)280                 {281                     string str = string.Join("\n", txt.Lines.Take(i + 1));282                     var size = g.MeasureString(str, txt.Font);283                     if (size.Height >= intY)284                     {285                         txt.SelectionStart = str.Length;286                         txt.ScrollToCaret();287                         return;288                     }289                 }290             }291         }292 293         void txt_KeyDown(object sender, KeyEventArgs e)294         {295             if (e.KeyCode == Keys.Up || e.KeyCode == Keys.Down)296             {297                 TextBox txt = (TextBox)sender;298                 if (m_lstVCache.ContainsKey(txt))299                 {300                     using (var g = txt.CreateGraphics())301                     {302                         var size = g.MeasureString(txt.Text.Substring(0, txt.SelectionStart), txt.Font);303                         m_lstVCache[txt].Value = https://www.cnblogs.com/bfyx/p/(int)size.Height;304                     }305                 }306             }307         }308 309         void txt_MouseWheel(object sender, MouseEventArgs e)310         {311             TextBox txt = (TextBox)sender;312             if (m_lstVCache.ContainsKey(txt))313             {314                 using (var g = txt.CreateGraphics())315                 {316                     StringBuilder str = new StringBuilder();317                     for (int i = 0; i < System.Windows.Forms.SystemInformation.MouseWheelScrollLines; i++)318                     {319                         str.AppendLine("A");320                     }321                     var height = (int)g.MeasureString(str.ToString(), txt.Font).Height;322                     if (e.Delta < 0)323                     {324                         if (height + m_lstVCache[txt].Value > m_lstVCache[txt].Maximum)325                             m_lstVCache[txt].Value =https://www.cnblogs.com/bfyx/p/ m_lstVCache[txt].Maximum;326                         else327                             m_lstVCache[txt].Value += height;328                     }329                     else330                     {331                         if (m_lstVCache[txt].Value - height < 0)332                             m_lstVCache[txt].Value = https://www.cnblogs.com/bfyx/p/0;333                         else334                             m_lstVCache[txt].Value -= height;335                     }336                 }337             }338         }339         #endregion

完整代碼

  1 using System;  2 using System.Collections.Generic;  3 using System.ComponentModel;  4 using System.Drawing;  5 using System.Linq;  6 using System.Text;  7 using System.Windows.Forms;  8   9 namespace HZH_Controls.Controls.ScrollBar 10 { 11     [ProvideProperty("UserCustomScrollbar", typeof(Control))] 12     public class ScrollbarComponent : Component, IExtenderProvider 13     { 14         public ScrollbarComponent() 15         { 16         } 17  18         public ScrollbarComponent(IContainer container) 19         { 20             container.Add(this); 21         } 22         bool m_blnUserCustomScrollbar = true; 23         public bool CanExtend(object extendee) 24         { 25             if (extendee is ScrollableControl) 26             { 27                 ScrollableControl control = (ScrollableControl)extendee; 28                 if (control.AutoScroll == true) 29                 { 30                     return true; 31                 } 32             } 33             else if (extendee is TreeView) 34             { 35                 TreeView control = (TreeView)extendee; 36                 if (control.Scrollable) 37                 { 38                     return true; 39                 } 40             } 41             else if (extendee is TextBox) 42             { 43                 TextBox control = (TextBox)extendee; 44                 if (control.Multiline && control.ScrollBars != ScrollBars.None) 45                 { 46                     return true; 47                 } 48             } 49             return false; 50         } 51  52         [Browsable(true), Category("自定義屬性"), Description("是否使用自定義滾動條"), DisplayName("UserCustomScrollbar"), Localizable(true)] 53         public bool GetUserCustomScrollbar(Control control) 54         { 55             return m_blnUserCustomScrollbar; 56         } 57  58         public void SetUserCustomScrollbar(Control control, bool blnUserCustomScrollbar) 59         { 60             m_blnUserCustomScrollbar = blnUserCustomScrollbar; 61             control.VisibleChanged += control_VisibleChanged; 62             control.SizeChanged += control_SizeChanged; 63             control.LocationChanged += control_LocationChanged; 64             control.Disposed += control_Disposed; 65              66             if (control is TreeView) 67             { 68                 TreeView tv = (TreeView)control; 69                 tv.MouseWheel += tv_MouseWheel;                 70                 tv.AfterSelect += tv_AfterSelect; 71                 tv.AfterExpand += tv_AfterExpand; 72                 tv.AfterCollapse += tv_AfterCollapse; 73             } 74             else if (control is TextBox) 75             { 76                 TextBox txt = (TextBox)control; 77                 txt.MouseWheel += txt_MouseWheel; 78                 txt.TextChanged += txt_TextChanged; 79                 80                 txt.KeyDown += txt_KeyDown; 81             } 82             control_SizeChanged(control, null); 83         } 84         85  86         void control_Disposed(object sender, EventArgs e) 87         { 88             Control control = (Control)sender; 89             if (m_lstVCache.ContainsKey(control) && m_lstVCache[control].Parent != null) 90             { 91                 m_lstVCache[control].Parent.Controls.Remove(m_lstVCache[control]); 92                 m_lstVCache.Remove(control); 93             } 94         } 95  96         void control_LocationChanged(object sender, EventArgs e) 97         { 98             ResetVScrollLocation(sender); 99         }100 101         void control_SizeChanged(object sender, EventArgs e)102         {103             if (ControlHelper.IsDesignMode())104             {105                 return;106             }107             else108             {109                 var control = sender as Control;110 111                 bool blnHasVScrollbar = control.IsHandleCreated && (ControlHelper.GetWindowLong(control.Handle, STYLE) & VSCROLL) != 0;112                 bool blnHasHScrollbar = control.IsHandleCreated && (ControlHelper.GetWindowLong(control.Handle, STYLE) & HSCROLL) != 0;113                 if (blnHasVScrollbar)114                 {115                     if (!m_lstVCache.ContainsKey(control))116                     {117                         if (control.Parent != null)118                         {119                             UCVScrollbar barV = new UCVScrollbar();120                             barV.Scroll += barV_Scroll;121                             m_lstVCache[control] = barV;122                             if (blnHasHScrollbar)123                             {124                                 barV.Height = control.Height - barV.Width - 2;125                             }126                             else127                             {128                                 barV.Height = control.Height - 2;129                             }130                             SetVMaxNum(control);131                             barV.Location = new System.Drawing.Point(control.Right - barV.Width - 1, control.Top + 1);132                             control.Parent.Controls.Add(barV);133                             int intControlIndex = control.Parent.Controls.GetChildIndex(control);134                             control.Parent.Controls.SetChildIndex(barV, intControlIndex);135                         }136                     }137                     else138                     {139                         SetVMaxNum(control);140                     }141                 }142                 else143                 {144                     if (m_lstVCache.ContainsKey(control) && m_lstVCache[control].Parent != null)145                     {146                         m_lstVCache[control].Parent.Controls.Remove(m_lstVCache[control]);147                         m_lstVCache.Remove(control);148                     }149                 }150 151                 //if (blnHasHScrollbar)152                 //{153                 //    if (control.Parent != null)154                 //    {155 156                 //    }157                 //}158                 //else159                 //{160                 //    if (m_lstHCache.ContainsKey(control))161                 //    {162                 //        if (m_lstHCache[control].Visible)163                 //        {164                 //            m_lstHCache[control].Parent.Controls.Remove(m_lstHCache[control]);165                 //        }166                 //    }167                 //}168             }169             ResetVScrollLocation(sender);170         }171 172         private void SetVMaxNum(Control control)173         {174             if (!m_lstVCache.ContainsKey(control))175                 return;176             UCVScrollbar barV = m_lstVCache[control];177             if (control is ScrollableControl)178             {179                 barV.Maximum = (control as ScrollableControl).VerticalScroll.Maximum;180                 barV.Value = https://www.cnblogs.com/bfyx/p/(control as ScrollableControl).VerticalScroll.Value;181             }182             else if (control is TreeView)183             {184                 barV.Maximum = GetTreeNodeMaxY(control as TreeView);185                 barV.Value = https://www.cnblogs.com/bfyx/p/(control as TreeView).AutoScrollOffset.Y;186             }187             else if (control is TextBox)188             {189                 TextBox txt = (TextBox)control;190                 int intTxtMaxHeight = 0;191                 int intTextHeight = 0;192                 using (var g = txt.CreateGraphics())193                 {194                     intTxtMaxHeight = (int)g.MeasureString(txt.Text, txt.Font).Height;195                     intTextHeight = (int)g.MeasureString(txt.Text.Substring(0, txt.SelectionStart), txt.Font).Height;196                 }197                 barV.Maximum = intTxtMaxHeight;198                 barV.Value = https://www.cnblogs.com/bfyx/p/(control as TextBox).AutoScrollOffset.Y;199             }200         }201         /// <summary>202         /// Resets the v scroll location.203         /// </summary>204         /// <param name="sender">The sender.</param>205         private void ResetVScrollLocation(object sender)206         {207             Control control = (Control)sender;208             bool blnHasVScrollbar = control.IsHandleCreated && (ControlHelper.GetWindowLong(control.Handle, STYLE) & VSCROLL) != 0;209             bool blnHasHScrollbar = control.IsHandleCreated && (ControlHelper.GetWindowLong(control.Handle, STYLE) & HSCROLL) != 0;210             if (control.Visible)211             {212                 if (m_lstVCache.ContainsKey(control))213                 {214                     m_lstVCache[control].Location = new System.Drawing.Point(control.Right - m_lstVCache[control].Width - 1, control.Top + 1);215                     if (blnHasHScrollbar)216                     {217                         m_lstVCache[control].Height = control.Height - m_lstVCache[control].Width - 2;218                     }219                     else220                     {221                         m_lstVCache[control].Height = control.Height - 2;222                     }223                 }224             }225         }226         /// <summary>227         /// Handles the VisibleChanged event of the control control.228         /// </summary>229         /// <param name="sender">The source of the event.</param>230         /// <param name="e">The <see cref="EventArgs"/> instance containing the event data.</param>231         void control_VisibleChanged(object sender, EventArgs e)232         {233             Control control = (Control)sender;234             if (!control.Visible)235             {236                 if (m_lstVCache.ContainsKey(control) && m_lstVCache[control].Parent != null)237                 {238                     m_lstVCache[control].Parent.Controls.Remove(m_lstVCache[control]);239                     m_lstVCache.Remove(control);240                 }241             }242         }243 244         private const int HSCROLL = 0x100000;245         private const int VSCROLL = 0x200000;246         private const int STYLE = -16;247 248         private Dictionary<Control, UCVScrollbar> m_lstVCache = new Dictionary<Control, UCVScrollbar>();249         //private Dictionary<ScrollableControl, UCVScrollbar> m_lstHCache = new Dictionary<ScrollableControl, UCVScrollbar>();250 251         void barV_Scroll(object sender, EventArgs e)252         {253             UCVScrollbar bar = (UCVScrollbar)sender;254             if (m_lstVCache.ContainsValue(bar))255             {256                 Control c = m_lstVCache.FirstOrDefault(p => p.Value =https://www.cnblogs.com/bfyx/p/= bar).Key;257                 if (c is ScrollableControl)258                 {259                     (c as ScrollableControl).AutoScrollPosition = new Point(0, bar.Value);260                 }261                 else if (c is TreeView)262                 {263                     TreeView tv = (c as TreeView);264                     SetTreeViewScrollLocation(tv, tv.Nodes, bar.Value);265                 }266                 else if (c is TextBox)267                 {268                     TextBox txt = (c as TextBox);269                     SetTextBoxScrollLocation(txt, bar.Value);270                 }271             }272         }273 274         #region Treeview處理    English:Treeview\u5904\u7406275         void tv_AfterCollapse(object sender, TreeViewEventArgs e)276         {277             control_SizeChanged(sender as Control, null);278         }279 280         void tv_AfterExpand(object sender, TreeViewEventArgs e)281         {282             control_SizeChanged(sender as Control, null);283         }284         /// <summary>285         /// Gets the tree node 最大高度286         /// </summary>287         /// <param name="tv">The tv.</param>288         /// <returns>System.Int32.</returns>289         private int GetTreeNodeMaxY(TreeView tv)290         {291             TreeNode tnLast = tv.Nodes[tv.Nodes.Count - 1];292         begin:293             if (tnLast.IsExpanded && tnLast.Nodes.Count > 0)294             {295                 tnLast = tnLast.LastNode;296                 goto begin;297             }298             return tnLast.Bounds.Bottom;299         }300         void tv_AfterSelect(object sender, TreeViewEventArgs e)301         {302             TreeView tv = (TreeView)sender;303             if (m_lstVCache.ContainsKey(tv))304             {305                 m_lstVCache[tv].Value = https://www.cnblogs.com/bfyx/p/tv.Nodes.Count > 0 ? Math.Abs(tv.Nodes[0].Bounds.Top) : 0;306             }307         }308 309         void tv_MouseWheel(object sender, MouseEventArgs e)310         {311             TreeView tv = (TreeView)sender;312             if (m_lstVCache.ContainsKey(tv))313             {314                 m_lstVCache[tv].Value = https://www.cnblogs.com/bfyx/p/tv.Nodes.Count > 0 ? Math.Abs(tv.Nodes[0].Bounds.Top) : 0;315             }316         }317         /// <summary>318         /// Sets the TreeView scroll location.319         /// </summary>320         /// <param name="tv">The tv.</param>321         /// <param name="tns">The TNS.</param>322         /// <param name="intY">The int y.</param>323         /// <returns><c>true</c> if XXXX, <c>false</c> otherwise.</returns>324         private bool SetTreeViewScrollLocation(TreeView tv, TreeNodeCollection tns, int intY)325         {326             for (int i = 0; i < tns.Count; i++)327             {328                 if (intY >= tns[i].Bounds.Top - tv.Nodes[0].Bounds.Top - 3 && intY <= tns[i].Bounds.Bottom - tv.Nodes[0].Bounds.Top + 3)329                 {330                     tns[i].EnsureVisible();                   331                     return true;332                 }333                 else if (tns[i].IsExpanded && tns[i].Nodes.Count > 0)334                 {335                     bool bln = SetTreeViewScrollLocation(tv, tns[i].Nodes, intY);336                     if (bln)337                         return true;338                 }339             }340             return false;341         }342         #endregion343 344         #region TextBox處理    English:TextBox Processing345 346         void txt_TextChanged(object sender, EventArgs e)347         {348             TextBox txt = sender as TextBox;349             control_SizeChanged(txt, null);350             SetVMaxNum(txt);351             if (m_lstVCache.ContainsKey(txt))352             {353                 using (var g = txt.CreateGraphics())354                 {355                     var size = g.MeasureString(txt.Text.Substring(0, txt.SelectionStart), txt.Font);356                     m_lstVCache[txt].Value = https://www.cnblogs.com/bfyx/p/(int)size.Height;357                 }358             }359         }360         private void SetTextBoxScrollLocation(TextBox txt, int intY)361         {362             using (var g = txt.CreateGraphics())363             {364                 for (int i = 0; i < txt.Lines.Length; i++)365                 {366                     string str = string.Join("\n", txt.Lines.Take(i + 1));367                     var size = g.MeasureString(str, txt.Font);368                     if (size.Height >= intY)369                     {370                         txt.SelectionStart = str.Length;371                         txt.ScrollToCaret();372                         return;373                     }374                 }375             }376         }377 378         void txt_KeyDown(object sender, KeyEventArgs e)379         {380             if (e.KeyCode == Keys.Up || e.KeyCode == Keys.Down)381             {382                 TextBox txt = (TextBox)sender;383                 if (m_lstVCache.ContainsKey(txt))384                 {385                     using (var g = txt.CreateGraphics())386                     {387                         var size = g.MeasureString(txt.Text.Substring(0, txt.SelectionStart), txt.Font);388                         m_lstVCache[txt].Value = https://www.cnblogs.com/bfyx/p/(int)size.Height;389                     }390                 }391             }392         }393 394         void txt_MouseWheel(object sender, MouseEventArgs e)395         {396             TextBox txt = (TextBox)sender;397             if (m_lstVCache.ContainsKey(txt))398             {399                 using (var g = txt.CreateGraphics())400                 {401                     StringBuilder str = new StringBuilder();402                     for (int i = 0; i < System.Windows.Forms.SystemInformation.MouseWheelScrollLines; i++)403                     {404                         str.AppendLine("A");405                     }406                     var height = (int)g.MeasureString(str.ToString(), txt.Font).Height;407                     if (e.Delta < 0)408                     {409                         if (height + m_lstVCache[txt].Value > m_lstVCache[txt].Maximum)410                             m_lstVCache[txt].Value =https://www.cnblogs.com/bfyx/p/ m_lstVCache[txt].Maximum;411                         else412                             m_lstVCache[txt].Value += height;413                     }414                     else415                     {416                         if (m_lstVCache[txt].Value - height < 0)417                             m_lstVCache[txt].Value = https://www.cnblogs.com/bfyx/p/0;418                         else419                             m_lstVCache[txt].Value -= height;420                     }421                 }422             }423         }424         #endregion425     }426 }
View Code

代碼就這些了

 

使用的時候,只需要在界面上添加組件ScrollbarComponent即可

最后的話

如果你喜歡的話,請到 https://gitee.com/kwwwvagaa/net_winform_custom_control 點個星 星吧

轉載請註明出處,本文鏈接:https://www.uj5u.com/net/6451.html

標籤:WinForm

上一篇:Winform中設定ZedGraph的X軸與Y軸的刻度不在對面顯示

下一篇:Winform中設定ZedGraph的字體和間距不隨圖形的縮放而縮放

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • WebAPI簡介

    Web體系結構: 有三個核心:資源(resource),URL(統一資源識別符號)和表示 他們的關系是這樣的:一個資源由一個URL進行標識,HTTP客戶端使用URL定位資源,表示是從資源回傳資料,媒體型別是資源回傳的資料格式。 接下來我們說下HTTP. HTTP協議的系統是一種無狀態的方式,使用請求/ ......

    uj5u.com 2020-09-09 22:07:47 more
  • asp.net core 3.1 入口:Program.cs中的Main函式

    本文分析Program.cs 中Main()函式中代碼的運行順序分析asp.net core程式的啟動,重點不是剖析原始碼,而是理清程式開始時執行的順序。到呼叫了哪些實體,哪些法方。asp.net core 3.1 的程式入口在專案Program.cs檔案里,如下。ususing System; us ......

    uj5u.com 2020-09-09 22:07:49 more
  • asp.net網站作為websocket服務端的應用該如何寫

    最近被websocket的一個問題困擾了很久,有一個需求是在web網站中搭建websocket服務。客戶端通過網頁與服務器建立連接,然后服務器根據ip給客戶端網頁發送資訊。 其實,這個需求并不難,只是剛開始對websocket的內容不太了解。上網搜索了一下,有通過asp.net core 實作的、有 ......

    uj5u.com 2020-09-09 22:08:02 more
  • ASP.NET 開源匯入匯出庫Magicodes.IE Docker中使用

    Magicodes.IE在Docker中使用 更新歷史 2019.02.13 【Nuget】版本更新到2.0.2 【匯入】修復單列匯入的Bug,單元測驗“OneColumnImporter_Test”。問題見(https://github.com/dotnetcore/Magicodes.IE/is ......

    uj5u.com 2020-09-09 22:08:05 more
  • 在webform中使用ajax

    如果你用過Asp.net webform, 說明你也算是.NET 開發的老兵了。WEBform應該是2011 2013左右,當時還用visual studio 2005、 visual studio 2008。后來基本都用的是MVC。 如果是新開發的專案,估計沒人會用webform技術。但是有些舊版 ......

    uj5u.com 2020-09-09 22:08:50 more
  • iis添加asp.net網站,訪問提示:由于擴展配置問題而無法提供您請求的

    今天在iis服務器配置asp.net網站,遇到一個問題,記錄一下: 問題:由于擴展配置問題而無法提供您請求的頁面。如果該頁面是腳本,請添加處理程式。如果應下載檔案,請添加 MIME 映射。 WindowServer2012服務器,添加角色安裝完.netframework和iis之后,運行aspx頁面 ......

    uj5u.com 2020-09-09 22:10:00 more
  • WebAPI-處理架構

    帶著問題去思考,大家好! 問題1:HTTP請求和回傳相應的HTTP回應資訊之間發生了什么? 1:首先是最底層,托管層,位于WebAPI和底層HTTP堆疊之間 2:其次是 訊息處理程式管道層,這里比如日志和快取。OWIN的參考是將訊息處理程式管道的一些功能下移到堆疊下端的OWIN中間件了。 3:控制器處理 ......

    uj5u.com 2020-09-09 22:11:13 more
  • 微信門戶開發框架-使用指導說明書

    微信門戶應用管理系統,采用基于 MVC + Bootstrap + Ajax + Enterprise Library的技術路線,界面層采用Boostrap + Metronic組合的前端框架,資料訪問層支持Oracle、SQLServer、MySQL、PostgreSQL等資料庫。框架以MVC5,... ......

    uj5u.com 2020-09-09 22:15:18 more
  • WebAPI-HTTP編程模型

    帶著問題去思考,大家好!它是什么?它包含什么?它能干什么? 訊息 HTTP編程模型的核心就是訊息抽象,表示為:HttPRequestMessage,HttpResponseMessage.用于客戶端和服務端之間交換請求和回應訊息。 HttpMethod類包含了一組靜態屬性: private stat ......

    uj5u.com 2020-09-09 22:15:23 more
  • 部署WebApi隨筆

    一、跨域 NuGet參考Microsoft.AspNet.WebApi.Cors WebApiConfig.cs中配置: // Web API 配置和服務 config.EnableCors(new EnableCorsAttribute("*", "*", "*")); 二、清除默認回傳XML格式 ......

    uj5u.com 2020-09-09 22:15:48 more
最新发布
  • C#多執行緒學習(二) 如何操縱一個執行緒

    <a href="https://www.cnblogs.com/x-zhi/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/2943582/20220801082530.png" alt="" /></...

    uj5u.com 2023-04-19 09:17:20 more
  • C#多執行緒學習(二) 如何操縱一個執行緒

    C#多執行緒學習(二) 如何操縱一個執行緒 執行緒學習第一篇:C#多執行緒學習(一) 多執行緒的相關概念 下面我們就動手來創建一個執行緒,使用Thread類創建執行緒時,只需提供執行緒入口即可。(執行緒入口使程式知道該讓這個執行緒干什么事) 在C#中,執行緒入口是通過ThreadStart代理(delegate)來提供的 ......

    uj5u.com 2023-04-19 09:16:49 more
  • 記一次 .NET某醫療器械清洗系統 卡死分析

    <a href="https://www.cnblogs.com/huangxincheng/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/214741/20200614104537.png" alt="" /&g...

    uj5u.com 2023-04-18 08:39:04 more
  • 記一次 .NET某醫療器械清洗系統 卡死分析

    一:背景 1. 講故事 前段時間協助訓練營里的一位朋友分析了一個程式卡死的問題,回過頭來看這個案例比較經典,這篇稍微整理一下供后來者少踩坑吧。 二:WinDbg 分析 1. 為什么會卡死 因為是表單程式,理所當然就是看主執行緒此時正在做什么? 可以用 ~0s ; k 看一下便知。 0:000> k # ......

    uj5u.com 2023-04-18 08:33:10 more
  • SignalR, No Connection with that ID,IIS

    <a href="https://www.cnblogs.com/smartstar/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/u36196.jpg" alt="" /></a>...

    uj5u.com 2023-03-30 17:21:52 more
  • 一次對pool的誤用導致的.net頻繁gc的診斷分析

    <a href="https://www.cnblogs.com/dotnet-diagnostic/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/3115652/20230225090434.png" alt=""...

    uj5u.com 2023-03-28 10:15:33 more
  • 一次對pool的誤用導致的.net頻繁gc的診斷分析

    <a href="https://www.cnblogs.com/dotnet-diagnostic/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/3115652/20230225090434.png" alt=""...

    uj5u.com 2023-03-28 10:13:31 more
  • C#遍歷指定檔案夾中所有檔案的3種方法

    <a href="https://www.cnblogs.com/xbhp/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/957602/20230310105611.png" alt="" /></a&...

    uj5u.com 2023-03-27 14:46:55 more
  • C#/VB.NET:如何將PDF轉為PDF/A

    <a href="https://www.cnblogs.com/Carina-baby/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/2859233/20220427162558.png" alt="" />...

    uj5u.com 2023-03-27 14:46:35 more
  • 武裝你的WEBAPI-OData聚合查詢

    <a href="https://www.cnblogs.com/podolski/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/616093/20140323000327.png" alt="" /><...

    uj5u.com 2023-03-27 14:46:16 more