当前位置: 移动技术网 > IT编程>开发语言>.net > (六十九)c#Winform自定义控件-垂直滚动条

(六十九)c#Winform自定义控件-垂直滚动条

2019年09月19日  | 移动技术网IT编程  | 我要评论

爱情万岁蔡明亮,心之彼端2攻略,卡秀网

前提

入行已经7,8年了,一直想做一套漂亮点的自定义控件,于是就有了本系列文章。

github:https://github.com/kwwwvagaa/netwinformcontrol

码云:

如果觉得写的还行,请点个 star 支持一下吧

欢迎前来交流探讨: 企鹅群568015492 

麻烦博客下方点个【推荐】,谢谢

nuget

install-package hzh_controls

目录

用处及效果

 

 

 

 目前支持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 = 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 minimum
104         {
105             get { return mominimum; }
106             set
107             {
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 maximum
119         {
120             get { return momaximum; }
121             set
122             {
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 value
134         {
135             get { return movalue; }
136             set
137             {
138                 movalue = 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 value
156                 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 autosize
178         {
179             get
180             {
181                 return base.autosize;
182             }
183             set
184             {
185                 base.autosize = value;
186                 if (base.autosize)
187                 {
188                     this.width = 15;
189                 }
190             }
191         }
192 
193         /// <summary>
194         /// the thumb color
195         /// </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 thumbcolor
203         {
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 = fperc * (maximum - largechange);
 56 
 57                         movalue = (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 = fperc * (maximum - largechange);
 87 
 88                         movalue = (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                     else
153                     {
154                         mothumbtop = y - (btnheight + nspot);
155                     }
156 
157 
158                     float fperc = (float)mothumbtop / (float)npixelrange;
159                     float fvalue = fperc * (maximum - largechange);
160                     movalue = (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:623128629@qq.com
  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 = 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 btnheight
102         {
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 largechange
112         {
113             get { return molargechange; }
114             set
115             {
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 smallchange
127         {
128             get { return mosmallchange; }
129             set
130             {
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 minimum
142         {
143             get { return mominimum; }
144             set
145             {
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 maximum
157         {
158             get { return momaximum; }
159             set
160             {
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 value
172         {
173             get { return movalue; }
174             set
175             {
176                 movalue = 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 value
194                 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 autosize
216         {
217             get
218             {
219                 return base.autosize;
220             }
221             set
222             {
223                 base.autosize = value;
224                 if (base.autosize)
225                 {
226                     this.width = 15;
227                 }
228             }
229         }
230 
231         /// <summary>
232         /// the thumb color
233         /// </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 thumbcolor
241         {
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 thumb
277             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             // ucvscrollbar
308             // 
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 thumb
351                 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                         else
369                             mothumbtop -= smallchange;
370 
371                         //figure out value
372                         float fperc = (float)mothumbtop / (float)npixelrange;
373                         float fvalue = fperc * (maximum - largechange);
374 
375                         movalue = (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                         else
400                             mothumbtop += smallchange;
401 
402                         //figure out value
403                         float fperc = (float)mothumbtop / (float)npixelrange;
404                         float fvalue = fperc * (maximum - largechange);
405 
406                         movalue = (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                     else
471                     {
472                         mothumbtop = y - (btnheight + nspot);
473                     }
474 
475 
476                     float fperc = (float)mothumbtop / (float)npixelrange;
477                     float fvalue = fperc * (maximum - largechange);
478                     movalue = (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.controldesigner
522     {
523         /// <summary>
524         /// 获取指示组件的移动功能的选择规则。
525         /// </summary>
526         /// <value>the selection rules.</value>
527         public override selectionrules selectionrules
528         {
529             get
530             {
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                     else
541                     {
542                         selectionrules = selectionrules.visible | selectionrules.allsizeable | selectionrules.moveable;
543                     }
544                 }
545                 return selectionrules;
546             }
547         }
548     }
549 }

 

为了方便使用,我们添加一个组件

新增类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 = (control as scrollablecontrol).verticalscroll.value;
 96             }
 97             else if (control is treeview)
 98             {
 99                 barv.maximum = gettreenodemaxy(control as treeview);
100                 barv.value = (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 = (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                     else
135                     {
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 == 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\u7406
190         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 = 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 = 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         #endregion
258 
259         #region textbox处理    english:textbox processing
260 
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 = (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 = (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 = m_lstvcache[txt].maximum;
326                         else
327                             m_lstvcache[txt].value += height;
328                     }
329                     else
330                     {
331                         if (m_lstvcache[txt].value - height < 0)
332                             m_lstvcache[txt].value = 0;
333                         else
334                             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             else
108             {
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                             else
127                             {
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                     else
138                     {
139                         setvmaxnum(control);
140                     }
141                 }
142                 else
143                 {
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                 //else
159                 //{
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 = (control as scrollablecontrol).verticalscroll.value;
181             }
182             else if (control is treeview)
183             {
184                 barv.maximum = gettreenodemaxy(control as treeview);
185                 barv.value = (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 = (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                     else
220                     {
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 == 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\u7406
275         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 = 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 = 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         #endregion
343 
344         #region textbox处理    english:textbox processing
345 
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 = (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 = (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 = m_lstvcache[txt].maximum;
411                         else
412                             m_lstvcache[txt].value += height;
413                     }
414                     else
415                     {
416                         if (m_lstvcache[txt].value - height < 0)
417                             m_lstvcache[txt].value = 0;
418                         else
419                             m_lstvcache[txt].value -= height;
420                     }
421                 }
422             }
423         }
424         #endregion
425     }
426 }

代码就这些了

 

使用的时候,只需要在界面上添加组件scrollbarcomponent即可

最后的话

如果你喜欢的话,请到  点个星 星吧

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网