RenderEngine.5.GraphicsPath.cs 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497
  1. using System;
  2. using System.Drawing;
  3. using System.Drawing.Drawing2D;
  4. namespace Microsoft.Windows.Forms
  5. {
  6. public static partial class RenderEngine
  7. {
  8. /// <summary>
  9. /// 创建路径。
  10. /// </summary>
  11. /// <param name="rect">矩形。</param>
  12. /// <returns>创建的路径。</returns>
  13. public static GraphicsPath CreateGraphicsPath(Rectangle rect)
  14. {
  15. return CreateGraphicsPath(rect.X, rect.Y, rect.Width, rect.Height);
  16. }
  17. /// <summary>
  18. /// 创建路径。
  19. /// </summary>
  20. /// <param name="pt">左上角。</param>
  21. /// <param name="sz">大小</param>
  22. /// <returns>创建的路径。</returns>
  23. public static GraphicsPath CreateGraphicsPath(Point pt, Size sz)
  24. {
  25. return CreateGraphicsPath(pt.X, pt.Y, sz.Width, sz.Height);
  26. }
  27. /// <summary>
  28. /// 创建路径。
  29. /// </summary>
  30. /// <param name="x">左上角水平坐标。</param>
  31. /// <param name="y">左上角垂直坐标</param>
  32. /// <param name="width">宽度。</param>
  33. /// <param name="height">高度。</param>
  34. /// <returns>创建的路劲。</returns>
  35. public static GraphicsPath CreateGraphicsPath(int x, int y, int width, int height)
  36. {
  37. Point[] points = new Point[4];
  38. points[0] = new Point(x, y);
  39. points[1] = new Point(x + width, y);
  40. points[2] = new Point(x + width, y + height);
  41. points[3] = new Point(x, y + height);
  42. GraphicsPath shape = new GraphicsPath();
  43. shape.AddPolygon(points);
  44. return shape;
  45. }
  46. /// <summary>
  47. /// 创建路径。
  48. /// </summary>
  49. /// <param name="rect">用来创建路径的矩形。</param>
  50. /// <param name="cornerStyle">圆角弯曲样式。</param>
  51. /// <param name="roundStyle">圆角的样式。</param>
  52. /// <param name="radius">圆角半径。</param>
  53. /// <param name="correct">是否把矩形长宽减 1,以便画出边框。</param>
  54. /// <returns>创建的路径。</returns>
  55. public static GraphicsPath CreateGraphicsPath(Rectangle rect, CornerStyle cornerStyle, RoundStyle roundStyle, float radius, bool correct)
  56. {
  57. //-----------------校准-----------------
  58. if (correct)
  59. {
  60. rect.Width--;
  61. rect.Height--;
  62. }
  63. //-----------------定义返回值-----------------
  64. GraphicsPath path = new GraphicsPath();
  65. //-----------------特殊情况处理-----------------
  66. if (float.IsNaN(radius) || radius <= 0f)
  67. {
  68. path.AddRectangle(rect);
  69. return path;
  70. }
  71. //-----------------临时变量定义-----------------
  72. float diameter = radius * 2;//直径
  73. float halfWidth = rect.Width / 2f;//宽度一半
  74. float halfHeight = rect.Height / 2f;//高度一半
  75. PointF ptMiddleCenter = new PointF(rect.X + halfWidth, rect.Y + halfHeight);//中心点
  76. float lrDegrees = 0f;//半径大于半高,圆心角
  77. float lrOffset = 0f;//半径大于半高,圆弧到边距离
  78. if ((roundStyle & RoundStyle.All) != 0 && radius > halfHeight)
  79. {
  80. double lrRadian = Math.Acos((radius - halfHeight) / radius);//弧度
  81. lrDegrees = (float)MathEx.ToDegrees(lrRadian);//角度
  82. lrOffset = (float)(radius * Math.Sin(lrRadian));
  83. }
  84. float tbDegrees = 0f;//半径大于半宽,圆心角
  85. float tbOffset = 0f;//半径大于办宽,圆弧到边距离
  86. if ((roundStyle & RoundStyle.All) != 0 && radius > halfWidth)
  87. {
  88. double tbRadian = Math.Acos((radius - halfWidth) / radius);//弧度
  89. tbDegrees = (float)MathEx.ToDegrees(tbRadian);//角度
  90. tbOffset = (float)(radius * Math.Sin(tbRadian));
  91. }
  92. //临时变量
  93. PointF ptBegin;
  94. PointF ptEnd;
  95. #region 左上
  96. if ((roundStyle & RoundStyle.TopLeft) == 0)//直角
  97. {
  98. if ((cornerStyle & CornerStyle.LeftIn) != 0)
  99. {
  100. ptBegin = new PointF(rect.X + radius, ptMiddleCenter.Y);
  101. ptEnd = new PointF(rect.X, rect.Y);
  102. path.AddLine(ptBegin, ptEnd);
  103. }
  104. else if ((cornerStyle & CornerStyle.LeftOut) != 0)
  105. {
  106. ptBegin = new PointF(rect.X, ptMiddleCenter.Y);
  107. ptEnd = new PointF(rect.X + radius, rect.Y);
  108. path.AddLine(ptBegin, ptEnd);
  109. }
  110. else if ((cornerStyle & CornerStyle.TopIn) != 0)
  111. {
  112. ptBegin = new PointF(rect.X, rect.Y);
  113. ptEnd = new PointF(ptMiddleCenter.X, rect.Y + radius);
  114. path.AddLine(ptBegin, ptEnd);
  115. }
  116. else if ((cornerStyle & CornerStyle.TopOut) != 0)
  117. {
  118. ptBegin = new PointF(rect.X, rect.Y + radius);
  119. ptEnd = new PointF(ptMiddleCenter.X, rect.Y);
  120. path.AddLine(ptBegin, ptEnd);
  121. }
  122. else
  123. {
  124. ptBegin = ptEnd = new PointF(rect.X, rect.Y);
  125. path.AddLine(ptBegin, ptEnd);
  126. }
  127. }
  128. else//圆角
  129. {
  130. if ((cornerStyle & CornerStyle.LeftIn) != 0)
  131. {
  132. if (radius > halfHeight)
  133. path.AddArc(rect.X - radius, rect.Y, diameter, diameter, 270 + lrDegrees, -lrDegrees);
  134. else
  135. path.AddArc(rect.X - radius, rect.Y, diameter, diameter, 0, -90);
  136. }
  137. else if ((cornerStyle & CornerStyle.LeftOut) != 0)
  138. {
  139. if (radius > halfHeight)
  140. path.AddArc(rect.X - (radius - lrOffset), rect.Y, diameter, diameter, 270 - lrDegrees, lrDegrees);
  141. else
  142. path.AddArc(rect.X, rect.Y, diameter, diameter, 180, 90);
  143. }
  144. else if ((cornerStyle & CornerStyle.TopIn) != 0)
  145. {
  146. if (radius > halfWidth)
  147. path.AddArc(rect.X, rect.Y - radius, diameter, diameter, 180, -tbDegrees);
  148. else
  149. path.AddArc(rect.X, rect.Y - radius, diameter, diameter, 180, -90);
  150. }
  151. else if ((cornerStyle & CornerStyle.TopOut) != 0)
  152. {
  153. if (radius > halfWidth)
  154. path.AddArc(rect.X, rect.Y - (radius - tbOffset), diameter, diameter, 180, tbDegrees);
  155. else
  156. path.AddArc(rect.X, rect.Y, diameter, diameter, 180, 90);
  157. }
  158. else
  159. {
  160. path.AddArc(rect.X, rect.Y, diameter, diameter, 180, 90);
  161. }
  162. }
  163. #endregion
  164. #region 右上
  165. if ((roundStyle & RoundStyle.TopRight) == 0)
  166. {
  167. if ((cornerStyle & CornerStyle.RightIn) != 0)
  168. {
  169. ptBegin = new PointF(rect.Right, rect.Y);
  170. ptEnd = new PointF(rect.Right - radius, ptMiddleCenter.Y);
  171. path.AddLine(ptBegin, ptEnd);
  172. }
  173. else if ((cornerStyle & CornerStyle.RightOut) != 0)
  174. {
  175. ptBegin = new PointF(rect.Right - radius, rect.Y);
  176. ptEnd = new PointF(rect.Right, ptMiddleCenter.Y);
  177. path.AddLine(ptBegin, ptEnd);
  178. }
  179. else if ((cornerStyle & CornerStyle.TopIn) != 0)
  180. {
  181. ptBegin = new PointF(ptMiddleCenter.X, rect.Y + radius);
  182. ptEnd = new PointF(rect.Right, rect.Y);
  183. path.AddLine(ptBegin, ptEnd);
  184. }
  185. else if ((cornerStyle & CornerStyle.TopOut) != 0)
  186. {
  187. ptBegin = new PointF(ptMiddleCenter.X, rect.Y);
  188. ptEnd = new PointF(rect.Right, rect.Y + radius);
  189. path.AddLine(ptBegin, ptEnd);
  190. }
  191. else//矩形
  192. {
  193. ptBegin = ptEnd = new PointF(rect.Right, rect.Y);
  194. path.AddLine(ptBegin, ptEnd);
  195. }
  196. }
  197. else
  198. {
  199. if ((cornerStyle & CornerStyle.RightIn) != 0)
  200. {
  201. if (radius > halfHeight)
  202. path.AddArc(rect.Right - radius, rect.Y, diameter, diameter, 270, -lrDegrees);
  203. else
  204. path.AddArc(rect.Right - radius, rect.Y, diameter, diameter, 270, -90);
  205. }
  206. else if ((cornerStyle & CornerStyle.RightOut) != 0)
  207. {
  208. if (radius > halfHeight)
  209. path.AddArc(rect.Right - radius - lrOffset, rect.Y, diameter, diameter, 270, lrDegrees);
  210. else
  211. path.AddArc(rect.Right - diameter, rect.Y, diameter, diameter, 270, 90);
  212. }
  213. else if ((cornerStyle & CornerStyle.TopIn) != 0)
  214. {
  215. if (radius > halfWidth)
  216. path.AddArc(rect.Right - diameter, rect.Y - radius, diameter, diameter, tbDegrees, -tbDegrees);
  217. else
  218. path.AddArc(rect.Right - diameter, rect.Y - radius, diameter, diameter, 90, -90);
  219. }
  220. else if ((cornerStyle & CornerStyle.TopOut) != 0)
  221. {
  222. if (radius > halfWidth)
  223. path.AddArc(rect.Right - diameter, rect.Y - (radius - tbOffset), diameter, diameter, 360 - tbDegrees, tbDegrees);
  224. else
  225. path.AddArc(rect.Right - diameter, rect.Y, diameter, diameter, 270, 90);
  226. }
  227. else
  228. {
  229. path.AddArc(rect.Right - diameter, rect.Y, diameter, diameter, 270, 90);
  230. }
  231. }
  232. #endregion
  233. #region 右下
  234. if ((roundStyle & RoundStyle.BottomRight) == 0)
  235. {
  236. if ((cornerStyle & CornerStyle.RightIn) != 0)
  237. {
  238. ptBegin = new PointF(rect.Right - radius, ptMiddleCenter.Y);
  239. ptEnd = new PointF(rect.Right, rect.Bottom);
  240. path.AddLine(ptBegin, ptEnd);
  241. }
  242. else if ((cornerStyle & CornerStyle.RightOut) != 0)
  243. {
  244. ptBegin = new PointF(rect.Right, ptMiddleCenter.Y);
  245. ptEnd = new PointF(rect.Right - radius, rect.Bottom);
  246. path.AddLine(ptBegin, ptEnd);
  247. }
  248. else if ((cornerStyle & CornerStyle.BottomIn) != 0)
  249. {
  250. ptBegin = new PointF(rect.Right, rect.Bottom);
  251. ptEnd = new PointF(ptMiddleCenter.X, rect.Bottom - radius);
  252. path.AddLine(ptBegin, ptEnd);
  253. }
  254. else if ((cornerStyle & CornerStyle.BottomOut) != 0)
  255. {
  256. ptBegin = new PointF(rect.Right, rect.Bottom - radius);
  257. ptEnd = new PointF(ptMiddleCenter.X, rect.Bottom);
  258. path.AddLine(ptBegin, ptEnd);
  259. }
  260. else//矩形
  261. {
  262. ptBegin = ptEnd = new PointF(rect.Right, rect.Bottom);
  263. path.AddLine(ptBegin, ptEnd);
  264. }
  265. }
  266. else
  267. {
  268. if ((cornerStyle & CornerStyle.RightIn) != 0)
  269. {
  270. if (radius > halfHeight)
  271. path.AddArc(rect.Right - radius, rect.Bottom - diameter, diameter, diameter, 90 + lrDegrees, -lrDegrees);
  272. else
  273. path.AddArc(rect.Right - radius, rect.Bottom - diameter, diameter, diameter, 180, -90);
  274. }
  275. else if ((cornerStyle & CornerStyle.RightOut) != 0)
  276. {
  277. if (radius > halfHeight)
  278. path.AddArc(rect.Right - radius - lrOffset, rect.Bottom - diameter, diameter, diameter, 90 - lrDegrees, lrDegrees);
  279. else
  280. path.AddArc(rect.Right - diameter, rect.Bottom - diameter, diameter, diameter, 0, 90);
  281. }
  282. else if ((cornerStyle & CornerStyle.BottomIn) != 0)
  283. {
  284. if (radius > halfWidth)
  285. path.AddArc(rect.Right - diameter, rect.Bottom - radius, diameter, diameter, 0, -tbDegrees);
  286. else
  287. path.AddArc(rect.Right - diameter, rect.Bottom - radius, diameter, diameter, 0, -90);
  288. }
  289. else if ((cornerStyle & CornerStyle.BottomOut) != 0)
  290. {
  291. if (radius > halfWidth)
  292. path.AddArc(rect.Right - diameter, rect.Bottom - radius - tbOffset, diameter, diameter, 0, tbDegrees);
  293. else
  294. path.AddArc(rect.Right - diameter, rect.Bottom - diameter, diameter, diameter, 0, 90);
  295. }
  296. else
  297. {
  298. path.AddArc(rect.Right - diameter, rect.Bottom - diameter, diameter, diameter, 0, 90);
  299. }
  300. }
  301. #endregion
  302. #region 左下
  303. if ((roundStyle & RoundStyle.BottomLeft) == 0)
  304. {
  305. if ((cornerStyle & CornerStyle.LeftIn) != 0)
  306. {
  307. ptBegin = new PointF(rect.X, rect.Bottom);
  308. ptEnd = new PointF(rect.X + radius, ptMiddleCenter.Y);
  309. path.AddLine(ptBegin, ptEnd);
  310. }
  311. else if ((cornerStyle & CornerStyle.LeftOut) != 0)
  312. {
  313. ptBegin = new PointF(rect.X + radius, rect.Bottom);
  314. ptEnd = new PointF(rect.X, ptMiddleCenter.Y);
  315. path.AddLine(ptBegin, ptEnd);
  316. }
  317. else if ((cornerStyle & CornerStyle.BottomIn) != 0)
  318. {
  319. ptBegin = new PointF(ptMiddleCenter.X, rect.Bottom - radius);
  320. ptEnd = new PointF(rect.X, rect.Bottom);
  321. path.AddLine(ptBegin, ptEnd);
  322. }
  323. else if ((cornerStyle & CornerStyle.BottomOut) != 0)
  324. {
  325. ptBegin = new PointF(ptMiddleCenter.X, rect.Bottom);
  326. ptEnd = new PointF(rect.X, rect.Bottom - radius);
  327. path.AddLine(ptBegin, ptEnd);
  328. }
  329. else
  330. {
  331. ptBegin = ptEnd = new PointF(rect.X, rect.Bottom);
  332. path.AddLine(ptBegin, ptEnd);
  333. }
  334. }
  335. else
  336. {
  337. if ((cornerStyle & CornerStyle.LeftIn) != 0)
  338. {
  339. if (radius > halfHeight)
  340. path.AddArc(rect.X - radius, rect.Bottom - diameter, diameter, diameter, 90, -lrDegrees);
  341. else
  342. path.AddArc(rect.X - radius, rect.Bottom - diameter, diameter, diameter, 90, -90);
  343. }
  344. else if ((cornerStyle & CornerStyle.LeftOut) != 0)
  345. {
  346. if (radius > halfHeight)
  347. path.AddArc(rect.X - (radius - lrOffset), rect.Bottom - diameter, diameter, diameter, 90, lrDegrees);
  348. else
  349. path.AddArc(rect.X, rect.Bottom - diameter, diameter, diameter, 90, 90);
  350. }
  351. else if ((cornerStyle & CornerStyle.BottomIn) != 0)
  352. {
  353. if (radius > halfWidth)
  354. path.AddArc(rect.X, rect.Bottom - radius, diameter, diameter, 180 + tbDegrees, -tbDegrees);
  355. else
  356. path.AddArc(rect.X, rect.Bottom - radius, diameter, diameter, 270, -90);
  357. }
  358. else if ((cornerStyle & CornerStyle.BottomOut) != 0)
  359. {
  360. if (radius > halfWidth)
  361. path.AddArc(rect.X, rect.Bottom - radius - tbOffset, diameter, diameter, 180 - tbDegrees, tbDegrees);
  362. else
  363. path.AddArc(rect.X, rect.Bottom - diameter, diameter, diameter, 90, 90);
  364. }
  365. else
  366. {
  367. path.AddArc(rect.X, rect.Bottom - diameter, diameter, diameter, 90, 90);
  368. }
  369. }
  370. #endregion
  371. //闭合返回
  372. path.CloseFigure();
  373. return path;
  374. }
  375. /// <summary>
  376. /// 建立带有圆角样式和标题的路径。
  377. /// </summary>
  378. /// <param name="rect">用来简历路径的矩形。</param>
  379. /// <param name="style">圆角样式。</param>
  380. /// <param name="radius">圆角大小。</param>
  381. /// <param name="tabSize">标题大小。</param>
  382. /// <param name="tabRound">标题是否圆角。</param>
  383. /// <param name="tabRadius">标题圆角大小。</param>
  384. /// <param name="correct">是否把矩形长宽减 1,以便画出边框。</param>
  385. /// <returns>简历的路径。</returns>
  386. public static GraphicsPath CreateGroupBoxTabGraphicsPath(Rectangle rect, RoundStyle style, float radius, Size tabSize, bool tabRound, float tabRadius, bool correct)
  387. {
  388. //校正
  389. if (correct)
  390. {
  391. rect.Width--;
  392. rect.Height--;
  393. }
  394. style = (float.IsNaN(radius) || radius <= 0f) ? RoundStyle.None : style;
  395. tabRound = (float.IsNaN(tabRadius) || tabRadius <= 0f) ? false : tabRound;
  396. //定义
  397. GraphicsPath path = new GraphicsPath();
  398. Rectangle tabRect = new Rectangle(rect.Location, tabSize);
  399. float diameter = radius * 2;
  400. float tabDiameter = tabRadius * 2;
  401. Point pt;
  402. //左上
  403. if ((style & RoundStyle.TopLeft) == 0)
  404. {
  405. pt = new Point(rect.X, rect.Y);
  406. path.AddLine(pt, pt);
  407. }
  408. else
  409. {
  410. path.AddArc(rect.X, rect.Y, diameter, diameter, 180, 90);
  411. }
  412. //Tab右上
  413. if (tabRound)
  414. {
  415. if (tabRadius > tabRect.Height)//不到90度
  416. {
  417. double radians = Math.Acos((tabRadius - tabRect.Height) / tabRadius);
  418. path.AddArc((float)(tabRect.Right - tabRadius * Math.Sin(radians) - tabRadius),
  419. tabRect.Y, tabDiameter, tabDiameter, 270, (float)MathEx.ToDegrees(radians));
  420. }
  421. else//到90度
  422. {
  423. path.AddArc(tabRect.Right - tabDiameter, tabRect.Y, tabDiameter, tabDiameter, 270, 90);
  424. //Tab右下
  425. pt = new Point(tabRect.Right, tabRect.Bottom);
  426. path.AddLine(pt, pt);
  427. }
  428. }
  429. else
  430. {
  431. pt = new Point(tabRect.Right, tabRect.Y);
  432. path.AddLine(pt, pt);
  433. //Tab右下
  434. pt = new Point(tabRect.Right, tabRect.Bottom);
  435. path.AddLine(pt, pt);
  436. }
  437. //右上
  438. if ((style & RoundStyle.TopRight) == 0)
  439. {
  440. pt = new Point(rect.Right, tabRect.Bottom);
  441. path.AddLine(pt, pt);
  442. }
  443. else
  444. {
  445. path.AddArc(rect.Right - diameter, tabRect.Bottom, diameter, diameter, 270, 90);
  446. }
  447. //右下
  448. if ((style & RoundStyle.BottomRight) == 0)
  449. {
  450. pt = new Point(rect.Right, rect.Bottom);
  451. path.AddLine(pt, pt);
  452. }
  453. else
  454. {
  455. path.AddArc(rect.Right - diameter, rect.Bottom - diameter, diameter, diameter, 0, 90);
  456. }
  457. //左下
  458. if ((style & RoundStyle.BottomLeft) == 0)
  459. {
  460. pt = new Point(rect.X, rect.Bottom);
  461. path.AddLine(pt, pt);
  462. }
  463. else
  464. {
  465. path.AddArc(rect.X, rect.Bottom - diameter, diameter, diameter, 90, 90);
  466. }
  467. //闭合返回
  468. path.CloseFigure();
  469. return path;
  470. }
  471. }
  472. }