TrackBar.cs 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699
  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. // Autors:
  24. // Jordi Mas i Hernandez, [email protected]
  25. //
  26. // TODO:
  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.
  29. //
  30. // Copyright (C) Novell Inc., 2004
  31. //
  32. //
  33. // $Revision: 1.13 $
  34. // $Modtime: $
  35. // $Log: TrackBar.cs,v $
  36. // Revision 1.13 2004/08/23 20:10:03 jordi
  37. // fixes properties and methods
  38. //
  39. // Revision 1.12 2004/08/21 20:21:48 pbartok
  40. // - Replaced direct XplatUI calls with their Control counterpart
  41. //
  42. // Revision 1.11 2004/08/20 19:45:50 jordi
  43. // fixes timer, new properties and methods
  44. //
  45. // Revision 1.10 2004/08/13 20:55:20 jordi
  46. // change from wndproc to events
  47. //
  48. // Revision 1.9 2004/08/13 18:46:26 jordi
  49. // adds timer and grap window
  50. //
  51. // Revision 1.8 2004/08/12 20:29:01 jordi
  52. // Trackbar enhancement, fix mouse problems, highli thumb, etc
  53. //
  54. // Revision 1.7 2004/08/10 23:27:12 jordi
  55. // add missing methods, properties, and restructure to hide extra ones
  56. //
  57. // Revision 1.6 2004/08/10 15:47:11 jackson
  58. // Allow control to handle buffering
  59. //
  60. // Revision 1.5 2004/08/07 23:32:26 jordi
  61. // throw exceptions of invalid enums values
  62. //
  63. // Revision 1.4 2004/08/06 23:18:06 pbartok
  64. // - Fixed some rounding issues with float/int
  65. //
  66. // Revision 1.3 2004/07/27 15:53:02 jordi
  67. // fixes trackbar events, def classname, methods signature
  68. //
  69. // Revision 1.2 2004/07/26 17:42:03 jordi
  70. // Theme support
  71. //
  72. // Revision 1.1 2004/07/15 09:38:02 jordi
  73. // Horizontal and Vertical TrackBar control implementation
  74. //
  75. //
  76. // NOT COMPLETE
  77. using System.ComponentModel;
  78. using System.Drawing;
  79. using System.Drawing.Imaging;
  80. using System.Drawing.Drawing2D;
  81. using System.Timers;
  82. namespace System.Windows.Forms
  83. {
  84. [DefaultEvent ("Scroll")]
  85. public class TrackBar : Control, ISupportInitialize
  86. {
  87. private int minimum;
  88. private int maximum;
  89. private int tickFrequency;
  90. private bool autosize;
  91. private int position;
  92. private int smallChange;
  93. private int largeChange;
  94. private Orientation orientation;
  95. private TickStyle tickStyle;
  96. private Rectangle paint_area = new Rectangle ();
  97. private Rectangle thumb_pos = new Rectangle (); /* Current position and size of the thumb */
  98. private Rectangle thumb_area = new Rectangle (); /* Area where the thumb can scroll */
  99. private bool thumb_pressed = false;
  100. private System.Timers.Timer holdclick_timer = new System.Timers.Timer ();
  101. private int thumb_mouseclick;
  102. private bool mouse_clickmove;
  103. #region Events
  104. public event EventHandler Scroll;
  105. public event EventHandler ValueChanged;
  106. public new event EventHandler ImeModeChanged;
  107. public new event EventHandler ForeColorChanged;
  108. public new event EventHandler TextChanged;
  109. public new event EventHandler BackgroundImageChanged;
  110. #endregion // Events
  111. public TrackBar ()
  112. {
  113. orientation = Orientation.Horizontal;
  114. minimum = 0;
  115. maximum = 10;
  116. tickFrequency = 1;
  117. autosize = true;
  118. position = 0;
  119. tickStyle = TickStyle.BottomRight;
  120. smallChange = 1;
  121. largeChange = 5;
  122. Scroll = null;
  123. ValueChanged = null;
  124. mouse_clickmove = false;
  125. SizeChanged += new System.EventHandler (OnResizeTB);
  126. MouseDown += new MouseEventHandler (OnMouseDownTB);
  127. MouseUp += new MouseEventHandler (OnMouseUpTB);
  128. MouseMove += new MouseEventHandler (OnMouseMoveTB);
  129. holdclick_timer.Elapsed += new ElapsedEventHandler (OnFirstClickTimer);
  130. SetStyle (ControlStyles.UserPaint | ControlStyles.AllPaintingInWmPaint, true);
  131. SetStyle (ControlStyles.ResizeRedraw | ControlStyles.Opaque, true);
  132. }
  133. #region Public Properties
  134. [DefaultValue (true)]
  135. public bool AutoSize {
  136. get { return autosize; }
  137. set { autosize = value;}
  138. }
  139. [EditorBrowsable (EditorBrowsableState.Never)]
  140. public override Image BackgroundImage {
  141. get { return base.BackgroundImage; }
  142. set {
  143. if (base.BackgroundImage == value)
  144. return;
  145. if (BackgroundImageChanged != null)
  146. BackgroundImageChanged (this, EventArgs.Empty);
  147. base.BackgroundImage = value;
  148. }
  149. }
  150. protected override CreateParams CreateParams {
  151. get {
  152. CreateParams createParams = base.CreateParams;
  153. createParams.ClassName = XplatUI.DefaultClassName;
  154. createParams.Style = (int) (
  155. WindowStyles.WS_CHILD |
  156. WindowStyles.WS_VISIBLE);
  157. return createParams;
  158. }
  159. }
  160. protected override ImeMode DefaultImeMode {
  161. get {return ImeMode.Disable; }
  162. }
  163. protected override Size DefaultSize {
  164. get { return new System.Drawing.Size (104, 42); }
  165. }
  166. [EditorBrowsable (EditorBrowsableState.Never)]
  167. public override Font Font {
  168. get { return base.Font; }
  169. set { base.Font = value; }
  170. }
  171. [EditorBrowsable (EditorBrowsableState.Never)]
  172. public override Color ForeColor {
  173. get { return base.ForeColor; }
  174. set {
  175. if (value == base.ForeColor)
  176. return;
  177. if (ForeColorChanged != null)
  178. ForeColorChanged (this, EventArgs.Empty);
  179. Refresh ();
  180. }
  181. }
  182. [EditorBrowsable (EditorBrowsableState.Never)]
  183. public new ImeMode ImeMode {
  184. get { return base.ImeMode; }
  185. set {
  186. if (value == base.ImeMode)
  187. return;
  188. base.ImeMode = value;
  189. if (ImeModeChanged != null)
  190. ImeModeChanged (this, EventArgs.Empty);
  191. }
  192. }
  193. [DefaultValue (5)]
  194. public int LargeChange
  195. {
  196. get { return largeChange; }
  197. set {
  198. if (value < 0)
  199. throw new Exception( string.Format("Value '{0}' must be greater than or equal to 0.", value));
  200. largeChange = value;
  201. Refresh ();
  202. }
  203. }
  204. [DefaultValue (10)]
  205. [RefreshProperties (RefreshProperties.All)]
  206. public int Maximum {
  207. get { return maximum; }
  208. set {
  209. if (maximum != value) {
  210. maximum = value;
  211. if (maximum < minimum)
  212. minimum = maximum;
  213. Refresh ();
  214. }
  215. }
  216. }
  217. [DefaultValue (0)]
  218. [RefreshProperties (RefreshProperties.All)]
  219. public int Minimum {
  220. get { return minimum; }
  221. set {
  222. if (Minimum != value) {
  223. minimum = value;
  224. if (minimum > maximum)
  225. maximum = minimum;
  226. Refresh ();
  227. }
  228. }
  229. }
  230. [DefaultValue (Orientation.Horizontal)]
  231. [Localizable (true)]
  232. public Orientation Orientation {
  233. get { return orientation; }
  234. set {
  235. if (!Enum.IsDefined (typeof (Orientation), value))
  236. throw new InvalidEnumArgumentException (string.Format("Enum argument value '{0}' is not valid for Orientation", value));
  237. /* Orientation can be changed once the control has been created */
  238. if (orientation != value) {
  239. orientation = value;
  240. int old_witdh = Width;
  241. Width = Height;
  242. Height = old_witdh;
  243. Refresh ();
  244. }
  245. }
  246. }
  247. [DefaultValue (1)]
  248. public int SmallChange {
  249. get { return smallChange;}
  250. set {
  251. if ( value < 0 )
  252. throw new Exception( string.Format("Value '{0}' must be greater than or equal to 0.", value));
  253. if (smallChange != value) {
  254. smallChange = value;
  255. Refresh ();
  256. }
  257. }
  258. }
  259. [EditorBrowsable (EditorBrowsableState.Never)]
  260. [Bindable (false)]
  261. public override string Text {
  262. get { return base.Text; }
  263. set {
  264. if (value == base.Text)
  265. return;
  266. if (TextChanged != null)
  267. TextChanged (this, EventArgs.Empty);
  268. Refresh ();
  269. }
  270. }
  271. [DefaultValue (1)]
  272. public int TickFrequency {
  273. get { return tickFrequency; }
  274. set {
  275. if ( value > 0 ) {
  276. tickFrequency = value;
  277. Refresh ();
  278. }
  279. }
  280. }
  281. [DefaultValue (TickStyle.BottomRight)]
  282. public TickStyle TickStyle {
  283. get { return tickStyle; }
  284. set {
  285. if (!Enum.IsDefined (typeof (TickStyle), value))
  286. throw new InvalidEnumArgumentException (string.Format("Enum argument value '{0}' is not valid for TickStyle", value));
  287. if (tickStyle != value) {
  288. tickStyle = value;
  289. Refresh ();
  290. }
  291. }
  292. }
  293. [DefaultValue (0)]
  294. [Bindable (false)]
  295. public int Value {
  296. get { return position; }
  297. set {
  298. if (value < Minimum || value > Maximum)
  299. throw new ArgumentException(
  300. string.Format("'{0}' is not a valid value for 'Value'. 'Value' should be between 'Minimum' and 'Maximum'", value));
  301. if (position != value) {
  302. position = value;
  303. if (ValueChanged != null)
  304. ValueChanged (this, new EventArgs ());
  305. Refresh ();
  306. }
  307. }
  308. }
  309. #endregion //Public Properties
  310. #region Public Methods
  311. public virtual void BeginInit ()
  312. {
  313. }
  314. protected override void CreateHandle ()
  315. {
  316. base.CreateHandle ();
  317. }
  318. public virtual void EndInit ()
  319. {
  320. }
  321. protected override bool IsInputKey (Keys keyData)
  322. {
  323. return false;
  324. }
  325. protected override void OnBackColorChanged (EventArgs e)
  326. {
  327. }
  328. protected override void OnHandleCreated (EventArgs e)
  329. {
  330. if (AutoSize)
  331. if (Orientation == Orientation.Horizontal)
  332. Size = new Size (Width, 40);
  333. else
  334. Size = new Size (50, Height);
  335. UpdateArea ();
  336. CreateBuffers (Width, Height);
  337. UpdatePos (Value, true);
  338. }
  339. [EditorBrowsable (EditorBrowsableState.Advanced)]
  340. protected override void OnMouseWheel (MouseEventArgs e)
  341. {
  342. if (!Enabled) return;
  343. if (e.Delta > 0)
  344. SmallDecrement ();
  345. else
  346. SmallIncrement ();
  347. base.OnMouseWheel (e);
  348. }
  349. protected virtual void OnScroll (EventArgs e)
  350. {
  351. if (Scroll != null)
  352. Scroll (this, e);
  353. }
  354. protected virtual void OnValueChanged (EventArgs e)
  355. {
  356. if (ValueChanged != null)
  357. ValueChanged (this, e);
  358. }
  359. public void SetRange (int minValue, int maxValue)
  360. {
  361. Minimum = minValue;
  362. Maximum = maxValue;
  363. Refresh ();
  364. }
  365. public override string ToString()
  366. {
  367. return string.Format("System.Windows.Forms.Trackbar, Minimum: {0}, Maximum: {1}, Value: {2}",
  368. Minimum, Maximum, Value);
  369. }
  370. protected override void WndProc (ref Message m)
  371. {
  372. switch ((Msg) m.Msg) {
  373. case Msg.WM_PAINT: {
  374. PaintEventArgs paint_event;
  375. paint_event = XplatUI.PaintEventStart (Handle);
  376. OnPaintTB (paint_event);
  377. XplatUI.PaintEventEnd (Handle);
  378. return;
  379. }
  380. case Msg.WM_KEYDOWN:
  381. OnKeyDownTB (new KeyEventArgs ((Keys)m.WParam.ToInt32 ()));
  382. return;
  383. case Msg.WM_ERASEBKGND:
  384. m.Result = (IntPtr) 1; /* Disable background painting to avoid flickering */
  385. return;
  386. default:
  387. break;
  388. }
  389. base.WndProc (ref m);
  390. }
  391. #endregion Public Methods
  392. #region Private Methods
  393. private void UpdateArea ()
  394. {
  395. paint_area.X = paint_area.Y = 0;
  396. paint_area.Width = Width;
  397. paint_area.Height = Height;
  398. }
  399. private void UpdatePos (int newPos, bool update_trumbpos)
  400. {
  401. int old = position;
  402. if (newPos < minimum)
  403. Value = minimum;
  404. else
  405. if (newPos > maximum)
  406. Value = maximum;
  407. else
  408. Value = newPos;
  409. }
  410. private void LargeIncrement ()
  411. {
  412. UpdatePos (position + LargeChange, true);
  413. Refresh ();
  414. OnScroll (new EventArgs ());
  415. }
  416. private void LargeDecrement ()
  417. {
  418. UpdatePos (position - LargeChange, true);
  419. Refresh ();
  420. OnScroll (new EventArgs ());
  421. }
  422. private void SmallIncrement ()
  423. {
  424. UpdatePos (position + SmallChange, true);
  425. Refresh ();
  426. OnScroll (new EventArgs ());
  427. }
  428. private void SmallDecrement ()
  429. {
  430. UpdatePos (position - SmallChange, true);
  431. Refresh ();
  432. OnScroll (new EventArgs ());
  433. }
  434. private void Draw ()
  435. {
  436. float ticks = (Maximum - Minimum) / tickFrequency; /* N of ticks draw*/
  437. if (thumb_pressed)
  438. ThemeEngine.Current.DrawTrackBar (DeviceContext, paint_area, this,
  439. ref thumb_pos, ref thumb_area, thumb_pressed, ticks, thumb_mouseclick, true);
  440. else
  441. ThemeEngine.Current.DrawTrackBar (DeviceContext, paint_area, this,
  442. ref thumb_pos, ref thumb_area, thumb_pressed, ticks, Value - Minimum, false);
  443. }
  444. private void OnMouseUpTB (object sender, MouseEventArgs e)
  445. {
  446. if (!Enabled) return;
  447. if (thumb_pressed == true || mouse_clickmove == true) {
  448. thumb_pressed = false;
  449. holdclick_timer.Enabled = false;
  450. this.Capture = false;
  451. Refresh ();
  452. }
  453. }
  454. private void OnMouseDownTB (object sender, MouseEventArgs e)
  455. {
  456. if (!Enabled) return;
  457. bool fire_timer = false;
  458. Point point = new Point (e.X, e.Y);
  459. if (orientation == Orientation.Horizontal) {
  460. if (thumb_pos.Contains (point)) {
  461. this.Capture = true;
  462. thumb_pressed = true;
  463. thumb_mouseclick = e.X;
  464. Refresh ();
  465. }
  466. else {
  467. if (paint_area.Contains (point)) {
  468. if (e.X > thumb_pos.X + thumb_pos.Width)
  469. LargeIncrement ();
  470. else
  471. LargeDecrement ();
  472. Refresh ();
  473. fire_timer = true;
  474. mouse_clickmove = true;
  475. }
  476. }
  477. }
  478. else {
  479. if (thumb_pos.Contains (point)) {
  480. this.Capture = true;
  481. thumb_pressed = true;
  482. thumb_mouseclick = e.Y;
  483. Refresh ();
  484. }
  485. else {
  486. if (paint_area.Contains (point)) {
  487. if (e.Y > thumb_pos.Y + thumb_pos.Height)
  488. LargeIncrement ();
  489. else
  490. LargeDecrement ();
  491. Refresh ();
  492. fire_timer = true;
  493. mouse_clickmove = true;
  494. }
  495. }
  496. }
  497. if (fire_timer) {
  498. holdclick_timer.Interval = 300;
  499. holdclick_timer.Enabled = true;
  500. }
  501. }
  502. private void OnMouseMoveTB (object sender, MouseEventArgs e)
  503. {
  504. if (!Enabled) return;
  505. Point pnt = new Point (e.X, e.Y);
  506. /* Moving the thumb */
  507. if (thumb_pressed) {
  508. if (orientation == Orientation.Horizontal){
  509. if (paint_area.Contains (e.X, thumb_pos.Y))
  510. thumb_mouseclick = e.X;
  511. }
  512. else {
  513. if (paint_area.Contains (thumb_pos.X, e.Y))
  514. thumb_mouseclick = e.Y;
  515. }
  516. Refresh ();
  517. OnScroll (new EventArgs ());
  518. }
  519. }
  520. private void OnResizeTB (object sender, System.EventArgs e)
  521. {
  522. if (Width <= 0 || Height <= 0)
  523. return;
  524. UpdateArea ();
  525. CreateBuffers (Width, Height);
  526. }
  527. private void OnPaintTB (PaintEventArgs pevent)
  528. {
  529. if (Width <= 0 || Height <= 0 || Visible == false)
  530. return;
  531. /* Copies memory drawing buffer to screen*/
  532. UpdateArea ();
  533. Draw ();
  534. pevent.Graphics.DrawImage (ImageBuffer, 0, 0);
  535. }
  536. private void OnKeyDownTB (KeyEventArgs e)
  537. {
  538. switch (e.KeyCode) {
  539. case Keys.Up:
  540. case Keys.Right:
  541. SmallIncrement ();
  542. break;
  543. case Keys.Down:
  544. case Keys.Left:
  545. SmallDecrement ();
  546. break;
  547. default:
  548. break;
  549. }
  550. }
  551. private void OnFirstClickTimer (Object source, ElapsedEventArgs e)
  552. {
  553. Point pnt;
  554. pnt = PointToClient (MousePosition);
  555. if (thumb_area.Contains (pnt)) {
  556. if (orientation == Orientation.Horizontal) {
  557. if (pnt.X > thumb_pos.X + thumb_pos.Width)
  558. LargeIncrement ();
  559. if (pnt.X < thumb_pos.X)
  560. LargeDecrement ();
  561. }
  562. else {
  563. if (pnt.Y > thumb_pos.Y + thumb_pos.Height)
  564. LargeIncrement ();
  565. if (pnt.Y < thumb_pos.Y)
  566. LargeDecrement ();
  567. }
  568. Refresh ();
  569. }
  570. }
  571. protected override void SetBoundsCore (int x, int y,int width, int height, BoundsSpecified specified)
  572. {
  573. base.SetBoundsCore (x, y,width, height, specified);
  574. }
  575. #endregion // Private Methods
  576. }
  577. }