TrackBar.cs 15 KB

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