ivr流程编辑器

FlowBrokenLineControl.cs 15KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Drawing;
  4. using System.Drawing.Drawing2D;
  5. using System.Windows.Forms;
  6. using System.Linq;
  7. namespace HySoft.FlowEditor
  8. {
  9. public partial class FlowBrokenLineControl : UserControl
  10. {
  11. #region 字段
  12. /// <summary>
  13. /// 线宽
  14. /// </summary>
  15. int _lineWidth = 2;
  16. /// <summary>
  17. /// 线半宽
  18. /// </summary>
  19. int _lineHalfWidth = 1;
  20. /// <summary>
  21. /// 图形路径
  22. /// </summary>
  23. GraphicsPath _graphicsPath;
  24. /// <summary>
  25. /// 折线点
  26. /// </summary>
  27. List<Point> _points;
  28. /// <summary>
  29. /// 线颜色
  30. /// </summary>
  31. Color _lineColor;
  32. /// <summary>
  33. /// 被选中时的线颜色
  34. /// </summary>
  35. Color _selectedLineColor;
  36. /// <summary>
  37. /// 是否有箭头
  38. /// </summary>
  39. bool _bArrow = true;
  40. /// <summary>
  41. /// 绑定的线对象
  42. /// </summary>
  43. FlowLine _flowLine;
  44. /// <summary>
  45. /// 是否被选中
  46. /// </summary>
  47. bool _bSelected;
  48. #endregion
  49. #region 属性
  50. /// <summary>
  51. /// 折线组成的点的列表
  52. /// </summary>
  53. public List<Point> PointList
  54. {
  55. get { return _points; }
  56. set
  57. {
  58. _points = value;
  59. SetControlRegion();
  60. }
  61. }
  62. /// <summary>
  63. /// 线颜色
  64. /// </summary>
  65. public Color LineColor
  66. {
  67. get { return _lineColor; }
  68. set
  69. {
  70. _lineColor = value;
  71. if (!_bSelected)
  72. BackColor = _lineColor;
  73. }
  74. }
  75. /// <summary>
  76. /// 被选中时的线颜色
  77. /// </summary>
  78. public Color SelectedLineColor
  79. {
  80. get { return _selectedLineColor; }
  81. set
  82. {
  83. _selectedLineColor = value;
  84. if (_bSelected)
  85. BackColor = _lineColor;
  86. }
  87. }
  88. /// <summary>
  89. /// 是否被选中
  90. /// </summary>
  91. public bool BeSelected
  92. {
  93. get { return _bSelected; }
  94. set
  95. {
  96. if (_bSelected != value)
  97. {
  98. _bSelected = value;
  99. if (_bSelected)
  100. BackColor = _selectedLineColor;
  101. else
  102. BackColor = _lineColor;
  103. }
  104. }
  105. }
  106. /// <summary>
  107. /// 线宽
  108. /// </summary>
  109. public int LineWidth
  110. {
  111. get { return _lineWidth; }
  112. set
  113. {
  114. if(value < 2)
  115. _lineWidth = 2;
  116. else
  117. _lineWidth = value;
  118. _lineHalfWidth = (_lineWidth + 1) / 2;
  119. SetControlRegion();
  120. }
  121. }
  122. /// <summary>
  123. /// 绑定的线对象
  124. /// </summary>
  125. public FlowLine FlowLine
  126. {
  127. get { return _flowLine; }
  128. set { _flowLine = value; }
  129. }
  130. #endregion
  131. #region 公开方法
  132. /// <summary>
  133. /// 构造方法
  134. /// </summary>
  135. public FlowBrokenLineControl()
  136. {
  137. InitializeComponent();
  138. this.BackColor = _lineColor;
  139. this.BorderStyle = System.Windows.Forms.BorderStyle.None;
  140. this.ResumeLayout(false);
  141. }
  142. /// <summary>
  143. /// 构造方法
  144. /// </summary>
  145. /// <param name="line">绑定的线</param>
  146. public FlowBrokenLineControl(FlowLine line)
  147. {
  148. InitializeComponent();
  149. _flowLine = line;
  150. this.BackColor = _lineColor;
  151. this.BorderStyle = System.Windows.Forms.BorderStyle.None;
  152. this.ResumeLayout(false);
  153. }
  154. #endregion
  155. #region 私有方法
  156. /// <summary>
  157. /// 重新设置控件的GraphicsPath
  158. /// </summary>
  159. void ResetControlGraphicsPath()
  160. {
  161. _graphicsPath = GetGraphicsPath();
  162. }
  163. /// <summary>
  164. /// (废弃的)获取GraphicsPath
  165. /// </summary>
  166. /// <returns></returns>
  167. GraphicsPath OldGetGraphicsPath()
  168. {
  169. ///计算points
  170. if (_points == null || _points.Count < 2)
  171. return null;
  172. Point[] points = new Point[_points.Count * 2];
  173. //计算第一个点
  174. TwoPointPos begainTwoPointPos = GetTwoPointPos(_points[0], _points[1]);
  175. switch (begainTwoPointPos)
  176. {
  177. case TwoPointPos.Down:
  178. case TwoPointPos.Up:
  179. points[0] = new Point(_points[0].X - _lineHalfWidth, _points[0].Y);
  180. points[_points.Count * 2 - 1] = new Point(_points[0].X + _lineHalfWidth, _points[0].Y);
  181. break;
  182. case TwoPointPos.Left:
  183. case TwoPointPos.Right:
  184. points[0] = new Point(_points[0].X, _points[0].Y - _lineHalfWidth);
  185. points[_points.Count * 2 - 1] = new Point(_points[0].X, _points[0].Y + _lineHalfWidth);
  186. break;
  187. }
  188. //计算中间点
  189. int i = 0;
  190. for (; i < _points.Count - 2; i++)
  191. {
  192. ThreePointPos threePointPos = GetThreePointPos(_points[i], _points[i + 1], _points[i + 2]);
  193. switch (threePointPos)
  194. {
  195. case ThreePointPos.Down:
  196. case ThreePointPos.Up:
  197. points[i + 1] = new Point(_points[i + 1].X - _lineHalfWidth, _points[i + 1].Y);
  198. points[points.Length - i - 2] = new Point(_points[i + 1].X + _lineHalfWidth, _points[i + 1].Y);
  199. break;
  200. case ThreePointPos.Left:
  201. case ThreePointPos.Right:
  202. points[i + 1] = new Point(_points[i + 1].X, _points[i + 1].Y - _lineHalfWidth);
  203. points[points.Length - i - 2] = new Point(_points[i + 1].X, _points[i + 1].Y + _lineHalfWidth);
  204. break;
  205. case ThreePointPos.UpRight:
  206. case ThreePointPos.DownLeft:
  207. case ThreePointPos.RightUp:
  208. case ThreePointPos.LeftDown:
  209. points[i + 1] = new Point(_points[i + 1].X - _lineHalfWidth, _points[i + 1].Y - _lineHalfWidth);
  210. points[points.Length - i - 2] = new Point(_points[i + 1].X + _lineHalfWidth, _points[i + 1].Y + _lineHalfWidth);
  211. break;
  212. case ThreePointPos.UpLeft:
  213. case ThreePointPos.DownRight:
  214. case ThreePointPos.LeftUp:
  215. case ThreePointPos.RightDown:
  216. points[i + 1] = new Point(_points[i + 1].X - _lineHalfWidth, _points[i + 1].Y + _lineHalfWidth);
  217. points[points.Length - i - 2] = new Point(_points[i + 1].X + _lineHalfWidth, _points[i + 1].Y - _lineHalfWidth);
  218. break;
  219. }
  220. }
  221. //计算最后一个点
  222. TwoPointPos endTwoPointPos = GetTwoPointPos(_points[_points.Count - 2], _points[_points.Count - 1]);
  223. switch (endTwoPointPos)
  224. {
  225. case TwoPointPos.Down:
  226. case TwoPointPos.Up:
  227. points[i + 1] = new Point(_points[i + 1].X - _lineHalfWidth, _points[i + 1].Y);
  228. points[points.Length - i - 2] = new Point(_points[i + 1].X + _lineHalfWidth, _points[i + 1].Y);
  229. break;
  230. case TwoPointPos.Left:
  231. case TwoPointPos.Right:
  232. points[i + 1] = new Point(_points[i + 1].X, _points[i + 1].Y - _lineHalfWidth);
  233. points[points.Length - i - 2] = new Point(_points[i + 1].X, _points[i + 1].Y + _lineHalfWidth);
  234. break;
  235. }
  236. //计算types
  237. if (points == null && points.Length <= 2)
  238. return null;
  239. Byte[] types = new Byte[points.Length];
  240. for (int j = 0; j < types.Length; j++)
  241. {
  242. types[j] = (Byte)PathPointType.Line;
  243. }
  244. System.Drawing.Drawing2D.GraphicsPath path = new GraphicsPath(points, types);
  245. return path;
  246. }
  247. /// <summary>
  248. /// 获取GraphicsPath
  249. /// </summary>
  250. /// <returns></returns>
  251. GraphicsPath GetGraphicsPath()
  252. {
  253. ///计算points
  254. if (_points == null || _points.Count < 2)
  255. return null;
  256. Rectangle[] rects = new Rectangle[_points.Count - 1];
  257. for (int i = 0; i < _points.Count - 1; i++)
  258. {
  259. rects[i] = new Rectangle();
  260. TwoPointPos twoPointPos = GetTwoPointPos(_points[i], _points[i+1]);
  261. switch (twoPointPos)
  262. {
  263. case TwoPointPos.Up:
  264. rects[i] = new Rectangle(_points[i + 1].X - _lineHalfWidth, _points[i + 1].Y, _lineHalfWidth * 2, _points[i].Y - _points[i + 1].Y);
  265. break;
  266. case TwoPointPos.Down:
  267. rects[i] = new Rectangle(_points[i].X - _lineHalfWidth, _points[i].Y, _lineHalfWidth * 2, _points[i + 1].Y - _points[i].Y);
  268. break;
  269. case TwoPointPos.Left:
  270. rects[i] = new Rectangle(_points[i + 1].X, _points[i + 1].Y - _lineHalfWidth, _points[i].X - _points[i + 1].X, _lineHalfWidth * 2);
  271. break;
  272. case TwoPointPos.Right:
  273. rects[i] = new Rectangle(_points[i].X, _points[i + 1].Y - _lineHalfWidth, _points[i + 1].X - _points[i].X, _lineHalfWidth * 2);
  274. break;
  275. }
  276. }
  277. System.Drawing.Drawing2D.GraphicsPath path = new GraphicsPath();
  278. //添加箭头
  279. if (_bArrow)
  280. {
  281. Point headPoint = _points[_points.Count - 1];
  282. Point tailPoint = _points[_points.Count - 2];
  283. Point pos2 = new Point();
  284. Point pos3 = new Point();
  285. TwoPointPos twoPointPos = GetTwoPointPos(tailPoint, headPoint);
  286. switch (twoPointPos)
  287. {
  288. case TwoPointPos.Up:
  289. pos2.X = headPoint.X - (_lineWidth * 2);
  290. pos2.Y = headPoint.Y + (_lineWidth * 2);
  291. pos3.X = headPoint.X + (_lineWidth * 2);
  292. pos3.Y = pos2.Y;
  293. break;
  294. case TwoPointPos.Down:
  295. pos2.X = headPoint.X - (_lineWidth * 2);
  296. pos2.Y = headPoint.Y - (_lineWidth * 2);
  297. pos3.X = headPoint.X + (_lineWidth * 2);
  298. pos3.Y = pos2.Y;
  299. break;
  300. case TwoPointPos.Left:
  301. pos2.X = headPoint.X + (_lineWidth * 2);
  302. pos2.Y = headPoint.Y - (_lineWidth * 2);
  303. pos3.X = pos2.X;
  304. pos3.Y = headPoint.Y + (_lineWidth * 2);
  305. break;
  306. case TwoPointPos.Right:
  307. pos2.X = headPoint.X - (_lineWidth * 2);
  308. pos2.Y = headPoint.Y - (_lineWidth * 2);
  309. pos3.X = pos2.X;
  310. pos3.Y = headPoint.Y + (_lineWidth * 2);
  311. break;
  312. }
  313. Point[] arrowPoints = new Point[] { headPoint, pos2, pos3 };
  314. path.AddPolygon(arrowPoints);
  315. }
  316. path.AddRectangles(rects.ToArray());
  317. return path;
  318. }
  319. /// <summary>
  320. /// 设置控件的区域
  321. /// </summary>
  322. void SetControlRegion()
  323. {
  324. ResetControlGraphicsPath();
  325. if(_graphicsPath != null)
  326. this.Region = new Region(_graphicsPath);
  327. }
  328. /// <summary>
  329. /// 判断2个点的位置,第二个相对于第一个点的位置
  330. ///
  331. /// </summary>
  332. /// <param name="point1"></param>
  333. /// <param name="point2"></param>
  334. /// <returns></returns>
  335. public static TwoPointPos GetTwoPointPos(Point point1, Point point2)
  336. {
  337. if (point2.X > point1.X)
  338. {
  339. return TwoPointPos.Right;
  340. }
  341. else if (point2.X < point1.X)
  342. {
  343. return TwoPointPos.Left;
  344. }
  345. else
  346. {
  347. if (point2.Y > point1.Y)
  348. return TwoPointPos.Down;
  349. else
  350. return TwoPointPos.Up;
  351. }
  352. }
  353. /// <summary>
  354. /// 判断三个点的位置
  355. /// </summary>
  356. /// <param name="point1"></param>
  357. /// <param name="point2"></param>
  358. /// <param name="point3"></param>
  359. /// <returns></returns>
  360. ThreePointPos GetThreePointPos(Point point1, Point point2, Point point3)
  361. {
  362. TwoPointPos point2Pos = GetTwoPointPos(point1, point2);
  363. TwoPointPos point3Pos = GetTwoPointPos(point2, point3);
  364. if (point2Pos == TwoPointPos.Right)
  365. {
  366. if (point3Pos == TwoPointPos.Right)
  367. return ThreePointPos.Right;
  368. else if (point3Pos == TwoPointPos.Up)
  369. return ThreePointPos.RightUp;
  370. else if (point3Pos == TwoPointPos.Down)
  371. return ThreePointPos.RightDown;
  372. }
  373. else if (point2Pos == TwoPointPos.Left)
  374. {
  375. if (point3Pos == TwoPointPos.Left)
  376. return ThreePointPos.Left;
  377. else if (point3Pos == TwoPointPos.Up)
  378. return ThreePointPos.LeftUp;
  379. else if (point3Pos == TwoPointPos.Down)
  380. return ThreePointPos.LeftDown;
  381. }
  382. else if (point2Pos == TwoPointPos.Up)
  383. {
  384. if (point3Pos == TwoPointPos.Up)
  385. return ThreePointPos.Up;
  386. else if (point3Pos == TwoPointPos.Right)
  387. return ThreePointPos.UpRight;
  388. else if (point3Pos == TwoPointPos.Left)
  389. return ThreePointPos.UpLeft;
  390. }
  391. //Down
  392. if (point3Pos == TwoPointPos.Down)
  393. return ThreePointPos.Down;
  394. else if (point3Pos == TwoPointPos.Right)
  395. return ThreePointPos.DownRight;
  396. //Left
  397. return ThreePointPos.DownLeft;
  398. }
  399. #endregion
  400. #region 控件响应方法
  401. #endregion
  402. }
  403. /// <summary>
  404. /// 两个点相对位置类型
  405. /// </summary>
  406. public enum TwoPointPos
  407. {
  408. Left,
  409. Up,
  410. Right,
  411. Down,
  412. }
  413. /// <summary>
  414. /// 三个点相对位置类型
  415. /// </summary>
  416. public enum ThreePointPos
  417. {
  418. LeftUp,
  419. RightUp,
  420. RightDown,
  421. LeftDown,
  422. UpRight,
  423. UpLeft,
  424. DownLeft,
  425. DownRight,
  426. Left,
  427. Right,
  428. Up,
  429. Down,
  430. }
  431. }