RPanel.cs 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419
  1. using System;
  2. using System.Collections.Generic;
  3. using System.ComponentModel;
  4. using System.Drawing.Drawing2D;
  5. using System.Drawing;
  6. using System.Linq;
  7. using System.Text;
  8. using System.Threading.Tasks;
  9. using static System.Windows.Forms.VisualStyles.VisualStyleElement.TextBox;
  10. using System.Windows.Forms;
  11. using ZedGraph;
  12. namespace ImpulseVision
  13. {
  14. public class RPanel : Panel
  15. {
  16. #region -- Свойства --
  17. [Description("Цвет обводки (границы) кнопки")]
  18. public Color BorderColor { get; set; } = Color.Tomato;
  19. [Description("Указывает, включено ли использование отдельного цвета обводки (границы) кнопки")]
  20. public bool BorderColorEnabled { get; set; } = false;
  21. [Description("Цвет обводки (границы) кнопки при наведении курсора")]
  22. public Color BorderColorOnHover { get; set; } = Color.Tomato;
  23. [Description("Указывает, включено ли использование отдельного цвета обводки (границы) кнопки при наведении курсора")]
  24. public bool BorderColorOnHoverEnabled { get; set; } = false;
  25. [Description("Дополнительный фоновый цвет кнопки используемый для создания градиента (При BackColorGradientEnabled = true)")]
  26. public Color BackColorAdditional { get; set; } = Color.Gray;
  27. [Description("Указывает, включен ли градинт кнопки")]
  28. public bool BackColorGradientEnabled { get; set; } = false;
  29. [Description("Определяет направление линейного градиента шапки")]
  30. public LinearGradientMode BackColorGradientMode { get; set; } = LinearGradientMode.Horizontal;
  31. [Description("Текст, отображаемый при наведении курсора")]
  32. public string TextHover { get; set; }
  33. private bool roundingEnable = false;
  34. [Description("Вкл/Выкл закругление объекта")]
  35. public bool RoundingEnable
  36. {
  37. get => roundingEnable;
  38. set
  39. {
  40. roundingEnable = value;
  41. Refresh();
  42. }
  43. }
  44. private int roundingPercent = 100;
  45. [DisplayName("Rounding [%]")]
  46. [DefaultValue(100)]
  47. [Description("Указывает радиус закругления объекта в процентном соотношении")]
  48. public int Rounding
  49. {
  50. get => roundingPercent;
  51. set
  52. {
  53. if (value >= 0 && value <= 100)
  54. {
  55. roundingPercent = value;
  56. Refresh();
  57. }
  58. }
  59. }
  60. [Description("Вкл/Выкл эффект волны по нажатию кнопки курсором.")]
  61. public bool UseRippleEffect { get; set; } = true;
  62. [Description("Цвет эффекта волны по нажатию кнопки курсором")]
  63. public Color RippleColor { get; set; } = Color.Black;
  64. [Description("Вкл/Выкл эффект нажатия кнопки.")]
  65. public bool UseDownPressEffectOnClick { get; set; }
  66. public bool UseZoomEffectOnHover { get; set; }
  67. public override string Text
  68. {
  69. get { return base.Text; }
  70. set
  71. {
  72. base.Text = value;
  73. Invalidate();
  74. }
  75. }
  76. #endregion
  77. #region -- Переменные --
  78. private StringFormat SF = new StringFormat();
  79. private bool MouseEntered = false;
  80. private bool MousePressed = false;
  81. Animation CurtainButtonAnim = new Animation();
  82. //Animation RippleButtonAnim = new Animation();
  83. Animation TextSlideAnim = new Animation();
  84. Dictionary<Animation, Rectangle> RippleButtonAnimDic = new Dictionary<Animation, Rectangle>();
  85. Point ClickLocation = new Point();
  86. #endregion
  87. public RPanel()
  88. {
  89. SetStyle(
  90. ControlStyles.AllPaintingInWmPaint |
  91. ControlStyles.OptimizedDoubleBuffer |
  92. ControlStyles.ResizeRedraw |
  93. ControlStyles.SupportsTransparentBackColor |
  94. ControlStyles.UserPaint |
  95. ControlStyles.Opaque |
  96. ControlStyles.Selectable |
  97. ControlStyles.UserMouse |
  98. ControlStyles.EnableNotifyMessage,
  99. true);
  100. DoubleBuffered = true;
  101. Size = new Size(100, 30);
  102. Font = new Font("Verdana", 8.25F, FontStyle.Regular);
  103. Cursor = Cursors.Hand;
  104. BackColor = Color.Tomato;
  105. BorderColor = BackColor;
  106. ForeColor = Color.White;
  107. SF.Alignment = StringAlignment.Center;
  108. SF.LineAlignment = StringAlignment.Center;
  109. }
  110. protected override void OnPaint(PaintEventArgs e)
  111. {
  112. base.OnPaint(e);
  113. Graphics graph = e.Graphics;
  114. graph.SmoothingMode = SmoothingMode.HighQuality;
  115. graph.InterpolationMode = InterpolationMode.HighQualityBicubic;
  116. graph.PixelOffsetMode = PixelOffsetMode.HighQuality;
  117. graph.SmoothingMode = SmoothingMode.AntiAlias;
  118. graph.Clear(Parent.BackColor);
  119. Rectangle rect = new Rectangle(0, 0, Width - 1, Height - 1);
  120. Rectangle rectCurtain = new Rectangle(0, 0, (int)CurtainButtonAnim.Value, Height - 1);
  121. Rectangle rectText = new Rectangle((int)TextSlideAnim.Value, rect.Y, rect.Width, rect.Height);
  122. Rectangle rectTextHover = new Rectangle((int)TextSlideAnim.Value - rect.Width, rect.Y, rect.Width, rect.Height);
  123. // Закругление
  124. float roundingValue = 0.1F;
  125. if (RoundingEnable && roundingPercent > 0)
  126. {
  127. roundingValue = Height / 100F * roundingPercent;
  128. }
  129. GraphicsPath rectPath = Drawer.RoundedRectangle(rect, roundingValue);
  130. Region = new Region(rectPath);
  131. graph.Clear(Parent.BackColor);
  132. Brush headerBrush = new SolidBrush(BackColor);
  133. if (BackColorGradientEnabled)
  134. {
  135. if (rect.Width > 0 && rect.Height > 0)
  136. headerBrush = new LinearGradientBrush(rect, BackColor, BackColorAdditional, BackColorGradientMode);
  137. }
  138. Brush borderBrush = headerBrush;
  139. if (BorderColorEnabled)
  140. {
  141. borderBrush = new SolidBrush(BorderColor);
  142. if (MouseEntered && BorderColorOnHoverEnabled)
  143. borderBrush = new SolidBrush(BorderColorOnHover);
  144. }
  145. // Основной прямоугольник (Фон)
  146. graph.DrawPath(new Pen(borderBrush), rectPath);
  147. graph.FillPath(headerBrush, rectPath);
  148. graph.SetClip(rectPath);
  149. // Рисуем доп. прямоугольник (Наша шторка)
  150. graph.DrawRectangle(new Pen(Color.FromArgb(60, Color.White)), rectCurtain);
  151. graph.FillRectangle(new SolidBrush(Color.FromArgb(60, Color.White)), rectCurtain);
  152. //if (UseRippleEffect == false)
  153. //{
  154. // // Стандартное рисование праямоугольника при клике
  155. // if (MousePressed)
  156. // {
  157. // graph.DrawRectangle(new Pen(Color.FromArgb(30, Color.Black)), rect);
  158. // graph.FillRectangle(new SolidBrush(Color.FromArgb(30, Color.Black)), rect);
  159. // }
  160. //}
  161. //else
  162. //{
  163. // // Ripple Effect - Волна
  164. // for (int i = 0; i < RippleButtonAnimDic.Count; i++)
  165. // {
  166. // KeyValuePair<Animation, Rectangle> animRect = RippleButtonAnimDic.ToList()[i];
  167. // Animation MultiRippleButtonAnim = animRect.Key;
  168. // Rectangle rectMultiRipple = animRect.Value;
  169. // rectMultiRipple = new Rectangle(
  170. // ClickLocation.X - (int)MultiRippleButtonAnim.Value / 2,
  171. // ClickLocation.Y - (int)MultiRippleButtonAnim.Value / 2,
  172. // (int)MultiRippleButtonAnim.Value,
  173. // (int)MultiRippleButtonAnim.Value
  174. // );
  175. // if (MultiRippleButtonAnim.Value > 0 && MultiRippleButtonAnim.Value < MultiRippleButtonAnim.TargetValue)
  176. // {
  177. // graph.DrawEllipse(new Pen(Color.FromArgb(30, RippleColor)), rectMultiRipple);
  178. // graph.FillEllipse(new SolidBrush(Color.FromArgb(30, RippleColor)), rectMultiRipple);
  179. // }
  180. // else if (MultiRippleButtonAnim.Value == MultiRippleButtonAnim.TargetValue)
  181. // {
  182. // if (MousePressed == false)
  183. // {
  184. // MultiRippleButtonAnim.Value = 0;
  185. // MultiRippleButtonAnim.Status = Animation.AnimationStatus.Completed;
  186. // }
  187. // else
  188. // {
  189. // if (i == RippleButtonAnimDic.Count - 1)
  190. // {
  191. // graph.DrawEllipse(new Pen(Color.FromArgb(30, RippleColor)), rectMultiRipple);
  192. // graph.FillEllipse(new SolidBrush(Color.FromArgb(30, RippleColor)), rectMultiRipple);
  193. // }
  194. // }
  195. // }
  196. // }
  197. // // Удаляем из очереди выполненные анимации волны
  198. // List<Animation> completedRippleAnimations = RippleButtonAnimDic.Keys.ToList().FindAll(x => x.Status == Animation.AnimationStatus.Completed);
  199. // for (int i = 0; i < completedRippleAnimations.Count; i++)
  200. // RippleButtonAnimDic.Remove(completedRippleAnimations[i]);
  201. }
  202. // Ripple Effect - Волна
  203. //////if (RippleButtonAnim.Value > 0 && RippleButtonAnim.Value < RippleButtonAnim.TargetValue)
  204. //////{
  205. ////// graph.DrawEllipse(new Pen(Color.FromArgb(30, Color.Black)), rectRipple);
  206. ////// graph.FillEllipse(new SolidBrush(Color.FromArgb(30, Color.Black)), rectRipple);
  207. //////}
  208. //////else if (RippleButtonAnim.Value == RippleButtonAnim.TargetValue)
  209. //////{
  210. ////// // Тут можно добавить проверку MousePressed, если false тогда обнуляем
  211. ////// if (MousePressed == false)
  212. ////// {
  213. ////// RippleButtonAnim.Value = 0;
  214. ////// }
  215. ////// else
  216. ////// {
  217. ////// graph.DrawEllipse(new Pen(Color.FromArgb(30, Color.Black)), rectRipple);
  218. ////// graph.FillEllipse(new SolidBrush(Color.FromArgb(30, Color.Black)), rectRipple);
  219. ////// }
  220. //////}
  221. // Рисуем текст
  222. //if (string.IsNullOrEmpty(TextHover))
  223. //{
  224. // graph.DrawString(Text, Font, new SolidBrush(ForeColor), rect, SF);
  225. //}
  226. //else
  227. //{
  228. // graph.DrawString(Text, Font, new SolidBrush(ForeColor), rectText, SF);
  229. // graph.DrawString(TextHover, Font, new SolidBrush(ForeColor), rectTextHover, SF);
  230. //}
  231. }
  232. /*
  233. private void TextSlideAction()
  234. {
  235. if (MouseEntered)
  236. {
  237. TextSlideAnim = new Animation("TextSlide_" + Handle, Invalidate, TextSlideAnim.Value, Width - 1);
  238. }
  239. else
  240. {
  241. TextSlideAnim = new Animation("TextSlide_" + Handle, Invalidate, TextSlideAnim.Value, 0);
  242. }
  243. TextSlideAnim.StepDivider = 8;
  244. Animator.Request(TextSlideAnim, true);
  245. }
  246. //private void ButtonRippleAction()
  247. //{
  248. // RippleButtonAnim = new Animation("ButtonRipple_" + Handle, Invalidate, 0, Width * 2);
  249. // RippleButtonAnim.StepDivider = 14;
  250. // Animator.Request(RippleButtonAnim, true);
  251. //}
  252. */
  253. /*
  254. private void ButtonMultiRippleAction()
  255. {
  256. Animation MultiRippleButtonAnim = new Animation("ButtonMultiRipple_" + Handle + DateTime.Now.Millisecond, Invalidate, 0, Width * 3);
  257. MultiRippleButtonAnim.StepDivider = 20;
  258. Animator.Request(MultiRippleButtonAnim);
  259. RippleButtonAnimDic.Add(MultiRippleButtonAnim, new Rectangle());
  260. }
  261. */
  262. /*
  263. private void ButtonCurtainAction()
  264. {
  265. if (MouseEntered)
  266. {
  267. CurtainButtonAnim = new Animation("ButtonCurtain_" + Handle, Invalidate, CurtainButtonAnim.Value, Width - 1);
  268. }
  269. else
  270. {
  271. CurtainButtonAnim = new Animation("ButtonCurtain_" + Handle, Invalidate, CurtainButtonAnim.Value, 0);
  272. }
  273. CurtainButtonAnim.StepDivider = 8;
  274. Animator.Request(CurtainButtonAnim, true);
  275. }
  276. */
  277. /*
  278. protected override void OnMouseEnter(EventArgs e)
  279. {
  280. base.OnMouseEnter(e);
  281. MouseEntered = true;
  282. if (UseZoomEffectOnHover)
  283. {
  284. Rectangle buttonRect = new Rectangle(Location, Size);
  285. buttonRect.Inflate(1, 1);
  286. Location = buttonRect.Location;
  287. Size = buttonRect.Size;
  288. }
  289. ButtonCurtainAction();
  290. TextSlideAction();
  291. }
  292. */
  293. /*
  294. protected override void OnMouseLeave(EventArgs e)
  295. {
  296. base.OnMouseLeave(e);
  297. MouseEntered = false;
  298. if (UseZoomEffectOnHover)
  299. {
  300. Rectangle buttonRect = new Rectangle(Location, Size);
  301. buttonRect.Inflate(-1, -1);
  302. Location = buttonRect.Location;
  303. Size = buttonRect.Size;
  304. }
  305. ButtonCurtainAction();
  306. TextSlideAction();
  307. }
  308. */
  309. /*
  310. protected override void OnMouseDown(MouseEventArgs e)
  311. {
  312. base.OnMouseDown(e);
  313. MousePressed = true;
  314. CurtainButtonAnim.Value = CurtainButtonAnim.TargetValue;
  315. ClickLocation = e.Location;
  316. //ButtonRippleAction();
  317. ButtonMultiRippleAction();
  318. if (UseDownPressEffectOnClick) Location = new Point(Location.X, Location.Y + 2);
  319. Focus();
  320. }
  321. */
  322. /*
  323. protected override void OnMouseUp(MouseEventArgs e)
  324. {
  325. base.OnMouseUp(e);
  326. MousePressed = false;
  327. Invalidate();
  328. if (UseDownPressEffectOnClick) Location = new Point(Location.X, Location.Y - 2);
  329. }
  330. */
  331. /*
  332. protected override void OnTextChanged(EventArgs e)
  333. {
  334. base.OnTextChanged(e);
  335. //Invalidate();
  336. }
  337. */
  338. /*
  339. protected override void OnParentBackColorChanged(EventArgs e)
  340. {
  341. Invalidate();
  342. base.OnParentBackColorChanged(e);
  343. }
  344. */
  345. }