2 // System.Windows.Forms.ScrollBar.cs
4 // Permission is hereby granted, free of charge, to any person obtaining
5 // a copy of this software and associated documentation files (the
6 // "Software"), to deal in the Software without restriction, including
7 // without limitation the rights to use, copy, modify, merge, publish,
8 // distribute, sublicense, and/or sell copies of the Software, and to
9 // permit persons to whom the Software is furnished to do so, subject to
10 // the following conditions:
12 // The above copyright notice and this permission notice shall be
13 // included in all copies or substantial portions of the Software.
15 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 // Copyright (C) 2004, Novell, Inc.
26 // Jordi Mas i Hernandez jordi@ximian.com
31 // $Log: ScrollBar.cs,v $
32 // Revision 1.22 2004/09/28 18:44:25 pbartok
33 // - Streamlined Theme interfaces:
34 // * Each DrawXXX method for a control now is passed the object for the
35 // control to be drawn in order to allow accessing any state the theme
38 // * ControlPaint methods for the theme now have a CP prefix to avoid
39 // name clashes with the Draw methods for controls
41 // * Every control now retrieves it's DefaultSize from the current theme
43 // Revision 1.21 2004/09/17 16:43:27 pbartok
44 // - Fixed behaviour of arrow buttons. Now properly behaves like Buttons (and
45 // like Microsoft's scrollbar arrow buttons)
47 // Revision 1.20 2004/09/17 16:14:36 pbartok
48 // - Added missing release of keyboard/mouse capture
50 // Revision 1.19 2004/09/05 08:03:51 jordi
51 // fixes bugs, adds flashing on certain situations
53 // Revision 1.18 2004/08/31 10:35:04 jordi
54 // adds autorepeat timer, uses a single timer, fixes scrolling bugs, adds new methods
56 // Revision 1.17 2004/08/25 21:35:18 jordi
57 // more fixes to scrollbar
59 // Revision 1.16 2004/08/25 19:20:13 jordi
60 // small bug fix regarding bar position
62 // Revision 1.15 2004/08/24 18:37:02 jordi
63 // fixes formmating, methods signature, and adds missing events
65 // Revision 1.14 2004/08/23 22:53:15 jordi
68 // Revision 1.13 2004/08/23 22:43:46 jordi
69 // *** empty log message ***
71 // Revision 1.11 2004/08/22 19:34:22 jackson
72 // Update the position through the Value property so the OnValueChanged event is raised.
74 // Revision 1.10 2004/08/21 20:22:21 pbartok
75 // - Replaced direct XplatUI calls with their Control counterpart
77 // Revision 1.9 2004/08/20 19:35:33 jackson
78 // Use the SWF timer so callbacks are run in the correct thread
80 // Revision 1.8 2004/08/20 19:34:26 jackson
81 // Use the SWF timer so callbacks are run in the correct thread
83 // Revision 1.7 2004/08/19 22:25:31 jordi
86 // Revision 1.6 2004/08/18 15:56:12 jordi
87 // fixes to scrollbar: steps and multiple timers
89 // Revision 1.5 2004/08/10 19:21:27 jordi
90 // scrollbar enhancements and standarize on win colors defaults
92 // Revision 1.4 2004/08/10 15:41:50 jackson
93 // Allow control to handle buffering
95 // Revision 1.3 2004/07/27 15:29:40 jordi
96 // fixes scrollbar events
98 // Revision 1.2 2004/07/26 17:42:03 jordi
104 using System.Drawing;
105 using System.Drawing.Imaging;
106 using System.Drawing.Drawing2D;
107 using System.ComponentModel;
108 using System.Runtime.InteropServices;
110 namespace System.Windows.Forms
112 [DefaultEvent ("Scroll")]
113 [DefaultProperty ("Value")]
114 public class ScrollBar : Control
116 #region Local Variables
117 private int position;
120 private int large_change;
121 private int small_change;
122 internal int scrollbutton_height;
123 internal int scrollbutton_width;
124 internal Rectangle paint_area = new Rectangle ();
125 private ScrollBars type;
126 private Rectangle first_arrow_area = new Rectangle (); // up or left
127 private Rectangle second_arrow_area = new Rectangle (); // down or right
128 private Rectangle thumb_pos = new Rectangle ();
129 private Rectangle thumb_area = new Rectangle ();
130 internal ButtonState firstbutton_state = ButtonState.Normal;
131 internal ButtonState secondbutton_state = ButtonState.Normal;
132 private bool firstbutton_pressed = false;
133 private bool secondbutton_pressed = false;
134 private bool thumb_pressed = false;
135 private float pixel_per_pos = 0;
136 private Timer timer = new Timer ();
137 private TimerType timer_type;
138 private int thumb_pixel_click_move;
139 private int thumb_pixel_click_move_prev;
140 private int thumb_size = 0;
141 private const int thumb_min_size = 8;
143 private int lastclick_pos; // Position of the last button-down event
144 private int lastclick_pos_thumb; // Position of the last button-down event relative to the thumb
145 private bool outside_thumbarea_right = false;
146 private bool outside_thumbarea_left = false;
147 internal ThumbMoving thumb_moving = ThumbMoving.None;
148 #endregion // Local Variables
150 private enum TimerType
158 internal enum ThumbMoving
166 public new event EventHandler BackColorChanged;
167 public new event EventHandler BackgroundImageChanged;
168 public new event EventHandler Click;
169 public new event EventHandler DoubleClick;
170 public new event EventHandler FontChanged;
171 public new event EventHandler ForeColorChanged;
172 public new event EventHandler ImeModeChanged;
173 public new event MouseEventHandler MouseDown;
174 public new event MouseEventHandler MouseMove;
175 public new event MouseEventHandler MouseUp;
176 public new event PaintEventHandler Paint;
177 public event ScrollEventHandler Scroll;
178 public new event EventHandler TextChanged;
179 public event EventHandler ValueChanged;
190 timer.Tick += new EventHandler (OnTimer);
191 base.KeyDown += new KeyEventHandler (OnKeyDownSB);
192 base.MouseDown += new MouseEventHandler (OnMouseDownSB);
193 base.MouseUp += new MouseEventHandler (OnMouseUpSB);
194 base.MouseMove += new MouseEventHandler (OnMouseMoveSB);
195 base.Resize += new EventHandler (OnResizeSB);
196 base.TabStop = false;
198 if (ThemeEngine.Current.DoubleBufferingSupported == true) {
199 double_buffering = true;
201 double_buffering = false;
204 SetStyle (ControlStyles.UserPaint | ControlStyles.AllPaintingInWmPaint, true);
205 SetStyle (ControlStyles.ResizeRedraw | ControlStyles.Opaque, true);
208 #region Internal & Private Properties
209 internal Rectangle FirstArrowArea {
211 return this.first_arrow_area;
215 this.first_arrow_area = value;
219 internal Rectangle SecondArrowArea {
221 return this.second_arrow_area;
225 this.second_arrow_area = value;
229 internal Rectangle ThumbPos {
238 #endregion // Internal & Private Properties
240 #region Public Properties
242 [EditorBrowsable (EditorBrowsableState.Never)]
243 public override Color BackColor
245 get { return base.BackColor; }
247 if (base.BackColor == value)
250 if (BackColorChanged != null)
251 BackColorChanged (this, EventArgs.Empty);
253 base.BackColor = value;
258 [EditorBrowsable (EditorBrowsableState.Never)]
259 public override Image BackgroundImage
261 get { return base.BackgroundImage; }
263 if (base.BackgroundImage == value)
266 if (BackgroundImageChanged != null)
267 BackgroundImageChanged (this, EventArgs.Empty);
269 base.BackgroundImage = value;
273 protected override CreateParams CreateParams
275 get { return base.CreateParams; }
278 protected override ImeMode DefaultImeMode
280 get { return ImeMode.Disable; }
283 public override Font Font
285 get { return base.Font; }
287 if (base.Font == value)
290 if (FontChanged != null)
291 FontChanged (this, EventArgs.Empty);
297 [EditorBrowsable (EditorBrowsableState.Never)]
298 public override Color ForeColor
300 get { return base.ForeColor; }
302 if (base.ForeColor == value)
305 if (ForeColorChanged != null)
306 ForeColorChanged (this, EventArgs.Empty);
308 base.ForeColor = value;
313 [EditorBrowsable (EditorBrowsableState.Never)]
314 public new ImeMode ImeMode
316 get { return base.ImeMode; }
318 if (base.ImeMode == value)
321 if (ImeModeChanged != null)
322 ImeModeChanged (this, EventArgs.Empty);
324 base.ImeMode = value;
328 public int LargeChange {
329 get { return large_change; }
332 throw new Exception( string.Format("Value '{0}' must be greater than or equal to 0.", value));
334 if (large_change != value) {
335 large_change = value;
342 get { return maximum; }
346 if (maximum < minimum)
354 get { return minimum; }
358 if (minimum > maximum)
365 public int SmallChange {
366 get { return small_change; }
369 throw new Exception( string.Format("Value '{0}' must be greater than or equal to 0.", value));
371 if (small_change != value) {
372 small_change = value;
378 public new bool TabStop {
379 get { return base.TabStop; }
380 set { base.TabStop = value; }
383 [EditorBrowsable (EditorBrowsableState.Never)]
384 public override string Text {
385 get { return base.Text; }
386 set { base.Text = value; }
390 get { return position; }
392 if ( value < minimum || value > maximum )
393 throw new ArgumentException(
394 string.Format("'{0}' is not a valid value for 'Value'. 'Value' should be between 'Minimum' and 'Maximum'", value));
396 if (position != value){
399 if (ValueChanged != null)
400 ValueChanged (this, EventArgs.Empty);
402 UpdatePos (Value, true);
408 #endregion //Public Properties
410 #region Public Methods
412 protected override void OnEnabledChanged (EventArgs e)
414 base.OnEnabledChanged (e);
417 firstbutton_state = secondbutton_state = ButtonState.Normal;
419 firstbutton_state = secondbutton_state = ButtonState.Inactive;
424 protected override void OnHandleCreated (System.EventArgs e)
426 base.OnHandleCreated (e);
428 scrollbutton_height = ThemeEngine.Current.ScrollBarButtonSize;
429 scrollbutton_width = ThemeEngine.Current.ScrollBarButtonSize;
431 CreateBuffers (Width, Height);
434 UpdatePos (Value, true);
437 protected virtual void OnScroll (ScrollEventArgs event_args)
442 Scroll (this, event_args);
445 protected virtual void OnValueChanged (EventArgs e)
447 if (ValueChanged != null)
448 ValueChanged (this, e);
451 public override string ToString()
453 return string.Format("{0}, Minimum: {1}, Maximum: {2}, Value: {3}",
454 GetType( ).FullName.ToString( ), minimum, maximum, position);
457 protected void UpdateScrollInfo ()
462 protected override void WndProc (ref Message m)
468 PaintEventArgs paint_event;
470 paint_event = XplatUI.PaintEventStart (Handle);
471 OnPaintSB (paint_event);
472 XplatUI.PaintEventEnd (Handle);
477 case Msg.WM_ERASEBKGND:
478 m.Result = (IntPtr) 1; /// Disable background painting to avoid flickering
485 base.WndProc (ref m);
488 #endregion //Public Methods
490 #region Private Methods
492 private void CalcThumbArea ()
497 thumb_area.Height = Height - scrollbutton_height - scrollbutton_height;
499 thumb_area.Y = scrollbutton_height;
500 thumb_area.Width = Width;
502 if (Height < scrollbutton_height * 2)
505 double per = ((double) large_change / (double)((1 + maximum - minimum)));
506 thumb_size = 1 + (int) (thumb_area.Height * per);
508 if (thumb_size < thumb_min_size)
509 thumb_size = thumb_min_size;
513 pixel_per_pos = ((float)(thumb_area.Height - thumb_size) / (float) ((maximum - minimum - large_change) + 1));
518 thumb_area.X = scrollbutton_width;
519 thumb_area.Height = Height;
520 thumb_area.Width = Width - scrollbutton_width - scrollbutton_width;
522 if (Width < scrollbutton_width * 2)
525 double per = ((double) large_change / (double)((1 + maximum - minimum)));
526 thumb_size = 1 + (int) (thumb_area.Width * per);
528 if (thumb_size < thumb_min_size)
529 thumb_size = thumb_min_size;
531 pixel_per_pos = ((float)(thumb_area.Width - thumb_size) / (float) ((maximum - minimum - large_change) + 1));
537 ThemeEngine.Current.DrawScrollBar(DeviceContext, this.ClientRectangle, this);
540 private void LargeIncrement ()
542 UpdatePos (position + large_change, true);
545 OnScroll (new ScrollEventArgs (ScrollEventType.LargeIncrement, position));
546 OnScroll (new ScrollEventArgs (ScrollEventType.EndScroll, position));
549 private void LargeDecrement ()
551 UpdatePos (position - large_change, true);
554 OnScroll (new ScrollEventArgs (ScrollEventType.LargeDecrement, position));
555 OnScroll (new ScrollEventArgs (ScrollEventType.EndScroll, position));
558 private void OnResizeSB (Object o, EventArgs e)
560 if (Width <= 0 || Height <= 0)
563 paint_area.X = paint_area. Y = 0;
564 paint_area.Width = Width;
565 paint_area.Height = Height;
567 CreateBuffers (Width, Height);
570 UpdatePos (position, true);
573 private void OnPaintSB (PaintEventArgs pevent)
575 if (Width <= 0 || Height <= 0 || Visible == false)
578 /* Copies memory drawing buffer to screen*/
581 if (double_buffering)
582 pevent.Graphics.DrawImage (ImageBuffer, 0, 0);
586 private void OnTimer (Object source, EventArgs e)
588 switch (timer_type) {
590 case TimerType.HoldButton:
591 SetRepeatButtonTimer ();
594 case TimerType.RepeatButton:
596 if ((firstbutton_state & ButtonState.Pushed) == ButtonState.Pushed)
599 if ((secondbutton_state & ButtonState.Pushed) == ButtonState.Pushed)
605 case TimerType.HoldThumbArea:
606 SetRepeatThumbAreaTimer ();
609 case TimerType.RepeatThumbArea:
612 pnt = PointToClient (MousePosition);
615 lastclick_pos = pnt.Y;
617 lastclick_pos = pnt.X;
619 if (thumb_moving == ThumbMoving.Forward) {
620 if ((vert && (thumb_pos.Y + thumb_size > lastclick_pos)) ||
621 (!vert && (thumb_pos.X + thumb_size > lastclick_pos)) ||
622 (thumb_area.Contains (pnt) == false)){
623 timer.Enabled = false;
624 thumb_moving = ThumbMoving.None;
630 if ((vert && (thumb_pos.Y < lastclick_pos)) ||
631 (!vert && (thumb_pos.X < lastclick_pos))){
632 timer.Enabled = false;
633 thumb_moving = ThumbMoving.None;
646 private void OnMouseMoveSB (object sender, MouseEventArgs e)
648 if (firstbutton_pressed) {
649 if (!first_arrow_area.Contains (e.X, e.Y) && ((firstbutton_state & ButtonState.Pushed) == ButtonState.Pushed)) {
650 firstbutton_state = ButtonState.Normal;
653 } else if (first_arrow_area.Contains (e.X, e.Y) && ((firstbutton_state & ButtonState.Normal) == ButtonState.Normal)) {
654 firstbutton_state = ButtonState.Pushed;
658 } else if (secondbutton_pressed) {
659 if (!second_arrow_area.Contains (e.X, e.Y) && ((secondbutton_state & ButtonState.Pushed) == ButtonState.Pushed)) {
660 secondbutton_state = ButtonState.Normal;
663 } else if (second_arrow_area.Contains (e.X, e.Y) && ((secondbutton_state & ButtonState.Normal) == ButtonState.Normal)) {
664 secondbutton_state = ButtonState.Pushed;
668 } else if (thumb_pressed == true) {
673 int mouse_click = e.Y;
674 int outside_curpos = thumb_area.Y + thumb_area.Height - thumb_size + lastclick_pos_thumb;
677 if (mouse_click > thumb_area.Y + thumb_area.Height) {
678 outside_thumbarea_right = true;
679 mouse_click = thumb_area.Y + thumb_area.Height;
682 if (mouse_click < thumb_area.Y) {
683 outside_thumbarea_left = true;
684 mouse_click = thumb_area.Y;
687 if (outside_thumbarea_right && mouse_click < outside_curpos) {
688 outside_thumbarea_right = false;
689 thumb_pixel_click_move_prev =
690 thumb_pixel_click_move = outside_curpos;
693 if (outside_thumbarea_left && mouse_click > thumb_area.Y + lastclick_pos_thumb) {
694 outside_thumbarea_left = false;
695 thumb_pixel_click_move_prev =
696 thumb_pixel_click_move = thumb_area.Y + lastclick_pos_thumb;
699 if (outside_thumbarea_right == false && outside_thumbarea_left == false) {
700 pixel_pos = thumb_pos.Y + (thumb_pixel_click_move - thumb_pixel_click_move_prev);
701 thumb_pixel_click_move_prev = thumb_pixel_click_move;
702 thumb_pixel_click_move = mouse_click;
703 UpdateThumbPos (pixel_pos, true);
708 int mouse_click = e.X;
709 int outside_curpos = thumb_area.X + thumb_area.Width - thumb_size + lastclick_pos_thumb;
711 if (mouse_click > thumb_area.X + thumb_area.Width) {
712 outside_thumbarea_right = true;
713 mouse_click = thumb_area.X + thumb_area.Width;
716 if (mouse_click < thumb_area.X) {
717 outside_thumbarea_left = true;
718 mouse_click = thumb_area.X;
721 if (outside_thumbarea_right && mouse_click < outside_curpos) {
722 outside_thumbarea_right = false;
723 thumb_pixel_click_move_prev =
724 thumb_pixel_click_move = outside_curpos;
727 if (outside_thumbarea_left && mouse_click > thumb_area.X + lastclick_pos_thumb) {
728 outside_thumbarea_left = false;
729 thumb_pixel_click_move_prev =
730 thumb_pixel_click_move = thumb_area.X + lastclick_pos_thumb;
733 if (outside_thumbarea_right == false && outside_thumbarea_left == false) {
734 pixel_pos = thumb_pos.X + (thumb_pixel_click_move - thumb_pixel_click_move_prev);
735 thumb_pixel_click_move_prev = thumb_pixel_click_move;
736 thumb_pixel_click_move = mouse_click;
737 UpdateThumbPos (pixel_pos, true);
747 private void OnMouseDownSB (object sender, MouseEventArgs e)
749 if (firstbutton_state != ButtonState.Inactive && first_arrow_area.Contains (e.X, e.Y)) {
751 firstbutton_state = ButtonState.Pushed;
752 firstbutton_pressed = true;
756 if (secondbutton_state != ButtonState.Inactive && second_arrow_area.Contains (e.X, e.Y)) {
758 secondbutton_state = ButtonState.Pushed;
759 secondbutton_pressed = true;
763 if (thumb_pos.Contains (e.X, e.Y)) {
764 thumb_pressed = true;
768 lastclick_pos_thumb = e.Y - thumb_pos.Y;
770 thumb_pixel_click_move_prev = thumb_pixel_click_move = e.Y;
773 lastclick_pos_thumb = e.X - thumb_pos.X;
775 thumb_pixel_click_move_prev = thumb_pixel_click_move = e.X;
779 if (thumb_area.Contains (e.X, e.Y)) {
782 lastclick_pos_thumb = e.Y - thumb_pos.Y;
785 if (e.Y > thumb_pos.Y + thumb_pos.Height) {
787 thumb_moving = ThumbMoving.Forward;
791 thumb_moving = ThumbMoving.Backwards;
796 lastclick_pos_thumb = e.X - thumb_pos.X;
799 if (e.X > thumb_pos.X + thumb_pos.Width) {
800 thumb_moving = ThumbMoving.Forward;
804 thumb_moving = ThumbMoving.Backwards;
809 SetHoldThumbAreaTimer ();
810 timer.Enabled = true;
817 /* If arrows are pressed, fire timer for auto-repeat */
818 if ((((firstbutton_state & ButtonState.Pushed) == ButtonState.Pushed)
819 || ((secondbutton_state & ButtonState.Pushed) == ButtonState.Pushed)) &&
820 timer.Enabled == false) {
821 SetHoldButtonClickTimer ();
822 timer.Enabled = true;
826 private void OnMouseUpSB (object sender, MouseEventArgs e)
828 timer.Enabled = false;
830 if (thumb_moving != ThumbMoving.None) {
831 thumb_moving = ThumbMoving.None;
835 this.Capture = false;
837 if (firstbutton_pressed) {
838 firstbutton_state = ButtonState.Normal;
839 if (first_arrow_area.Contains (e.X, e.Y)) {
842 firstbutton_pressed = false;
844 } else if (secondbutton_pressed) {
845 secondbutton_state = ButtonState.Normal;
846 if (second_arrow_area.Contains (e.X, e.Y)) {
849 secondbutton_pressed = false;
851 } else if (thumb_pressed == true) {
852 OnScroll (new ScrollEventArgs (ScrollEventType.ThumbPosition, position));
853 OnScroll (new ScrollEventArgs (ScrollEventType.EndScroll, position));
854 thumb_pressed = false;
859 private void OnKeyDownSB (Object o, KeyEventArgs key)
861 switch (key.KeyCode){
888 private void SmallIncrement ()
890 UpdatePos (position + small_change, true);
893 OnScroll (new ScrollEventArgs (ScrollEventType.SmallIncrement, position));
894 OnScroll (new ScrollEventArgs (ScrollEventType.EndScroll, position));
897 private void SmallDecrement ()
899 UpdatePos (position - small_change, true);
902 OnScroll (new ScrollEventArgs (ScrollEventType.SmallDecrement, position));
903 OnScroll (new ScrollEventArgs (ScrollEventType.EndScroll, position));
906 private void SetHoldButtonClickTimer ()
908 timer.Enabled = false;
909 timer.Interval = 200;
910 timer_type = TimerType.HoldButton;
911 timer.Enabled = true;
914 private void SetRepeatButtonTimer ()
916 timer.Enabled = false;
918 timer_type = TimerType.RepeatButton;
919 timer.Enabled = true;
922 private void SetHoldThumbAreaTimer ()
924 timer.Enabled = false;
925 timer.Interval = 200;
926 timer_type = TimerType.HoldThumbArea;
927 timer.Enabled = true;
930 private void SetRepeatThumbAreaTimer ()
932 timer.Enabled = false;
934 timer_type = TimerType.RepeatThumbArea;
935 timer.Enabled = true;
938 private void UpdatePos (int newPos, bool update_thumbpos)
943 if (newPos < minimum)
946 if (newPos > maximum + 1 - large_change)
947 pos = maximum + 1 - large_change;
951 if (update_thumbpos) {
953 UpdateThumbPos (thumb_area.Y + (int)(((float)(pos - minimum)) * pixel_per_pos), false);
955 UpdateThumbPos (thumb_area.X + (int)(((float)(pos - minimum)) * pixel_per_pos), false);
960 position = pos; // Updates directly the value to avoid thumb pos update
962 if (ValueChanged != null)
963 ValueChanged (this, EventArgs.Empty);
966 if (pos != old) // Fire event
967 OnScroll (new ScrollEventArgs (ScrollEventType.ThumbTrack, pos));
971 private void UpdateThumbPos (int pixel, bool update_value)
976 if (pixel < thumb_area.Y)
977 thumb_pos.Y = thumb_area.Y;
979 if (pixel > thumb_area.Y + thumb_area.Height - thumb_size)
980 thumb_pos.Y = thumb_area.Y + thumb_area.Height - thumb_size;
985 thumb_pos.Width = ThemeEngine.Current.ScrollBarButtonSize;
986 thumb_pos.Height = thumb_size;
987 new_pos = (float) (thumb_pos.Y - thumb_area.Y);
988 new_pos = new_pos / pixel_per_pos;
992 if (pixel < thumb_area.X)
993 thumb_pos.X = thumb_area.X;
995 if (pixel > thumb_area.X + thumb_area.Width - thumb_size)
996 thumb_pos.X = thumb_area.X + thumb_area.Width - thumb_size;
1001 thumb_pos.Width = thumb_size;
1002 thumb_pos.Height = ThemeEngine.Current.ScrollBarButtonSize;
1003 new_pos = (float) (thumb_pos.X - thumb_area.X);
1004 new_pos = new_pos / pixel_per_pos;
1008 UpdatePos ((int) new_pos + minimum, false);
1012 #endregion //Private Methods