2 // System.Windows.Forms.TrackBar.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.
24 // Jordi Mas i Hernandez, jordi@ximian.com
27 // - The AutoSize functionality seems quite broken for vertical controls in .Net 1.1. Not
28 // sure if we are implementing it the right way.
30 // Copyright (C) Novell Inc., 2004
35 // $Log: TrackBar.cs,v $
36 // Revision 1.15 2004/10/05 04:56:12 jackson
37 // Let the base Control handle the buffers, derived classes should not have to CreateBuffers themselves.
39 // Revision 1.14 2004/09/28 18:44:25 pbartok
40 // - Streamlined Theme interfaces:
41 // * Each DrawXXX method for a control now is passed the object for the
42 // control to be drawn in order to allow accessing any state the theme
45 // * ControlPaint methods for the theme now have a CP prefix to avoid
46 // name clashes with the Draw methods for controls
48 // * Every control now retrieves it's DefaultSize from the current theme
50 // Revision 1.13 2004/08/23 20:10:03 jordi
51 // fixes properties and methods
53 // Revision 1.12 2004/08/21 20:21:48 pbartok
54 // - Replaced direct XplatUI calls with their Control counterpart
56 // Revision 1.11 2004/08/20 19:45:50 jordi
57 // fixes timer, new properties and methods
59 // Revision 1.10 2004/08/13 20:55:20 jordi
60 // change from wndproc to events
62 // Revision 1.9 2004/08/13 18:46:26 jordi
63 // adds timer and grap window
65 // Revision 1.8 2004/08/12 20:29:01 jordi
66 // Trackbar enhancement, fix mouse problems, highli thumb, etc
68 // Revision 1.7 2004/08/10 23:27:12 jordi
69 // add missing methods, properties, and restructure to hide extra ones
71 // Revision 1.6 2004/08/10 15:47:11 jackson
72 // Allow control to handle buffering
74 // Revision 1.5 2004/08/07 23:32:26 jordi
75 // throw exceptions of invalid enums values
77 // Revision 1.4 2004/08/06 23:18:06 pbartok
78 // - Fixed some rounding issues with float/int
80 // Revision 1.3 2004/07/27 15:53:02 jordi
81 // fixes trackbar events, def classname, methods signature
83 // Revision 1.2 2004/07/26 17:42:03 jordi
86 // Revision 1.1 2004/07/15 09:38:02 jordi
87 // Horizontal and Vertical TrackBar control implementation
93 using System
.ComponentModel
;
95 using System
.Drawing
.Imaging
;
96 using System
.Drawing
.Drawing2D
;
99 namespace System
.Windows
.Forms
102 [DefaultEvent ("Scroll")]
103 public class TrackBar
: Control
, ISupportInitialize
107 internal int tickFrequency
;
108 private bool autosize
;
109 private int position
;
110 private int smallChange
;
111 private int largeChange
;
112 private Orientation orientation
;
113 private TickStyle tickStyle
;
114 internal Rectangle paint_area
= new Rectangle ();
115 private Rectangle thumb_pos
= new Rectangle (); /* Current position and size of the thumb */
116 private Rectangle thumb_area
= new Rectangle (); /* Area where the thumb can scroll */
117 internal bool thumb_pressed
= false;
118 private System
.Timers
.Timer holdclick_timer
= new System
.Timers
.Timer ();
119 internal int thumb_mouseclick
;
120 private bool mouse_clickmove
;
123 public event EventHandler Scroll
;
124 public event EventHandler ValueChanged
;
125 public new event EventHandler ImeModeChanged
;
126 public new event EventHandler ForeColorChanged
;
127 public new event EventHandler TextChanged
;
128 public new event EventHandler BackgroundImageChanged
;
133 orientation
= Orientation
.Horizontal
;
139 tickStyle
= TickStyle
.BottomRight
;
144 mouse_clickmove
= false;
145 SizeChanged
+= new System
.EventHandler (OnResizeTB
);
146 MouseDown
+= new MouseEventHandler (OnMouseDownTB
);
147 MouseUp
+= new MouseEventHandler (OnMouseUpTB
);
148 MouseMove
+= new MouseEventHandler (OnMouseMoveTB
);
149 holdclick_timer
.Elapsed
+= new ElapsedEventHandler (OnFirstClickTimer
);
151 SetStyle (ControlStyles
.UserPaint
| ControlStyles
.AllPaintingInWmPaint
, true);
152 SetStyle (ControlStyles
.ResizeRedraw
| ControlStyles
.Opaque
, true);
155 #region Private & Internal Properties
156 internal Rectangle ThumbPos
{
166 internal Rectangle ThumbArea
{
175 #endregion // Private & Internal Properties
177 #region Public Properties
179 [DefaultValue (true)]
180 public bool AutoSize
{
181 get { return autosize; }
182 set { autosize = value;}
185 [EditorBrowsable (EditorBrowsableState
.Never
)]
186 public override Image BackgroundImage
{
187 get { return base.BackgroundImage; }
189 if (base.BackgroundImage
== value)
192 if (BackgroundImageChanged
!= null)
193 BackgroundImageChanged (this, EventArgs
.Empty
);
195 base.BackgroundImage
= value;
199 protected override CreateParams CreateParams
{
201 CreateParams createParams
= base.CreateParams
;
202 createParams
.ClassName
= XplatUI
.DefaultClassName
;
204 createParams
.Style
= (int) (
205 WindowStyles
.WS_CHILD
|
206 WindowStyles
.WS_VISIBLE
);
212 protected override ImeMode DefaultImeMode
{
213 get {return ImeMode.Disable; }
216 protected override Size DefaultSize
{
217 get { return ThemeEngine.Current.TrackBarDefaultSize; }
220 [EditorBrowsable (EditorBrowsableState
.Never
)]
221 public override Font Font
{
222 get { return base.Font; }
223 set { base.Font = value; }
226 [EditorBrowsable (EditorBrowsableState
.Never
)]
227 public override Color ForeColor
{
228 get { return base.ForeColor; }
230 if (value == base.ForeColor
)
233 if (ForeColorChanged
!= null)
234 ForeColorChanged (this, EventArgs
.Empty
);
240 [EditorBrowsable (EditorBrowsableState
.Never
)]
241 public new ImeMode ImeMode
{
242 get { return base.ImeMode; }
244 if (value == base.ImeMode
)
247 base.ImeMode
= value;
248 if (ImeModeChanged
!= null)
249 ImeModeChanged (this, EventArgs
.Empty
);
254 public int LargeChange
256 get { return largeChange; }
259 throw new Exception( string.Format("Value '{0}' must be greater than or equal to 0.", value));
267 [RefreshProperties (RefreshProperties
.All
)]
269 get { return maximum; }
271 if (maximum
!= value) {
274 if (maximum
< minimum
)
283 [RefreshProperties (RefreshProperties
.All
)]
285 get { return minimum; }
288 if (Minimum
!= value) {
291 if (minimum
> maximum
)
299 [DefaultValue (Orientation
.Horizontal
)]
301 public Orientation Orientation
{
302 get { return orientation; }
304 if (!Enum
.IsDefined (typeof (Orientation
), value))
305 throw new InvalidEnumArgumentException (string.Format("Enum argument value '{0}' is not valid for Orientation", value));
307 /* Orientation can be changed once the control has been created */
308 if (orientation
!= value) {
311 int old_witdh
= Width
;
320 public int SmallChange
{
321 get { return smallChange;}
324 throw new Exception( string.Format("Value '{0}' must be greater than or equal to 0.", value));
326 if (smallChange
!= value) {
333 [EditorBrowsable (EditorBrowsableState
.Never
)]
335 public override string Text
{
336 get { return base.Text; }
338 if (value == base.Text
)
341 if (TextChanged
!= null)
342 TextChanged (this, EventArgs
.Empty
);
349 public int TickFrequency
{
350 get { return tickFrequency; }
353 tickFrequency
= value;
359 [DefaultValue (TickStyle
.BottomRight
)]
360 public TickStyle TickStyle
{
361 get { return tickStyle; }
363 if (!Enum
.IsDefined (typeof (TickStyle
), value))
364 throw new InvalidEnumArgumentException (string.Format("Enum argument value '{0}' is not valid for TickStyle", value));
366 if (tickStyle
!= value) {
376 get { return position; }
378 if (value < Minimum
|| value > Maximum
)
379 throw new ArgumentException(
380 string.Format("'{0}' is not a valid value for 'Value'. 'Value' should be between 'Minimum' and 'Maximum'", value));
382 if (position
!= value) {
385 if (ValueChanged
!= null)
386 ValueChanged (this, new EventArgs ());
393 #endregion //Public Properties
395 #region Public Methods
397 public virtual void BeginInit ()
402 protected override void CreateHandle ()
404 base.CreateHandle ();
408 public virtual void EndInit ()
413 protected override bool IsInputKey (Keys keyData
)
418 protected override void OnBackColorChanged (EventArgs e
)
423 protected override void OnHandleCreated (EventArgs e
)
426 if (Orientation
== Orientation
.Horizontal
)
427 Size
= new Size (Width
, 40);
429 Size
= new Size (50, Height
);
432 UpdatePos (Value
, true);
435 [EditorBrowsable (EditorBrowsableState
.Advanced
)]
436 protected override void OnMouseWheel (MouseEventArgs e
)
438 if (!Enabled
) return;
445 base.OnMouseWheel (e
);
449 protected virtual void OnScroll (EventArgs e
)
455 protected virtual void OnValueChanged (EventArgs e
)
457 if (ValueChanged
!= null)
458 ValueChanged (this, e
);
461 public void SetRange (int minValue
, int maxValue
)
469 public override string ToString()
471 return string.Format("System.Windows.Forms.Trackbar, Minimum: {0}, Maximum: {1}, Value: {2}",
472 Minimum
, Maximum
, Value
);
476 protected override void WndProc (ref Message m
)
478 switch ((Msg
) m
.Msg
) {
481 PaintEventArgs paint_event
;
483 paint_event
= XplatUI
.PaintEventStart (Handle
);
484 OnPaintTB (paint_event
);
485 XplatUI
.PaintEventEnd (Handle
);
490 OnKeyDownTB (new KeyEventArgs ((Keys
)m
.WParam
.ToInt32 ()));
493 case Msg
.WM_ERASEBKGND
:
494 m
.Result
= (IntPtr
) 1; /* Disable background painting to avoid flickering */
501 base.WndProc (ref m
);
504 #endregion Public Methods
506 #region Private Methods
508 private void UpdateArea ()
510 paint_area
.X
= paint_area
.Y
= 0;
511 paint_area
.Width
= Width
;
512 paint_area
.Height
= Height
;
515 private void UpdatePos (int newPos
, bool update_trumbpos
)
519 if (newPos
< minimum
)
522 if (newPos
> maximum
)
528 private void LargeIncrement ()
530 UpdatePos (position
+ LargeChange
, true);
532 OnScroll (new EventArgs ());
535 private void LargeDecrement ()
537 UpdatePos (position
- LargeChange
, true);
539 OnScroll (new EventArgs ());
542 private void SmallIncrement ()
544 UpdatePos (position
+ SmallChange
, true);
546 OnScroll (new EventArgs ());
549 private void SmallDecrement ()
551 UpdatePos (position
- SmallChange
, true);
553 OnScroll (new EventArgs ());
558 float ticks
= (Maximum
- Minimum
) / tickFrequency
; /* N of ticks draw*/
560 ThemeEngine
.Current
.DrawTrackBar(DeviceContext
, this.ClientRectangle
, this);
563 private void OnMouseUpTB (object sender
, MouseEventArgs e
)
565 if (!Enabled
) return;
567 if (thumb_pressed
== true || mouse_clickmove
== true) {
568 thumb_pressed
= false;
569 holdclick_timer
.Enabled
= false;
570 this.Capture
= false;
575 private void OnMouseDownTB (object sender
, MouseEventArgs e
)
577 if (!Enabled
) return;
579 bool fire_timer
= false;
581 Point point
= new Point (e
.X
, e
.Y
);
583 if (orientation
== Orientation
.Horizontal
) {
585 if (thumb_pos
.Contains (point
)) {
587 thumb_pressed
= true;
588 thumb_mouseclick
= e
.X
;
592 if (paint_area
.Contains (point
)) {
593 if (e
.X
> thumb_pos
.X
+ thumb_pos
.Width
)
600 mouse_clickmove
= true;
605 if (thumb_pos
.Contains (point
)) {
607 thumb_pressed
= true;
608 thumb_mouseclick
= e
.Y
;
613 if (paint_area
.Contains (point
)) {
614 if (e
.Y
> thumb_pos
.Y
+ thumb_pos
.Height
)
621 mouse_clickmove
= true;
627 holdclick_timer
.Interval
= 300;
628 holdclick_timer
.Enabled
= true;
632 private void OnMouseMoveTB (object sender
, MouseEventArgs e
)
634 if (!Enabled
) return;
636 Point pnt
= new Point (e
.X
, e
.Y
);
638 /* Moving the thumb */
641 if (orientation
== Orientation
.Horizontal
){
642 if (paint_area
.Contains (e
.X
, thumb_pos
.Y
))
643 thumb_mouseclick
= e
.X
;
646 if (paint_area
.Contains (thumb_pos
.X
, e
.Y
))
647 thumb_mouseclick
= e
.Y
;
651 OnScroll (new EventArgs ());
655 private void OnResizeTB (object sender
, System
.EventArgs e
)
657 if (Width
<= 0 || Height
<= 0)
663 private void OnPaintTB (PaintEventArgs pevent
)
665 if (Width
<= 0 || Height
<= 0 || Visible
== false)
668 /* Copies memory drawing buffer to screen*/
671 pevent
.Graphics
.DrawImage (ImageBuffer
, 0, 0);
674 private void OnKeyDownTB (KeyEventArgs e
)
692 private void OnFirstClickTimer (Object source
, ElapsedEventArgs e
)
695 pnt
= PointToClient (MousePosition
);
697 if (thumb_area
.Contains (pnt
)) {
698 if (orientation
== Orientation
.Horizontal
) {
699 if (pnt
.X
> thumb_pos
.X
+ thumb_pos
.Width
)
702 if (pnt
.X
< thumb_pos
.X
)
706 if (pnt
.Y
> thumb_pos
.Y
+ thumb_pos
.Height
)
709 if (pnt
.Y
< thumb_pos
.Y
)
718 protected override void SetBoundsCore (int x
, int y
,int width
, int height
, BoundsSpecified specified
)
720 base.SetBoundsCore (x
, y
,width
, height
, specified
);
724 #endregion // Private Methods