HScrollBarEx.cs
上传用户:nnpulika
上传日期:2013-02-15
资源大小:597k
文件大小:17k
源码类别:

状态条

开发平台:

C#

  1. using System;
  2. using System.Drawing;
  3. using System.Diagnostics;
  4. using System.Runtime.InteropServices;
  5. using System.ComponentModel;
  6. using System.Windows.Forms;
  7. using UtilityLibrary.Win32;
  8. using UtilityLibrary.General;
  9. namespace UtilityLibrary.WinControls
  10. {
  11. /// <summary>
  12. /// 
  13. /// </summary>
  14. [ToolboxItem(false)]
  15. public class HScrollBarEx : UtilityLibrary.WinControls.ScrollBarEx
  16. {
  17. #region Events
  18. public event ThumbHandler ThumbLeft = null;
  19. public event ThumbHandler ThumbRight = null;
  20. public event EventHandler LineLeft = null;
  21. public event EventHandler LineRight = null;
  22. public event EventHandler PageLeft = null;
  23. public event EventHandler PageRight = null;
  24. #endregion
  25. #region Class variables
  26. DrawState leftArrowDrawState = DrawState.Normal;
  27. DrawState rightArrowDrawState = DrawState.Normal;
  28. bool ignoreMouseMove = false;
  29. bool draggingThumb = false;
  30. int oldMouseX = 0;
  31. ScrollBarHit currentTarget = ScrollBarHit.None;
  32. bool firstTick = false;
  33. double thumbPixelPos = 0;
  34. bool processingAutomaticScrolling = false;
  35. const int MINIMUM_THUMB_WIDTH = 6;
  36. #endregion
  37. #region Constructors
  38. public HScrollBarEx()
  39. {
  40. }
  41. public HScrollBarEx(Control parent) : base(parent)
  42. {
  43. }
  44. #endregion
  45. #region Properties
  46. public ImageList LeftArrowImageList
  47. {
  48. set {  upArrowImageList = value; }
  49. get { return upArrowImageList; }
  50. }
  51. public ImageList RightArrowImageList
  52. {
  53. set {  downArrowImageList = value; }
  54. get { return downArrowImageList; }
  55. }
  56. #endregion
  57. #region Overrides
  58. protected override void OnMouseDown(MouseEventArgs e)
  59. {
  60. base.OnMouseDown(e);
  61. if ( e.Button != MouseButtons.Left )
  62. return;
  63. ScrollBarHit hit = HitTest(new Point(e.X, e.Y));
  64. if ( hit == ScrollBarHit.LeftArrow )
  65. {
  66. leftArrowDrawState = DrawState.Hot;
  67. Position -= smallChange;
  68. FireLineLeft();
  69. }
  70. else if ( hit == ScrollBarHit.RightArrow )
  71. {
  72. rightArrowDrawState = DrawState.Hot;
  73. Position += smallChange;
  74. FireLineRight();
  75. }
  76. else if ( hit == ScrollBarHit.PageLeft )
  77. {
  78. Position -= largeChange;
  79. FirePageLeft();
  80. }
  81. else if ( hit == ScrollBarHit.PageRight )
  82. {
  83. Position += largeChange;
  84. FirePageRight();
  85. }
  86. else if ( hit == ScrollBarHit.Thumb )
  87. {
  88. Capture = true;
  89. draggingThumb = true;
  90. thumbDrawState = DrawState.Pressed;
  91. oldMouseX = e.X;
  92. thumbPixelPos = GetThumbPixelPosition(pos);
  93. Invalidate();
  94. }
  95. if ( !processingAutomaticScrolling )
  96. {
  97. if ( hit != ScrollBarHit.Thumb && hit != ScrollBarHit.None )
  98. ProcessScrolling(hit);
  99. }
  100. }
  101. protected override void OnMouseMove(MouseEventArgs e)
  102. {
  103. base.OnMouseDown(e);
  104. if ( ignoreMouseMove) 
  105. {
  106. ignoreMouseMove = false;
  107. return;
  108. }
  109. // Reset every thing to normal state
  110. leftArrowDrawState = DrawState.Normal;
  111. rightArrowDrawState = DrawState.Normal;
  112. thumbDrawState = DrawState.Normal;
  113. ScrollBarHit hit = HitTest(new Point(e.X, e.Y));
  114. if ( hit == ScrollBarHit.LeftArrow )
  115. {
  116. leftArrowDrawState = DrawState.Hot;
  117. }
  118. else if ( hit == ScrollBarHit.RightArrow )
  119. {
  120. rightArrowDrawState = DrawState.Hot;
  121. }
  122. else if ( hit == ScrollBarHit.Thumb || draggingThumb )
  123. {
  124. if ( draggingThumb )
  125. {
  126. thumbDrawState = DrawState.Pressed;
  127. UpdatePosition(e.X);
  128. oldMouseX = e.X;
  129. if ( dragFrequency == ThumbDraggedFireFrequency.MouseMove )
  130. {
  131. if ( pos > previousPos )
  132. FireThumbRight((int)pos-(int)previousPos);
  133. else
  134. FireThumbLeft((int)previousPos-(int)pos);
  135. }
  136. }
  137. else
  138. {
  139. thumbDrawState = DrawState.Hot;
  140. }
  141. }
  142. Invalidate();
  143. }
  144. protected override void OnMouseUp(MouseEventArgs e)
  145. {
  146. base.OnMouseUp(e);
  147. if ( e.Button != MouseButtons.Left )
  148. return;
  149. // Reset drawing to normal state
  150. leftArrowDrawState = DrawState.Normal;
  151. rightArrowDrawState = DrawState.Normal;
  152. thumbDrawState = DrawState.Normal;
  153. ignoreMouseMove = true;
  154. if ( draggingThumb )
  155. {
  156. Capture = false;
  157. thumbDrawState = DrawState.Normal;
  158. UpdatePosition(e.X);
  159. draggingThumb = false;
  160.                 
  161. if ( pos > previousPos )
  162. {
  163. FireThumbRight((int)pos-(int)previousPos);
  164. }
  165. else
  166. FireThumbLeft((int)previousPos-(int)pos);
  167. // For users who that want to know when the
  168. // Thumb is released
  169. FireThumbRelease();
  170. }
  171. Invalidate();
  172. }
  173. protected override void OnMouseEnter(EventArgs e)
  174. {
  175. // Set state to hot
  176. base.OnMouseEnter(e);
  177. Point pos = Control.MousePosition;
  178. pos = PointToClient(pos);
  179. ScrollBarHit hit = HitTest(pos);
  180. if ( hit == ScrollBarHit.LeftArrow )
  181. {
  182. leftArrowDrawState = DrawState.Hot;
  183. }
  184. else if ( hit == ScrollBarHit.RightArrow )
  185. {
  186. rightArrowDrawState = DrawState.Hot;
  187. }
  188. else if ( hit == ScrollBarHit.Thumb )
  189. {
  190. thumbDrawState = DrawState.Hot;
  191. }
  192. Invalidate();
  193. }
  194. protected override void OnMouseLeave(EventArgs e)
  195. {
  196. // Set state to Normal
  197. base.OnMouseLeave(e);
  198. leftArrowDrawState = DrawState.Normal;
  199. rightArrowDrawState = DrawState.Normal;
  200. thumbDrawState = DrawState.Normal;
  201. Invalidate();
  202. }
  203. protected override void SizeScrollBar()
  204. {
  205. // Resize scrollbar
  206. // Size scrollbar to have the standard dimensions
  207. // of an operating system created scrollbar
  208. Rectangle rcParent = parentWindow.ClientRectangle;
  209. if ( usingBothScrollBars )
  210. {
  211. Bounds =  new Rectangle(rcParent.Left+BorderGap, rcParent.Bottom - BorderGap*2 - HThumb,  
  212. rcParent.Width - BorderGap*2 - VThumb, HThumb);
  213. }
  214. else
  215. {
  216. Bounds =  new Rectangle(rcParent.Left+BorderGap, rcParent.Bottom - BorderGap*2 - HThumb,  
  217. rcParent.Width - BorderGap*2, HThumb);
  218. }
  219. }
  220. protected override void DrawScrollBar(Graphics g)
  221. {
  222. // Draw background
  223. DrawBackground(g);
  224. // Draw Button up arrow
  225. if ( Enabled )
  226. {
  227. // Up and Down buttons
  228. DrawArrowButtons(g);
  229. // Draw Thumb
  230. DrawThumb(g, thumbDrawState);
  231. // Draw Gripper
  232. if ( drawGripper )
  233. DrawThumbGripper(g, thumbDrawState);
  234. }
  235. }
  236. #endregion
  237. #region Implementation
  238. void FireThumbLeft(int delta)
  239. {
  240. if ( ThumbLeft != null && previousPos != pos )
  241. ThumbLeft(this, delta);
  242. }
  243. void FireThumbRight(int delta)
  244. {
  245. if ( ThumbRight != null && previousPos != pos )
  246. ThumbRight(this, delta);
  247. }
  248. void FireLineLeft()
  249. {
  250. if ( LineLeft != null && previousPos != pos )
  251. LineLeft(this, EventArgs.Empty);
  252. }
  253. void FireLineRight()
  254. {
  255. if ( LineRight != null && previousPos != pos )
  256. LineRight(this, EventArgs.Empty);
  257. }
  258.         
  259. void FirePageLeft()
  260. {
  261. if ( PageLeft != null && previousPos != pos )
  262. PageLeft(this, EventArgs.Empty);
  263. }
  264. void FirePageRight()
  265. {
  266. if ( PageRight != null && previousPos != pos )
  267. PageRight(this, EventArgs.Empty);
  268. }
  269. void ProcessScrolling(ScrollBarHit hit)
  270. {
  271. // Capture the mouse
  272. stopAutomaticScrolling = false;
  273. Capture = true;
  274. firstTick = true;
  275. // Start timer
  276. System.Windows.Forms.Timer timer = new System.Windows.Forms.Timer();
  277. timer.Tick += new EventHandler(ScrollingTick);
  278. timer.Interval = TIMER_INTERVAL;
  279. timer.Start();
  280. currentTarget = hit;
  281.                          
  282. while ( stopAutomaticScrolling == false ) 
  283. {
  284. // Check messages until we find a condition to break out of the loop
  285. Win32.MSG msg = new Win32.MSG();
  286. WindowsAPI.GetMessage(ref msg, 0, 0, 0);
  287. Point point = new Point(0,0);
  288. if ( msg.message == (int)Msg.WM_MOUSEMOVE 
  289. || msg.message == (int)Msg.WM_LBUTTONUP || msg.message == (int)Msg.WM_LBUTTONDBLCLK )
  290. {
  291. point = WindowsAPI.GetPointFromLPARAM((int)msg.lParam);
  292. }
  293. Msg thisMessage = (Msg)msg.message;
  294. switch(msg.message)
  295. {
  296. case (int)Msg.WM_MOUSEMOVE:
  297. {
  298. ScrollBarHit current = HitTest(point);
  299. ProcessMouseMoveScrolling(current);
  300. Invalidate();
  301. break;
  302. }
  303. case (int)Msg.WM_LBUTTONUP:
  304. case (int)Msg.WM_LBUTTONDBLCLK:
  305. {
  306. stopAutomaticScrolling = true;
  307. WindowsAPI.DispatchMessage(ref msg);
  308. break;
  309. }
  310. case (int)Msg.WM_KEYDOWN:
  311. {
  312. if ( (int)msg.wParam == (int)VirtualKeys.VK_ESCAPE) 
  313. stopAutomaticScrolling = true;
  314. break;
  315. }
  316. default:
  317. WindowsAPI.DispatchMessage(ref msg);
  318. break;
  319. }
  320. }
  321. // Stop timer
  322. timer.Stop();
  323. timer.Dispose();
  324. Invalidate();
  325. // Release the capture
  326. Capture = false;
  327. if ( processingAutomaticScrolling )
  328. {
  329. processingAutomaticScrolling = false;
  330. FireStoppingAutomaticScrolling();
  331. }
  332. }
  333. void ProcessMouseMoveScrolling(ScrollBarHit hit)
  334. {
  335. leftArrowDrawState = DrawState.Normal;
  336. rightArrowDrawState = DrawState.Normal;
  337. if ( hit == ScrollBarHit.LeftArrow )
  338. leftArrowDrawState = DrawState.Hot;
  339. else if ( hit == ScrollBarHit.RightArrow )
  340. rightArrowDrawState = DrawState.Hot;
  341.             
  342. }
  343. void ScrollingTick(Object timeObject, EventArgs eventArgs) 
  344. {
  345. processingAutomaticScrolling = true;
  346. FireStartingAutomaticScrolling();
  347. // Ignore the first tick since sometimes the user
  348. // is just clicking and the first tick happens
  349. // so fast that produces the effect of scrolling twice
  350. if ( firstTick )
  351. {
  352. firstTick = false;
  353. return;
  354. }
  355. // Get mouse coordinates
  356. Point point = Control.MousePosition;
  357. point = PointToClient(point);
  358. Rectangle rc = Rectangle.Empty;
  359. if ( currentTarget == ScrollBarHit.LeftArrow )
  360. {
  361. rc = GetArrowButtonRectangle(true);
  362. if ( rc.Contains(point) )
  363. {
  364. Position -= smallChange;
  365. FireLineLeft();
  366. }
  367. }
  368. else if ( currentTarget == ScrollBarHit.RightArrow )
  369. {
  370. rc = GetArrowButtonRectangle(false);
  371. if ( rc.Contains(point) )
  372. {
  373. Position += smallChange;
  374. FireLineRight();
  375. }
  376. }
  377. else if ( currentTarget == ScrollBarHit.PageLeft )
  378. {
  379. rc = GetPageRect(true);
  380. if ( rc.Contains(point) )
  381. {
  382. Position -= largeChange;
  383. FirePageLeft();
  384. }
  385. }
  386. else if ( currentTarget == ScrollBarHit.PageRight )
  387. {
  388. rc = GetPageRect(false);
  389. if ( rc.Contains(point) )
  390. {
  391. Position += largeChange;
  392. FirePageRight();
  393. }
  394. }
  395. }
  396. void SetPosition(double fpos)
  397. {
  398. if ( pos != fpos )
  399. {
  400. previousPos = pos;
  401. double newValue = fpos;
  402. if ( newValue >= max-largeChange ) 
  403. {
  404. // Position cannot be larger than
  405. // max-largeChange
  406. pos = max-largeChange;
  407. }
  408. else if ( newValue < 0 )
  409. {
  410. // Negative values don't make sense
  411. pos = 0;
  412. }
  413. else
  414. pos = newValue;
  415. if ( previousPos != pos )
  416. Invalidate();
  417. }
  418. else
  419. previousPos = pos;
  420. }
  421. void UpdatePosition(int xPos)
  422. {
  423. int increment = 0;
  424. if ( xPos >= oldMouseX )
  425. increment = xPos - oldMouseX;
  426. else
  427. increment = (oldMouseX - xPos)*(-1);
  428. thumbPixelPos += increment; 
  429. double fPos = GetThumbLogicalPosition(thumbPixelPos);
  430. SetPosition(fPos);
  431. }
  432. protected virtual void DrawArrowButtons(Graphics g)
  433. {
  434. Rectangle leftRect = GetArrowButtonRectangle(true); 
  435. Rectangle rightRect = GetArrowButtonRectangle(false);
  436. DrawFlatArrowButton(g, leftRect, ArrowGlyph.Left, leftArrowDrawState);
  437. DrawFlatArrowButton(g, rightRect, ArrowGlyph.Right, rightArrowDrawState);
  438. }
  439. protected virtual void DrawThumbGripper(Graphics g, DrawState drawState)
  440. {
  441. Rectangle rc = GetThumbRect();
  442. // Don't draw it if it won't fit
  443. if ( rc.Width < MINIMUM_THUMB_WITH_GRIPPER_SIZE )
  444. return;
  445. int xMiddle = rc.Left + rc.Width/2;
  446. int yPos = rc.Top + (rc.Height - GRIPPER_HEIGHT)/2;
  447.             
  448. Color lightColor = ColorUtil.VSNetSelectionColor;
  449. Color darkColor = ColorUtil.VSNetPressedColor;
  450. // Check if the user set custom colors for the gripper
  451. if ( gripperLightColor != Color.Empty )
  452. lightColor = gripperLightColor;
  453. if ( gripperDarkColor != Color.Empty )
  454. darkColor = gripperDarkColor;
  455. Pen lightPen = new Pen(lightColor);
  456. Pen darkPen = new Pen(darkColor);
  457. Point pt1 = new Point(xMiddle-GRIPPER_HEIGHT/2, yPos);
  458. Point pt2 = new Point(xMiddle-GRIPPER_HEIGHT/2, yPos+GRIPPER_WIDTH);
  459. g.DrawLine(lightPen, pt1, pt2);
  460. pt1 = new Point(xMiddle-GRIPPER_HEIGHT/2+1, yPos+1);
  461. pt2 = new Point(xMiddle-GRIPPER_HEIGHT/2+1, yPos+GRIPPER_WIDTH+1);
  462. g.DrawLine(darkPen, pt1, pt2);
  463. pt1 = new Point(xMiddle-GRIPPER_HEIGHT/2+2, yPos);
  464. pt2 = new Point(xMiddle-GRIPPER_HEIGHT/2+2, yPos+GRIPPER_WIDTH);
  465. g.DrawLine(lightPen, pt1, pt2);
  466. pt1 = new Point(xMiddle-GRIPPER_HEIGHT/2+3, yPos+1);
  467. pt2 = new Point(xMiddle-GRIPPER_HEIGHT/2+3, yPos+GRIPPER_WIDTH+1);
  468. g.DrawLine(darkPen, pt1, pt2);
  469. pt1 = new Point(xMiddle-GRIPPER_HEIGHT/2+4, yPos);
  470. pt2 = new Point(xMiddle-GRIPPER_HEIGHT/2+4, yPos+GRIPPER_WIDTH);
  471. g.DrawLine(lightPen, pt1, pt2);
  472. pt1 = new Point(xMiddle-GRIPPER_HEIGHT/2+5, yPos+1);
  473. pt2 = new Point(xMiddle-GRIPPER_HEIGHT/2+5, yPos+GRIPPER_WIDTH+1);
  474. g.DrawLine(darkPen, pt1, pt2);
  475. pt1 = new Point(xMiddle-GRIPPER_HEIGHT/2+6, yPos);
  476. pt2 = new Point(xMiddle-GRIPPER_HEIGHT/2+6, yPos+GRIPPER_WIDTH);
  477. g.DrawLine(lightPen, pt1, pt2);
  478. pt1 = new Point(xMiddle-GRIPPER_HEIGHT/2+7, yPos+1);
  479. pt2 = new Point(xMiddle-GRIPPER_HEIGHT/2+7, yPos+GRIPPER_WIDTH+1);
  480. g.DrawLine(darkPen, pt1, pt2);
  481. lightPen.Dispose();
  482. darkPen.Dispose();
  483. }
  484. Rectangle GetArrowButtonRectangle( bool leftButton)
  485. {
  486. Rectangle rc = ClientRectangle;
  487. if ( leftButton )
  488. {
  489. return new Rectangle(rc.Left, 0, HThumb, HThumb);
  490. }
  491. else
  492. {
  493. return new Rectangle(rc.Right-HThumb, 0, HThumb, HThumb);
  494. }
  495. }
  496. protected override Rectangle GetThumbRect()
  497. {
  498. double thumbWidth = GetThumbPixelSize();
  499. int drawPos = 0;
  500. if ( draggingThumb  ) 
  501. {
  502. // If dragging the thumb don't use
  503. // a position based on the scaled calculation
  504. // but the actual one from the OnMouseMove event
  505. // to avoid jerkiness from rounding off errors
  506. drawPos = GetSafeThumbPixelPos((int)thumbWidth);
  507. }
  508. else
  509. {
  510. drawPos = (int)GetThumbPixelPosition(pos);
  511. }
  512. // To avoid rounding off errors
  513. if ( pos == max-largeChange )
  514. drawPos = ClientRectangle.Width - HThumb - (int)thumbWidth;
  515. Rectangle rc = Rectangle.Empty;
  516. // If width is too small, don't let it disappear
  517. if ( thumbWidth < MINIMUM_THUMB_WIDTH )
  518. thumbWidth = MINIMUM_THUMB_WIDTH;
  519. // Smaller than the total width of the scrollbar
  520. // to make it look nicer
  521. rc = new Rectangle(drawPos, 0, (int)thumbWidth, HThumb);
  522. rc.Inflate(0, -1);
  523. return rc;
  524. }
  525. int GetSafeThumbPixelPos(int thumbWidth)
  526. {
  527. if ( thumbPixelPos > (ClientRectangle.Width - HThumb)- thumbWidth ) 
  528. {
  529. // Position cannot be larger than
  530. // max-largeChange
  531. return (ClientRectangle.Width - HThumb)-thumbWidth;
  532. }
  533. else if ( thumbPixelPos <= HThumb )
  534. {
  535. // Negative values don't make sense
  536. return HThumb;
  537. }
  538. else
  539. return (int)thumbPixelPos;
  540. }
  541. Rectangle GetPageRect(bool left)
  542. {
  543. Rectangle rcClient = ClientRectangle;
  544. Rectangle rcThumb = GetThumbRect();
  545. Rectangle pageRect;
  546. if ( left )
  547. {
  548. pageRect = new Rectangle(rcClient.Left+HThumb+1, 
  549. rcClient.Top, rcThumb.Left-HThumb-2, rcClient.Height);
  550. }
  551. else
  552. {
  553. pageRect = new Rectangle(rcThumb.Right+1, 
  554. rcClient.Top, rcClient.Right-HThumb-1, rcClient.Height);
  555. }
  556. return pageRect;
  557. }
  558. double GetThumbPixelSize()
  559. {
  560. Rectangle rc = ClientRectangle;
  561. int width = rc.Width - HThumb*2;
  562. if ( largeChange == 0 || (max-min) == 0)
  563. return 0;
  564. float numOfPages = (float)(max-min)/(float)largeChange;
  565. return width/numOfPages;                         
  566. }
  567. double GetThumbPixelPosition(double logicalPos)
  568. {
  569. double fWidth = ClientRectangle.Width - HThumb*2;
  570. double fRange = (max-min);
  571. double fLogicalPos = logicalPos;
  572. return (fLogicalPos*fWidth)/fRange + HThumb;
  573. }
  574. double GetThumbLogicalPosition(double pixelPos)
  575. {
  576. double fWidth = ClientRectangle.Width - HThumb*2;
  577. double fRange = (max-min);
  578. double fpixelPos = pixelPos;
  579. return (fRange*(fpixelPos-HThumb)/fWidth);
  580. }
  581. ScrollBarHit HitTest(Point point)
  582. {
  583. Rectangle leftArrow = GetArrowButtonRectangle(true);
  584. if ( leftArrow.Contains(point) )
  585. return ScrollBarHit.LeftArrow;
  586. Rectangle rightArrow = GetArrowButtonRectangle(false);
  587. if ( rightArrow.Contains(point) )
  588. return ScrollBarHit.RightArrow;
  589. Rectangle leftPageRect = GetPageRect(true);
  590. if ( leftPageRect.Contains(point) )
  591. return ScrollBarHit.PageLeft;
  592. Rectangle rightPageRect = GetPageRect(false);
  593. if ( rightPageRect.Contains(point) )
  594. return ScrollBarHit.PageRight;
  595. Rectangle thumbRect = GetThumbRect();
  596. if ( thumbRect.Contains(point) )
  597. return ScrollBarHit.Thumb;
  598.             
  599. return ScrollBarHit.None;
  600. }
  601. #endregion
  602. }
  603. }