1 //
2 // System.Windows.Forms.TrackBar.cs
3 //
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:
11 //
12 // The above copyright notice and this permission notice shall be
13 // included in all copies or substantial portions of the Software.
14 //
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.
22 //
23 //
24 // Copyright (c) 2004-2006 Novell, Inc.
25 //
26 // Authors:
27 //	Jordi Mas i Hernandez, jordi@ximian.com
28 //	Rolf Bjarne Kvinge, RKvinge@novell.com
29 //
30 // TODO:
31 //		- The AutoSize functionality seems quite broken for vertical controls in .Net 1.1. Not
32 //		sure if we are implementing it the right way.
33 //
34 
35 // NOT COMPLETE
36 
37 using System.ComponentModel;
38 using System.ComponentModel.Design;
39 using System.Drawing;
40 using System.Drawing.Imaging;
41 using System.Drawing.Drawing2D;
42 using System.Timers;
43 using System.Runtime.InteropServices;
44 
45 namespace System.Windows.Forms
46 {
47 	[DefaultBindingProperty ("Value")]
48 	[ComVisible (true)]
49 	[ClassInterface (ClassInterfaceType.AutoDispatch)]
50 	[Designer("System.Windows.Forms.Design.TrackBarDesigner, " + Consts.AssemblySystem_Design, "System.ComponentModel.Design.IDesigner")]
51 	[DefaultEvent ("Scroll")]
52 	[DefaultProperty("Value")]
53 	public class TrackBar : Control, ISupportInitialize
54 	{
55 		private int minimum;
56 		private int maximum;
57 		internal int tickFrequency;
58 		private bool autosize;
59 		private int position;
60 		private int smallChange;
61 		private int largeChange;
62 		private Orientation orientation;
63 		private TickStyle tickStyle;
64 		private Rectangle thumb_pos = new Rectangle ();	 /* Current position and size of the thumb */
65 		private Rectangle thumb_area = new Rectangle (); /* Area where the thumb can scroll */
66 		internal bool thumb_pressed = false;
67 		private System.Timers.Timer holdclick_timer = new System.Timers.Timer ();
68 		internal int thumb_mouseclick;
69 		private bool mouse_clickmove;
70 		private bool is_moving_right; // which way the thumb should move when mouse is down (right=up, left=down)
71 		internal int mouse_down_x_offset; // how far from left side of thumb was the mouse clicked.
72 		internal bool mouse_moved; // has the mouse moved since it was clicked?
73 		private const int size_of_autosize = 45;
74 		private bool right_to_left_layout;
75 		bool thumb_entered;
76 
77 		#region events
78 		[EditorBrowsable (EditorBrowsableState.Always)]
79 		[Browsable (true)]
80 		public new event EventHandler AutoSizeChanged {
81 			add {base.AutoSizeChanged += value;}
82 			remove {base.AutoSizeChanged -= value;}
83 		}
84 
85 		[Browsable (false)]
86 		[EditorBrowsable (EditorBrowsableState.Never)]
87 		public new event EventHandler BackgroundImageChanged {
88 			add { base.BackgroundImageChanged += value; }
89 			remove { base.BackgroundImageChanged -= value; }
90 		}
91 
92 		[EditorBrowsable (EditorBrowsableState.Never)]
93 		[Browsable (false)]
94 		public new event EventHandler BackgroundImageLayoutChanged
95 		{
96 			add { base.BackgroundImageLayoutChanged += value; }
97 			remove { base.BackgroundImageLayoutChanged -= value; }
98 		}
99 
100 		[Browsable (false)]
101 		[EditorBrowsable (EditorBrowsableState.Never)]
102 		public new event EventHandler Click {
103 			add { base.Click += value; }
104 			remove { base.Click -= value; }
105 		}
106 
107 		[Browsable (false)]
108 		[EditorBrowsable (EditorBrowsableState.Never)]
109 		public new event EventHandler DoubleClick {
110 			add { base.DoubleClick += value; }
111 			remove { base.DoubleClick -= value; }
112 		}
113 
114 		[Browsable (false)]
115 		[EditorBrowsable (EditorBrowsableState.Never)]
116 		public new event EventHandler FontChanged {
117 			add { base.FontChanged += value; }
118 			remove { base.FontChanged -= value; }
119 		}
120 
121 		[Browsable (false)]
122 		[EditorBrowsable (EditorBrowsableState.Never)]
123 		public new event EventHandler ForeColorChanged {
124 			add { base.ForeColorChanged += value; }
125 			remove { base.ForeColorChanged -= value; }
126 		}
127 
128 		[Browsable (false)]
129 		[EditorBrowsable (EditorBrowsableState.Never)]
130 		public new event EventHandler ImeModeChanged {
131 			add { base.ImeModeChanged += value; }
132 			remove { base.ImeModeChanged -= value; }
133 		}
134 
135 		[Browsable (false)]
136 		[EditorBrowsable (EditorBrowsableState.Never)]
137 		public new event MouseEventHandler MouseClick {
138 			add {base.MouseClick += value;}
139 			remove {base.MouseClick -= value;}
140 		}
141 
142 		[Browsable (false)]
143 		[EditorBrowsable (EditorBrowsableState.Never)]
144 		public new event MouseEventHandler MouseDoubleClick
145 		{
146 			add { base.MouseDoubleClick += value; }
147 			remove { base.MouseDoubleClick -= value; }
148 		}
149 
150 		[Browsable (false)]
151 		[EditorBrowsable (EditorBrowsableState.Never)]
152 		public new event EventHandler PaddingChanged
153 		{
154 			add { base.PaddingChanged += value; }
155 			remove { base.PaddingChanged -= value; }
156 		}
157 
158 		[Browsable (false)]
159 		[EditorBrowsable (EditorBrowsableState.Never)]
160 		public new event PaintEventHandler Paint {
161 			add { base.Paint += value; }
162 			remove { base.Paint -= value; }
163 		}
164 
165 		public event EventHandler RightToLeftLayoutChanged {
166 			add {Events.AddHandler (RightToLeftLayoutChangedEvent, value);}
167 			remove {Events.RemoveHandler (RightToLeftLayoutChangedEvent, value);}
168 		}
169 
170 		[Browsable (false)]
171 		[EditorBrowsable (EditorBrowsableState.Never)]
172 		public new event EventHandler TextChanged {
173 			add { base.TextChanged += value; }
174 			remove { base.TextChanged -= value; }
175 		}
176 
177 		static object RightToLeftLayoutChangedEvent = new object ();
178 		static object ScrollEvent = new object ();
179 		static object ValueChangedEvent = new object ();
180 
181 		public event EventHandler Scroll {
182 			add { Events.AddHandler (ScrollEvent, value); }
183 			remove { Events.RemoveHandler (ScrollEvent, value); }
184 		}
185 
186 		public event EventHandler ValueChanged {
187 			add { Events.AddHandler (ValueChangedEvent, value); }
188 			remove { Events.RemoveHandler (ValueChangedEvent, value); }
189 		}
190 
191 		#endregion // Events
192 
193 		#region UIA FrameWork Events
194 		static object UIAValueParamChangedEvent = new object ();
195 
196 		internal event EventHandler UIAValueParamChanged {
197 			add { Events.AddHandler (UIAValueParamChangedEvent, value); }
198 			remove { Events.RemoveHandler (UIAValueParamChangedEvent, value); }
199 		}
200 
OnUIAValueParamChanged()201 		internal void OnUIAValueParamChanged ()
202 		{
203 			EventHandler eh = (EventHandler) Events [UIAValueParamChangedEvent];
204 			if (eh != null)
205 				eh (this, EventArgs.Empty);
206 		}
207 		#endregion
208 
TrackBar()209 		public TrackBar ()
210 		{
211 			orientation = Orientation.Horizontal;
212 			minimum = 0;
213 			maximum = 10;
214 			tickFrequency = 1;
215 			autosize = true;
216 			position = 0;
217 			tickStyle = TickStyle.BottomRight;
218 			smallChange = 1;
219 			largeChange = 5;
220 			mouse_clickmove = false;
221 			MouseDown += new MouseEventHandler (OnMouseDownTB);
222 			MouseUp += new MouseEventHandler (OnMouseUpTB);
223 			MouseMove += new MouseEventHandler (OnMouseMoveTB);
224 			MouseLeave += new EventHandler (OnMouseLeave);
225 			KeyDown += new KeyEventHandler (OnKeyDownTB);
226 			LostFocus += new EventHandler (OnLostFocusTB);
227 			GotFocus += new EventHandler (OnGotFocusTB);
228 			holdclick_timer.Elapsed += new ElapsedEventHandler (OnFirstClickTimer);
229 
230 			SetStyle (ControlStyles.UserPaint | ControlStyles.Opaque | ControlStyles.UseTextForAccessibility, false);
231 		}
232 
233 		#region Private & Internal Properties
234 		internal Rectangle ThumbPos {
235 			get {
236 				return thumb_pos;
237 			}
238 
239 			set {
240 				thumb_pos = value;
241 			}
242 		}
243 
244 		internal Rectangle ThumbArea {
245 			get {
246 				return thumb_area;
247 			}
248 
249 			set {
250 				thumb_area = value;
251 			}
252 		}
253 
254 		internal bool ThumbEntered {
255 			get { return thumb_entered; }
256 			set {
257 				if (thumb_entered == value)
258 					return;
259 				thumb_entered = value;
260 				if (ThemeEngine.Current.TrackBarHasHotThumbStyle)
261 					Invalidate (GetRealThumbRectangle ());
262 			}
263 		}
264 		#endregion	// Private & Internal Properties
265 
266 		#region Public Properties
267 
268 		[Browsable (true)]
269 		[EditorBrowsable (EditorBrowsableState.Always)]
270 		[DesignerSerializationVisibility (DesignerSerializationVisibility.Visible)]
271 		[DefaultValue (true)]
272 		public override bool AutoSize {
273 			get { return autosize; }
274 			set { autosize = value;}
275 		}
276 
277 		[EditorBrowsable (EditorBrowsableState.Never)]
278 		[Browsable (false)]
279 		public override Image BackgroundImage {
280 			get { return base.BackgroundImage; }
281 			set { base.BackgroundImage = value; }
282 		}
283 
284 		[EditorBrowsable (EditorBrowsableState.Never)]
285 		[Browsable (false)]
286 		public override ImageLayout BackgroundImageLayout {
287 			get {
288 				return base.BackgroundImageLayout;
289 			}
290 			set {
291 				base.BackgroundImageLayout = value;
292 			}
293 		}
294 
295 		protected override CreateParams CreateParams {
296 			get {
297 				return base.CreateParams;
298 			}
299 		}
300 
301 		protected override ImeMode DefaultImeMode {
302 			get {return ImeMode.Disable; }
303 		}
304 
305 		protected override Size DefaultSize {
306 			get { return ThemeEngine.Current.TrackBarDefaultSize; }
307 		}
308 
309 		[EditorBrowsable (EditorBrowsableState.Never)]
310 		protected override bool DoubleBuffered {
311 			get {
312 				return base.DoubleBuffered;
313 			}
314 			set {
315 				base.DoubleBuffered = value;
316 			}
317 		}
318 
319 		[Browsable(false)]
320 		[EditorBrowsable (EditorBrowsableState.Never)]
321 		public override Font Font {
322 			get { return base.Font;	}
323 			set { base.Font = value; }
324 		}
325 
326 		[EditorBrowsable (EditorBrowsableState.Never)]
327 		[Browsable (false)]
328 		public override Color ForeColor {
329 			get { return base.ForeColor; }
330 			set { base.ForeColor = value; }
331 		}
332 
333 		[EditorBrowsable (EditorBrowsableState.Never)]
334 		[Browsable (false)]
335 		public new ImeMode ImeMode {
336 			get { return base.ImeMode; }
337 			set { base.ImeMode = value; }
338 		}
339 
340 		[DefaultValue (5)]
341 		public int LargeChange
342 		{
343 			get { return largeChange; }
344 			set {
345 				if (value < 0)
346 					throw new ArgumentOutOfRangeException (string.Format ("Value '{0}' must be greater than or equal to 0.", value));
347 
348 				largeChange = value;
349 
350 				OnUIAValueParamChanged ();
351 			}
352 		}
353 
354 		[DefaultValue (10)]
355 		[RefreshProperties (RefreshProperties.All)]
356 		public int Maximum {
357 			get { return maximum; }
358 			set {
359 				if (maximum != value)  {
360 					maximum = value;
361 
362 					if (maximum < minimum)
363 						minimum = maximum;
364 
365 					Refresh ();
366 
367 					OnUIAValueParamChanged ();
368 				}
369 			}
370 		}
371 
372 		[DefaultValue (0)]
373 		[RefreshProperties (RefreshProperties.All)]
374 		public int Minimum {
375 			get { return minimum; }
376 			set {
377 
378 				if (Minimum != value) {
379 					minimum = value;
380 
381 					if (minimum > maximum)
382 						maximum = minimum;
383 
384 					Refresh ();
385 
386 					OnUIAValueParamChanged ();
387 				}
388 			}
389 		}
390 
391 		[DefaultValue (Orientation.Horizontal)]
392 		[Localizable (true)]
393 		public Orientation Orientation {
394 			get { return orientation; }
395 			set {
396 				if (!Enum.IsDefined (typeof (Orientation), value))
397 					throw new InvalidEnumArgumentException (string.Format("Enum argument value '{0}' is not valid for Orientation", value));
398 
399 				/* Orientation can be changed once the control has been created */
400 				if (orientation != value) {
401 					orientation = value;
402 
403 					if (this.IsHandleCreated) {
404 						Size = new Size (Height, Width);
405 						Refresh ();
406 					}
407 				}
408 			}
409 		}
410 
411 		[Browsable (false)]
412 		[DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
413 		[EditorBrowsable (EditorBrowsableState.Never)]
414 		public new Padding Padding {
415 			get {
416 				return base.Padding;
417 			}
418 			set {
419 				base.Padding = value;
420 			}
421 		}
422 
423 		[Localizable (true)]
424 		[DefaultValue (false)]
425 		public virtual bool RightToLeftLayout {
426 			get {
427 				return right_to_left_layout;
428 			}
429 			set {
430 				if (value != right_to_left_layout) {
431 					right_to_left_layout = value;
432 					OnRightToLeftLayoutChanged (EventArgs.Empty);
433 				}
434 			}
435 		}
436 
437 		[DefaultValue (1)]
438 		public int SmallChange {
439 			get { return smallChange;}
440 			set {
441 				if (value < 0)
442 					throw new ArgumentOutOfRangeException (string.Format ("Value '{0}' must be greater than or equal to 0.", value));
443 
444 				if (smallChange != value) {
445 					smallChange = value;
446 
447 					OnUIAValueParamChanged ();
448 				}
449 			}
450 		}
451 
452 		[EditorBrowsable (EditorBrowsableState.Never)]
453 		[Bindable (false)]
454 		[Browsable (false)]
455 		public override string Text {
456 			get {	return base.Text; }
457 			set { base.Text = value; }
458 		}
459 
460 		[DefaultValue (1)]
461 		public int TickFrequency {
462 			get { return tickFrequency; }
463 			set {
464 				if ( value > 0 ) {
465 					tickFrequency = value;
466 					Refresh ();
467 				}
468 			}
469 		}
470 
471 		[DefaultValue (TickStyle.BottomRight)]
472 		public TickStyle TickStyle {
473 			get { return tickStyle; }
474 			set {
475 				if (!Enum.IsDefined (typeof (TickStyle), value))
476 					throw new InvalidEnumArgumentException (string.Format("Enum argument value '{0}' is not valid for TickStyle", value));
477 
478 				if (tickStyle != value) {
479 					tickStyle = value;
480 					Refresh ();
481 				}
482 			}
483 		}
484 
485 		[DefaultValue (0)]
486 		[Bindable (true)]
487 		public int Value {
488 			get { return position; }
489 			set {
490 				SetValue (value, false);
491 			}
492 		}
493 
SetValue(int value, bool fire_onscroll)494 		void SetValue (int value, bool fire_onscroll)
495 		{
496 			if (value < Minimum || value > Maximum)
497 				throw new ArgumentException(
498 						String.Format ("'{0}' is not a valid value for 'Value'. 'Value' should be between 'Minimum' and 'Maximum'", value));
499 
500 			if (position == value)
501 				return;
502 
503 			position = value;
504 
505 			// OnScroll goes before OnValueChanged
506 			if (fire_onscroll)
507 				OnScroll (EventArgs.Empty);
508 
509 			// XXX any reason we don't call OnValueChanged here?
510 			EventHandler eh = (EventHandler)(Events [ValueChangedEvent]);
511 			if (eh != null)
512 				eh (this, EventArgs.Empty);
513 
514 			Invalidate (thumb_area);
515 		}
516 
517 		#endregion //Public Properties
518 
519 		#region Public Methods
520 
BeginInit()521 		public void BeginInit ()
522 		{
523 
524 		}
525 
CreateHandle()526 		protected override void CreateHandle ()
527 		{
528 			base.CreateHandle ();
529 		}
530 
SetBoundsCore(int x, int y,int width, int height, BoundsSpecified specified)531 		protected override void SetBoundsCore (int x, int y,int width, int height, BoundsSpecified specified)
532 		{
533 			if (AutoSize) {
534 				if (orientation == Orientation.Vertical) {
535 					width = size_of_autosize;
536 				} else {
537 					height = size_of_autosize;
538 				}
539 			}
540 			base.SetBoundsCore (x, y, width, height, specified);
541 		}
542 
EndInit()543 		public void EndInit ()
544 		{
545 
546 		}
547 
IsInputKey(Keys keyData)548 		protected override bool IsInputKey (Keys keyData)
549 		{
550 			if ((keyData & Keys.Alt) == 0) {
551 				switch (keyData & Keys.KeyCode) {
552 				case Keys.Down:
553 				case Keys.Right:
554 				case Keys.Up:
555 				case Keys.Left:
556 				case Keys.PageUp:
557 				case Keys.PageDown:
558 				case Keys.Home:
559 				case Keys.End:
560 					return true;
561 				}
562 			}
563 			return base.IsInputKey (keyData);
564 		}
565 
OnBackColorChanged(EventArgs e)566 		protected override void OnBackColorChanged (EventArgs e)
567 		{
568 			base.OnBackColorChanged (e);
569 		}
570 
OnHandleCreated(EventArgs e)571 		protected override void OnHandleCreated (EventArgs e)
572 		{
573 			base.OnHandleCreated (e);
574 
575 			if (AutoSize)
576 				if (Orientation == Orientation.Horizontal)
577 					Size = new Size (Width, 40);
578 				else
579 					Size = new Size (50, Height);
580 
581 			UpdatePos (Value, true);
582 		}
583 
584 		[EditorBrowsable (EditorBrowsableState.Advanced)]
OnMouseWheel(MouseEventArgs e)585 		protected override void OnMouseWheel (MouseEventArgs e)
586 		{
587 			base.OnMouseWheel (e);
588 
589 			if (!Enabled) return;
590 
591 			if (e.Delta > 0)
592 				SmallDecrement ();
593 			else
594 				SmallIncrement ();
595 		}
596 
597 		[EditorBrowsable (EditorBrowsableState.Advanced)]
OnRightToLeftLayoutChanged(EventArgs e)598 		protected virtual void OnRightToLeftLayoutChanged (EventArgs e)
599 		{
600 			EventHandler eh = (EventHandler)Events [RightToLeftLayoutChangedEvent];
601 			if (eh != null)
602 				eh (this, e);
603 		}
604 
OnScroll(EventArgs e)605 		protected virtual void OnScroll (EventArgs e)
606 		{
607 			EventHandler eh = (EventHandler)(Events [ScrollEvent]);
608 			if (eh != null)
609 				eh (this, e);
610 		}
611 
OnSystemColorsChanged(EventArgs e)612 		protected override void OnSystemColorsChanged (EventArgs e)
613 		{
614 			base.OnSystemColorsChanged (e);
615 			Invalidate ();
616 		}
617 
OnValueChanged(EventArgs e)618 		protected virtual void OnValueChanged (EventArgs e)
619 		{
620 			EventHandler eh = (EventHandler)(Events [ValueChangedEvent]);
621 			if (eh != null)
622 				eh (this, e);
623 		}
624 
SetRange(int minValue, int maxValue)625 		public void SetRange (int minValue, int maxValue)
626 		{
627 			Minimum = minValue;
628 			Maximum = maxValue;
629 		}
630 
ToString()631 		public override string ToString()
632 		{
633 			return string.Format("System.Windows.Forms.TrackBar, Minimum: {0}, Maximum: {1}, Value: {2}",
634 						Minimum, Maximum, Value);
635 		}
636 
637 
WndProc(ref Message m)638 		protected override void WndProc (ref Message m)
639     		{
640 			base.WndProc (ref m);
641 
642 			// Basically we want ControlStyles.ResizeRedraw but
643 			// tests say we can't set that flag
644 			if ((Msg)m.Msg == Msg.WM_WINDOWPOSCHANGED && Visible)
645 				Invalidate ();
646     		}
647 
648 		#endregion Public Methods
649 
650 		#region Private Methods
651 
UpdatePos(int newPos, bool update_trumbpos)652 		private void UpdatePos (int newPos, bool update_trumbpos)
653 		{
654 			if (newPos < minimum){
655 				SetValue (minimum, true);
656 			}
657 			else {
658 				if (newPos > maximum) {
659 					SetValue (maximum, true);
660 				}
661 				else {
662 					SetValue (newPos, true);
663 				}
664 			}
665 		}
666 
667 			// Used by UIA implementation, so making internal
LargeIncrement()668 		internal void LargeIncrement ()
669     		{
670 			UpdatePos (position + LargeChange, true);
671 			Invalidate (thumb_area);
672     		}
673 
674 			// Used by UIA implementation, so making internal
LargeDecrement()675     		internal void LargeDecrement ()
676     		{
677 			UpdatePos (position - LargeChange, true);
678 			Invalidate (thumb_area);
679     		}
680 
SmallIncrement()681 		private void SmallIncrement ()
682     		{
683 			UpdatePos (position + SmallChange, true);
684 			Invalidate (thumb_area);
685     		}
686 
SmallDecrement()687     		private void SmallDecrement ()
688     		{
689 			UpdatePos (position - SmallChange, true);
690 			Invalidate (thumb_area);
691     		}
692 
OnMouseUpTB(object sender, MouseEventArgs e)693 		private void OnMouseUpTB (object sender, MouseEventArgs e)
694 		{
695 			if (!Enabled) return;
696 
697 			if (thumb_pressed == true || mouse_clickmove == true) {
698 				thumb_pressed = false;
699 				holdclick_timer.Enabled = false;
700 				this.Capture = false;
701 				Invalidate (thumb_area);
702 			}
703 		}
704 
OnMouseDownTB(object sender, MouseEventArgs e)705 		private void OnMouseDownTB (object sender, MouseEventArgs e)
706     		{
707     			if (!Enabled) return;
708 
709 			mouse_moved = false;
710 
711 			bool fire_timer = false;
712 
713     			Point point = new Point (e.X, e.Y);
714 
715 			if (orientation == Orientation.Horizontal) {
716 
717 				if (thumb_pos.Contains (point)) {
718 					this.Capture = true;
719 					thumb_pressed = true;
720 					thumb_mouseclick = e.X;
721 					mouse_down_x_offset = e.X - thumb_pos.X;
722 					Invalidate (thumb_area);
723 				}
724 				else {
725 					if (thumb_area.Contains (point)) {
726 						is_moving_right = e.X > thumb_pos.X + thumb_pos.Width;
727 						if (is_moving_right)
728 							LargeIncrement ();
729 						else
730 							LargeDecrement ();
731 
732 						Invalidate (thumb_area);
733 						fire_timer = true;
734 						mouse_clickmove = true;
735 					}
736 				}
737 			}
738 			else {
739 				Rectangle vertical_thumb_pos = thumb_pos;
740 				vertical_thumb_pos.Width = thumb_pos.Height;
741 				vertical_thumb_pos.Height = thumb_pos.Width;
742 				if (vertical_thumb_pos.Contains (point)) {
743 					this.Capture = true;
744 					thumb_pressed = true;
745 					thumb_mouseclick = e.Y;
746 					mouse_down_x_offset = e.Y - thumb_pos.Y;
747 					Invalidate (thumb_area);
748 				}
749 				else {
750 					if (thumb_area.Contains (point)) {
751 						is_moving_right = e.Y > thumb_pos.Y + thumb_pos.Width;
752 						if (is_moving_right)
753 							LargeDecrement ();
754 						else
755 							LargeIncrement ();
756 
757 						Invalidate (thumb_area);
758 						fire_timer = true;
759 						mouse_clickmove = true;
760 					}
761 				}
762 			}
763 
764 			if (fire_timer) {
765 				holdclick_timer.Interval = 300;
766 				holdclick_timer.Enabled = true;
767 			}
768     		}
769 
OnMouseMoveTB(object sender, MouseEventArgs e)770     		private void OnMouseMoveTB (object sender, MouseEventArgs e)
771     		{
772     			if (!Enabled) return;
773 
774     			mouse_moved = true;
775 
776     			/* Moving the thumb */
777     			if (thumb_pressed)
778 				SetValue (ThemeEngine.Current.TrackBarValueFromMousePosition (e.X, e.Y, this), true);
779 
780 			ThumbEntered = GetRealThumbRectangle ().Contains (e.Location);
781     		}
782 
GetRealThumbRectangle()783 		Rectangle GetRealThumbRectangle ()
784 		{
785 			Rectangle result = thumb_pos;
786 			if (Orientation == Orientation.Vertical) {
787 				result.Width = thumb_pos.Height;
788 				result.Height = thumb_pos.Width;
789 			}
790 			return result;
791 		}
792 
OnPaintInternal(PaintEventArgs pevent)793 		internal override void OnPaintInternal (PaintEventArgs pevent)
794 		{
795 			ThemeEngine.Current.DrawTrackBar (pevent.Graphics, pevent.ClipRectangle, this);
796 		}
797 
OnLostFocusTB(object sender, EventArgs e)798 		private void OnLostFocusTB (object sender, EventArgs e)
799 		{
800 			Invalidate();
801 		}
802 
OnGotFocusTB(object sender, EventArgs e)803 		private void OnGotFocusTB (object sender, EventArgs e)
804 		{
805 			Invalidate();
806 		}
OnKeyDownTB(object sender, KeyEventArgs e)807 		private void OnKeyDownTB (object sender, KeyEventArgs e)
808 		{
809 			bool horiz = Orientation == Orientation.Horizontal;
810 			switch (e.KeyCode) {
811 
812 			case Keys.Down:
813 			case Keys.Right:
814 				if(horiz)
815 					SmallIncrement();
816 				else
817 					SmallDecrement ();
818 				break;
819 
820 			case Keys.Up:
821 			case Keys.Left:
822 				if (horiz)
823 					SmallDecrement();
824 				else
825 					SmallIncrement();
826 				break;
827 
828 			case Keys.PageUp:
829 				if (horiz)
830 					LargeDecrement();
831 				else
832 					LargeIncrement();
833 				break;
834 
835 			case Keys.PageDown:
836 				if (horiz)
837 					LargeIncrement();
838 				else
839 					LargeDecrement();
840 				break;
841 
842 			case Keys.Home:
843 				if (horiz)
844 					SetValue (Minimum, true);
845 				else
846 					SetValue (Maximum, true);
847 				break;
848 
849 			case Keys.End:
850 				if (horiz)
851 					SetValue (Maximum, true);
852 				else
853 					SetValue (Minimum, true);
854 				break;
855 
856 			default:
857 				break;
858 			}
859 		}
860 
OnFirstClickTimer(Object source, ElapsedEventArgs e)861 		private void OnFirstClickTimer (Object source, ElapsedEventArgs e)
862 		{
863 			Point pnt;
864 			pnt = PointToClient (MousePosition);
865 			/*
866 				On Win32 the thumb only moves in one direction after a click,
867 				if the thumb passes the clicked point it will never go in the
868 				other way unless the mouse is released and clicked again. This
869 				is also true if the mouse moves while beeing hold down.
870 			*/
871 
872 			if (thumb_area.Contains (pnt)) 	{
873 				bool invalidate = false;
874 				if (orientation == Orientation.Horizontal) {
875 					if (pnt.X > thumb_pos.X + thumb_pos.Width && is_moving_right) {
876 						LargeIncrement ();
877 						invalidate = true;
878 					} else if (pnt.X < thumb_pos.X && !is_moving_right) {
879 						LargeDecrement ();
880 						invalidate = true;
881 					}
882 				} else {
883 					if (pnt.Y > thumb_pos.Y + thumb_pos.Width && is_moving_right) {
884 						LargeDecrement ();
885 						invalidate = true;
886 					} else if (pnt.Y < thumb_pos.Y && !is_moving_right) {
887 						LargeIncrement ();
888 						invalidate = true;
889 					}
890  				}
891  				if (invalidate)
892  					// A Refresh is necessary because the mouse is down and if we just invalidate
893  					// we'll only get paint events once in a while.
894  					Refresh();
895 			}
896 		}
897 
OnMouseLeave(object sender, EventArgs e)898 		void OnMouseLeave (object sender, EventArgs e)
899 		{
900 			ThumbEntered = false;
901 		}
902     		#endregion // Private Methods
903 	}
904 }
905 
906