TrackBar.cs 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559
  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. // - Draging the thumb does not behave exactly like in Win32
  28. // - The AutoSize functionality seems quite broken for vertical controls in .Net 1.1. Not
  29. // sure if we are implementing it the right way.
  30. // - Vertical orientation still needs some work
  31. // - OnMouseWheel event
  32. //
  33. // Copyright (C) Novell Inc., 2004
  34. //
  35. //
  36. // $Revision: 1.4 $
  37. // $Modtime: $
  38. // $Log: TrackBar.cs,v $
  39. // Revision 1.4 2004/08/06 23:18:06 pbartok
  40. // - Fixed some rounding issues with float/int
  41. //
  42. // Revision 1.3 2004/07/27 15:53:02 jordi
  43. // fixes trackbar events, def classname, methods signature
  44. //
  45. // Revision 1.2 2004/07/26 17:42:03 jordi
  46. // Theme support
  47. //
  48. // Revision 1.1 2004/07/15 09:38:02 jordi
  49. // Horizontal and Vertical TrackBar control implementation
  50. //
  51. //
  52. // NOT COMPLETE
  53. using System.ComponentModel;
  54. using System.Drawing;
  55. using System.Drawing.Imaging;
  56. using System.Drawing.Drawing2D;
  57. namespace System.Windows.Forms
  58. {
  59. public class TrackBar : Control, ISupportInitialize
  60. {
  61. private int minimum;
  62. private int maximum;
  63. private int tickFrequency;
  64. private bool autosize;
  65. private int position;
  66. private int smallChange;
  67. private int largeChange;
  68. private Orientation orientation;
  69. private TickStyle tickStyle;
  70. private Bitmap bmp_mem = null;
  71. private Graphics dc_mem = null;
  72. private Rectangle paint_area = new Rectangle ();
  73. private Rectangle thumb_pos = new Rectangle (); /* Current position and size of the thumb */
  74. private Rectangle thumb_area = new Rectangle (); /* Area where the thumb can scroll */
  75. private bool thumb_pressed = false;
  76. private int thumb_pixel_click_move;
  77. private float pixel_per_pos = 0;
  78. #region Events
  79. public event EventHandler Scroll;
  80. public event EventHandler ValueChanged;
  81. #endregion // Events
  82. public TrackBar ()
  83. {
  84. orientation = Orientation.Horizontal;
  85. minimum = 0;
  86. maximum = 10;
  87. tickFrequency = 1;
  88. autosize = true;
  89. position = 0;
  90. tickStyle = TickStyle.BottomRight;
  91. smallChange = 1;
  92. largeChange = 5;
  93. Scroll = null;
  94. ValueChanged = null;
  95. SetStyle (ControlStyles.UserPaint | ControlStyles.AllPaintingInWmPaint, true);
  96. SetStyle (ControlStyles.ResizeRedraw | ControlStyles.Opaque, true);
  97. }
  98. #region Public Properties
  99. public bool AutoSize {
  100. get { return autosize; }
  101. set { autosize = value;}
  102. }
  103. public override Image BackgroundImage {
  104. get { return base.BackgroundImage; }
  105. set { base.BackgroundImage = value; }
  106. }
  107. public override Font Font {
  108. get { return base.Font; }
  109. set { base.Font = value; }
  110. }
  111. public override Color ForeColor {
  112. get { return base.ForeColor; }
  113. set { base.ForeColor = value; }
  114. }
  115. public int LargeChange {
  116. get { return largeChange; }
  117. set {
  118. if (value < 0)
  119. throw new Exception( string.Format("Value '{0}' must be greater than or equal to 0.", value));
  120. largeChange = value;
  121. Invalidate ();
  122. }
  123. }
  124. public int Maximum {
  125. get { return maximum; }
  126. set {
  127. maximum = value;
  128. if (maximum < minimum)
  129. minimum = maximum;
  130. Invalidate ();
  131. }
  132. }
  133. public int Minimum {
  134. get { return minimum; }
  135. set {
  136. minimum = value;
  137. if (minimum > maximum)
  138. maximum = minimum;
  139. Invalidate ();
  140. }
  141. }
  142. public Orientation Orientation {
  143. get { return orientation; }
  144. set {
  145. /* Orientation can be changed once the control has been created*/
  146. orientation = value;
  147. int old_witdh = Width;
  148. Width = Height;
  149. Height = old_witdh;
  150. Invalidate();
  151. }
  152. }
  153. public int SmallChange {
  154. get { return smallChange;}
  155. set {
  156. if ( value < 0 )
  157. throw new Exception( string.Format("Value '{0}' must be greater than or equal to 0.", value));
  158. smallChange = value;
  159. Invalidate ();
  160. }
  161. }
  162. public override string Text {
  163. get { return base.Text; }
  164. set { base.Text = value; }
  165. }
  166. public int TickFrequency {
  167. get { return tickFrequency; }
  168. set {
  169. if ( value > 0 ) {
  170. tickFrequency = value;
  171. Invalidate ();
  172. }
  173. }
  174. }
  175. public TickStyle TickStyle {
  176. get { return tickStyle; }
  177. set { tickStyle = value ;}
  178. }
  179. public int Value {
  180. get { return position; }
  181. set {
  182. if (value < Minimum || value > Maximum)
  183. throw new ArgumentException(
  184. string.Format("'{0}' is not a valid value for 'Value'. 'Value' should be between 'Minimum' and 'Maximum'", value));
  185. if (position != value) {
  186. position = value;
  187. if (ValueChanged != null)
  188. ValueChanged (this, new EventArgs ());
  189. Invalidate ();
  190. }
  191. }
  192. }
  193. #endregion //Public Properties
  194. #region Public Methods
  195. public void SetRange (int minValue, int maxValue)
  196. {
  197. Minimum = minValue;
  198. Maximum = maxValue;
  199. Invalidate ();
  200. }
  201. public override string ToString()
  202. {
  203. return string.Format("System.Windows.Forms.Trackbar, Minimum: {0}, Maximum: {1}, Value: {2}",
  204. Minimum, Maximum, Value);
  205. }
  206. protected override CreateParams CreateParams {
  207. get {
  208. CreateParams createParams = base.CreateParams;
  209. createParams.ClassName = XplatUI.DefaultClassName;
  210. createParams.Style = (int) (
  211. WindowStyles.WS_CHILD |
  212. WindowStyles.WS_VISIBLE);
  213. return createParams;
  214. }
  215. }
  216. protected override ImeMode DefaultImeMode {
  217. get {return ImeMode.Disable; }
  218. }
  219. protected override Size DefaultSize {
  220. get { return new System.Drawing.Size (104, 42); }
  221. }
  222. public virtual void BeginInit()
  223. {
  224. }
  225. public virtual void EndInit()
  226. {
  227. }
  228. #endregion Public Methods
  229. #region Private Methods
  230. private void fire_scroll_event ()
  231. {
  232. if (Scroll == null)
  233. return;
  234. Scroll (this, new EventArgs ());
  235. }
  236. private void UpdateArea ()
  237. {
  238. paint_area.X = paint_area.Y = 0;
  239. paint_area.Width = Width;
  240. paint_area.Height = Height;
  241. UpdatePixelPerPos ();
  242. //Console.WriteLine ("UpdateArea: {0} {1} {2}", thumb_area.Width, thumb_pos.Width, pixel_per_pos);
  243. }
  244. private void UpdateThumbPos (int pixel, bool update_value)
  245. {
  246. float new_pos = 0;
  247. //Console.WriteLine ("UpdateThumbPos: " + pixel + " per " + pixel_per_pos);
  248. if (orientation == Orientation.Horizontal) {
  249. if (pixel < thumb_area.X)
  250. thumb_pos.X = thumb_area.X;
  251. else
  252. if (pixel > thumb_area.X + thumb_area.Width - thumb_pos.Width)
  253. thumb_pos.X = thumb_area.X + thumb_area.Width - thumb_pos.Width;
  254. else
  255. thumb_pos.X = pixel;
  256. new_pos = (float) (thumb_pos.X - thumb_area.X);
  257. new_pos = new_pos / pixel_per_pos;
  258. } else {
  259. if (pixel < thumb_area.Y)
  260. thumb_pos.Y = thumb_area.Y;
  261. else
  262. if (pixel > thumb_area.Y + thumb_area.Height - thumb_pos.Height)
  263. thumb_pos.Y = thumb_area.Y + thumb_area.Height - thumb_pos.Height;
  264. else
  265. thumb_pos.Y = pixel;
  266. new_pos = (float) (thumb_pos.Y - thumb_area.Y);
  267. new_pos = new_pos / pixel_per_pos;
  268. }
  269. //Console.WriteLine ("UpdateThumbPos: thumb_pos.Y {0} thumb_area.Y {1} pixel_per_pos {2}, new pos {3}, pixel {4}",
  270. // thumb_pos.Y, thumb_area.Y, pixel_per_pos, new_pos, pixel);
  271. if (update_value)
  272. UpdatePos ((int) new_pos, false);
  273. }
  274. private void LargeIncrement()
  275. {
  276. //Console.WriteLine ("large inc: {0} {1}", position, LargeChange);
  277. UpdatePos (position + LargeChange, true);
  278. fire_scroll_event ();
  279. }
  280. private void LargeDecrement()
  281. {
  282. //Console.WriteLine ("large dec: {0} {1}", position, LargeChange);
  283. UpdatePos (position - LargeChange, true);
  284. fire_scroll_event ();
  285. }
  286. private void UpdatePixelPerPos ()
  287. {
  288. pixel_per_pos = ((float)(thumb_area.Width)
  289. / (float) (1 + Maximum - Minimum));
  290. }
  291. private void UpdatePos (int newPos, bool update_trumbpos)
  292. {
  293. int old = position;
  294. if (newPos < minimum)
  295. Value = minimum;
  296. else
  297. if (newPos > maximum)
  298. Value = maximum;
  299. else
  300. Value = newPos;
  301. //Console.WriteLine ("UpdatePos: " + newPos + " ; " + Value);
  302. //Console.WriteLine ("event : {0} {1} {2}", Scroll != null, position, old);
  303. if (orientation == Orientation.Horizontal) {
  304. if (update_trumbpos)
  305. UpdateThumbPos (thumb_area.X + (int)(((float)(Value - Minimum)) * pixel_per_pos), false);
  306. }
  307. else {
  308. if (update_trumbpos)
  309. UpdateThumbPos (thumb_area.Y + (int)(((float)(Value - Minimum)) * pixel_per_pos), false);
  310. }
  311. }
  312. #endregion // Private Methods
  313. #region Override Event Methods
  314. protected override void OnResize (EventArgs e)
  315. {
  316. //Console.WriteLine ("OnResize");
  317. base.OnResize (e);
  318. if (Width <= 0 || Height <= 0)
  319. return;
  320. UpdateArea ();
  321. /* Area for double buffering */
  322. bmp_mem = new Bitmap (Width, Height, PixelFormat.Format32bppArgb);
  323. dc_mem = Graphics.FromImage (bmp_mem);
  324. }
  325. protected override void OnHandleCreated (EventArgs e)
  326. {
  327. base.OnHandleCreated(e);
  328. //Console.WriteLine ("OnHandleCreated");
  329. UpdateArea ();
  330. bmp_mem = new Bitmap (Width, Height, PixelFormat.Format32bppArgb);
  331. dc_mem = Graphics.FromImage (bmp_mem);
  332. UpdatePos (Value, true);
  333. UpdatePixelPerPos ();
  334. draw();
  335. UpdatePos (Value, true);
  336. if (AutoSize)
  337. if (Orientation == Orientation.Horizontal)
  338. Size = new Size (Width, 45);
  339. else
  340. Size = new Size (50, Height);
  341. }
  342. /* Disable background painting to avoid flickering, since we do our painting*/
  343. protected override void OnPaintBackground (PaintEventArgs pevent)
  344. {
  345. // None
  346. }
  347. private void draw ()
  348. {
  349. int ticks = (Maximum - Minimum) / tickFrequency;
  350. ThemeEngine.Current.DrawTrackBar (dc_mem, paint_area, ref thumb_pos, ref thumb_area,
  351. tickStyle, ticks, Orientation, Focused);
  352. }
  353. protected override void OnPaint (PaintEventArgs pevent)
  354. {
  355. Console.WriteLine ("OnDraw");
  356. if (Width <= 0 || Height <= 0 || Visible == false)
  357. return;
  358. /* Copies memory drawing buffer to screen*/
  359. UpdateArea ();
  360. draw();
  361. pevent.Graphics.DrawImage (bmp_mem, 0, 0);
  362. }
  363. protected override void OnMouseDown (MouseEventArgs e)
  364. {
  365. if (!Enabled) return;
  366. //System.Console.WriteLine ("OnMouseDown" + thumb_pos);
  367. Point point = new Point (e.X, e.Y);
  368. if (orientation == Orientation.Horizontal) {
  369. if (thumb_pos.Contains (point)) {
  370. thumb_pressed = true;
  371. Invalidate ();
  372. thumb_pixel_click_move = e.X;
  373. }
  374. else {
  375. if (paint_area.Contains (point)) {
  376. if (e.X > thumb_pos.X + thumb_pos.Width)
  377. LargeIncrement ();
  378. else
  379. LargeDecrement ();
  380. Invalidate ();
  381. }
  382. }
  383. }
  384. else {
  385. if (thumb_pos.Contains (point)) {
  386. thumb_pressed = true;
  387. Invalidate ();
  388. thumb_pixel_click_move = e.Y;
  389. }
  390. else {
  391. if (paint_area.Contains (point)) {
  392. if (e.Y > thumb_pos.Y + thumb_pos.Height)
  393. LargeIncrement ();
  394. else
  395. LargeDecrement ();
  396. Invalidate ();
  397. }
  398. }
  399. }
  400. }
  401. protected override void OnMouseMove (MouseEventArgs e)
  402. {
  403. if (!Enabled) return;
  404. //System.Console.WriteLine ("OnMouseMove " + thumb_pressed);
  405. Point pnt = new Point (e.X, e.Y);
  406. /* Moving the thumb */
  407. if (thumb_pos.Contains (pnt) && thumb_pressed) {
  408. System.Console.WriteLine ("OnMouseMove " + thumb_pressed);
  409. int pixel_pos;
  410. if (orientation == Orientation.Horizontal)
  411. pixel_pos = e.X - (thumb_pixel_click_move - thumb_pos.X);
  412. else
  413. pixel_pos = e.Y - (thumb_pixel_click_move - thumb_pos.Y);
  414. UpdateThumbPos (pixel_pos, true);
  415. if (orientation == Orientation.Horizontal)
  416. thumb_pixel_click_move = e.X;
  417. else
  418. thumb_pixel_click_move = e.Y;
  419. fire_scroll_event ();
  420. //System.Console.WriteLine ("OnMouseMove thumb "+ e.Y
  421. // + " clickpos " + thumb_pixel_click_move + " pos:" + thumb_pos.Y);
  422. Invalidate ();
  423. }
  424. if (!thumb_pos.Contains (pnt) && thumb_pressed) {
  425. thumb_pressed = false;
  426. Invalidate ();
  427. }
  428. }
  429. protected override void OnMouseWheel (MouseEventArgs e)
  430. {
  431. if (!Enabled) return;
  432. //System.Console.WriteLine ("OnMouseWheel delta: " + e.Delta + " clicks:" + e.Clicks);
  433. }
  434. #endregion //Override Event Methods
  435. }
  436. }