技术看点

  • WinForm自定义控件的使用
  • WinForm单窗体应用如何模块化

需求及效果

又来一波 C# GDI自定义控件show 。这个控件已经使用几年了,最近找出来重构一下。原来是没有边框的,那么导致导航的功能不是很突出。本来想加个效果:在执行单击时显示Loading动画,在执行完单击事件后恢复原样。这就是网页里见到的局部刷新,Ajax常用的场景。无奈要下班了,还没弄出来。需求来自几年前一个智能储物柜项目,人机界面有个美工设计好的效果图,为了省事和通用,需要一个透明的按钮来实现导航的任务。就是控件只是设计时可见,运行时不可见。

关键点说明

1)、GraphicsPath实现矩形的圆角羽化处理

  1. using (GraphicsPath path = new GraphicsPath())
  2. {
  3. #region 羽化,圆角处理
  4. path.StartFigure();
  5. path.AddArc(new Rectangle(new Point(rect.X, rect.Y), new Size( * Radius, * Radius)), , );
  6. path.AddLine(new Point(rect.X + Radius, rect.Y), new Point(rect.Right - Radius, rect.Y));
  7. path.AddArc(new Rectangle(new Point(rect.Right - * Radius, rect.Y), new Size( * Radius, * Radius)), , );
  8. path.AddLine(new Point(rect.Right, rect.Y + Radius), new Point(rect.Right, rect.Bottom - Radius));
  9. path.AddArc(new Rectangle(new Point(rect.Right - * Radius, rect.Bottom - * Radius), new Size( * Radius, * Radius)), , );
  10. path.AddLine(new Point(rect.Right - Radius, rect.Bottom), new Point(rect.X + Radius, rect.Bottom));
  11. path.AddArc(new Rectangle(new Point(rect.X, rect.Bottom - * Radius), new Size( * Radius, * Radius)), , );
  12. path.AddLine(new Point(rect.X, rect.Bottom - Radius), new Point(rect.X, rect.Y + Radius));
  13. path.CloseFigure();
  14. #endregion

要点就是画几段弧线和矩形连接起来。透明就是用了Color.FromArgb加上透明度,然后填充GraphicsPath形成透明区域。

  1. g.FillPath(new SolidBrush(Color.FromArgb(, BackColor)), path);

2)、单窗体应用如何模块化

窗体只有一个,但操作界面好多个,由于是无人值守的应用。那么老是切换窗体操作是非常不方便的。工作区域是一个容器Panel,把每个操作界面定义成一个Panel作为只容器。

  1. public partial class DepositBizPanel : UserControl
  2. {
  3. private BackgroundStyle backgroundStyle = BackgroundStyle.Green;
  4. /// <summary>
  5. /// 主题风格
  6. /// </summary>
  7. public BackgroundStyle BackgroundStyle
  8. {
  9. get { return backgroundStyle; }
  10. set
  11. {
  12. backgroundStyle = value;
  13. switch (value)
  14. {
  15. case GreenlandExpressBox.BackgroundStyle.Blue:
  16. BackgroundImage = Properties.Resources.jbblue;
  17. break;
  18. case GreenlandExpressBox.BackgroundStyle.Orange:
  19. BackgroundImage = Properties.Resources.jborange;
  20. break;
  21. case GreenlandExpressBox.BackgroundStyle.Green:
  22. BackgroundImage = Properties.Resources.jbgreen;
  23. break;
  24. }
  25. Invalidate();
  26. }
  27. }
  28.  
  29. public Panel ParentPanel
  30. {
  31. get;
  32. set;
  33. }
  34.  
  35. public Bitmap QR_Barcode
  36. {
  37. get { return (Bitmap)pbxBarcode.Image; }
  38. set { pbxBarcode.Image = value; }
  39. }
  40.  
  41. public DialogResult PanelDiagResult
  42. {
  43. get;
  44. set;
  45. }
  46.  
  47. public DepositBizPanel(Panel parent, Bitmap barcode, BackgroundStyle style)
  48. {
  49. InitializeComponent();
  50. DoubleBuffered = true;
  51. ParentPanel = parent;
  52. QR_Barcode = barcode;
  53. BackgroundStyle = style;
  54. }
  55.  
  56. private void btnback_Click(object sender, EventArgs e)
  57. {
  58. foreach (Control panel in ParentPanel.Controls)
  59. {
  60. if (panel is DepositBizPanel)
  61. {
  62. ParentPanel.Controls.Remove(panel);
  63. PanelDiagResult = DialogResult.Cancel;
  64. break;
  65. }
  66. }
  67. }
  68.  
  69. private void btnprocessnext_Click(object sender, EventArgs e)
  70. {
  71. foreach (Control panel in ParentPanel.Controls)
  72. {
  73. if (panel is DepositBizPanel)
  74. {
  75. ParentPanel.Controls.Remove(panel);
  76. PanelDiagResult = DialogResult.OK;
  77. break;
  78. }
  79. }
  80. }
  81. }

人机操作界面例子

透明按钮自定义控件全部代码

自定义按钮:

  1. /// <summary>
  2. /// Cool透明自定义按钮
  3. /// </summary>
  4. public partial class CoolTransparentButton : UserControl
  5. {
  6. private Size iconSize = new Size(, );
  7. public Size IconSize
  8. {
  9. get
  10. {
  11. return iconSize;
  12. }
  13. set
  14. {
  15. iconSize = value;
  16. Invalidate();
  17. }
  18. }
  19. private string _ButtonText;
  20. public string ButtonText
  21. {
  22. get { return _ButtonText; }
  23. set
  24. {
  25. _ButtonText = value;
  26. Invalidate();
  27. }
  28. }
  29. protected Image _IconImage;
  30. public Image IconImage
  31. {
  32. get
  33. {
  34. return _IconImage;
  35. }
  36. set
  37. {
  38. _IconImage = value;
  39. Invalidate();
  40. }
  41. }
  42. private bool _FocseActived = false;
  43. private Color _BorderColor = Color.White;
  44. public Color BorderColor
  45. {
  46. get
  47. {
  48. return _BorderColor;
  49. }
  50. set
  51. {
  52. _BorderColor = value;
  53. Invalidate();
  54. }
  55. }
  56. private int _Radius = ;
  57. public int Radius
  58. {
  59. get
  60. {
  61. return _Radius;
  62. }
  63. set
  64. {
  65. _Radius = value;
  66. Invalidate();
  67. }
  68. }
  69. private bool ifDrawBorderWhenLostFocse = true;
  70. /// <summary>
  71. /// 失去焦点是否画边框
  72. /// </summary>
  73. public bool IfDrawBorderWhenLostFocse
  74. {
  75. get
  76. {
  77. return ifDrawBorderWhenLostFocse;
  78. }
  79. set
  80. {
  81. ifDrawBorderWhenLostFocse = value;
  82. Invalidate();
  83. }
  84. }
  85. /// <summary>
  86. /// 是否处于激活状态(焦点)
  87. /// </summary>
  88. public bool FocseActived
  89. {
  90. get { return _FocseActived; }
  91. set
  92. {
  93. _FocseActived = value;
  94. Invalidate();
  95. }
  96. }
  97. public CoolTransparentButton()
  98. {
  99. DoubleBuffered = true;
  100. BackColor = Color.Transparent;
  101. SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.OptimizedDoubleBuffer | ControlStyles.ResizeRedraw, true);
  102. SetStyle(ControlStyles.Opaque, false);
  103. UpdateStyles();
  104. }
  105. protected override void OnPaint(PaintEventArgs e)
  106. {
  107. var rect = ClientRectangle;
  108. rect.Inflate(-, -);
  109. Graphics g = e.Graphics;
  110. g.SmoothingMode = SmoothingMode.HighQuality;
  111. using (GraphicsPath path = new GraphicsPath())
  112. {
  113. #region 羽化,圆角处理
  114. path.StartFigure();
  115. path.AddArc(new Rectangle(new Point(rect.X, rect.Y), new Size( * Radius, * Radius)), , );
  116. path.AddLine(new Point(rect.X + Radius, rect.Y), new Point(rect.Right - Radius, rect.Y));
  117. path.AddArc(new Rectangle(new Point(rect.Right - * Radius, rect.Y), new Size( * Radius, * Radius)), , );
  118. path.AddLine(new Point(rect.Right, rect.Y + Radius), new Point(rect.Right, rect.Bottom - Radius));
  119. path.AddArc(new Rectangle(new Point(rect.Right - * Radius, rect.Bottom - * Radius), new Size( * Radius, * Radius)), , );
  120. path.AddLine(new Point(rect.Right - Radius, rect.Bottom), new Point(rect.X + Radius, rect.Bottom));
  121. path.AddArc(new Rectangle(new Point(rect.X, rect.Bottom - * Radius), new Size( * Radius, * Radius)), , );
  122. path.AddLine(new Point(rect.X, rect.Bottom - Radius), new Point(rect.X, rect.Y + Radius));
  123. path.CloseFigure();
  124. #endregion
  125. if (!FocseActived)
  126. {
  127. if (ifDrawBorderWhenLostFocse)
  128. g.DrawPath(new Pen(Color.Gray, ), path);
  129. g.FillPath(new SolidBrush(Color.FromArgb(, BackColor)), path);
  130. }
  131. else
  132. {
  133. g.DrawPath(new Pen(BorderColor, ), path);
  134. rect.Inflate(-, -);
  135. g.FillPath(new SolidBrush(Color.FromArgb(, BackColor)), path);
  136. }
  137. #region 画文本
  138. g.SmoothingMode = SmoothingMode.AntiAlias;
  139. if (IconImage != null)
  140. {
  141. Rectangle rc = new Rectangle((Width - ) / , , IconSize.Width, IconSize.Height);
  142. g.DrawImage(IconImage, rc);
  143. }
  144. if (!string.IsNullOrEmpty(ButtonText))
  145. {
  146. using (StringFormat f = new StringFormat())
  147. {
  148. Rectangle rectTxt = new Rectangle(, (Height - ) / , Width, );
  149. f.Alignment = StringAlignment.Center;// 水平居中对齐
  150. f.LineAlignment = StringAlignment.Center; // 垂直居中对齐
  151. f.FormatFlags = StringFormatFlags.NoWrap;// 设置为单行文本
  152. SolidBrush fb = new SolidBrush(this.ForeColor); // 绘制文本
  153. e.Graphics.DrawString(ButtonText, new Font("微软雅黑", 16F, FontStyle.Bold), fb, rectTxt, f);
  154. }
  155. }
  156. #endregion
  157. }
  158. }
  159. protected override void OnMouseHover(EventArgs e)
  160. {
  161. FocseActived = true;
  162. }
  163. protected override void OnMouseLeave(EventArgs e)
  164. {
  165. FocseActived = false;
  166. }
  167. protected override void OnEnter(EventArgs e)
  168. {
  169. FocseActived = true;
  170. }
  171. protected override void OnLeave(EventArgs e)
  172. {
  173. FocseActived = false;
  174. }
  175. }

注释不是很多,如有需要拿走不谢.

C#Winform 自定义透明按钮和单窗体模块化实现的更多相关文章

  1. c#winform自定义窗体,重绘标题栏,自定义控件学习

    c#winform自定义窗体,重绘标题栏 虽然现在都在说winform窗体太丑了,但是我也能尽量让桌面应用程序漂亮那么一点点话不多说,先上图 重绘标题栏先将原生窗体设置成无边框,FormBoderSt ...

  2. WPF权限控制——【3】数据库、自定义弹窗、表单验证

    你相信"物竞天择,适者生存"这样的学说吗?但是我们今天却在提倡"尊老爱幼,救死扶伤",帮助并救护弱势群体:第二次世界大战期间,希特勒认为自己是优等民族,劣势民族 ...

  3. Winform的"透明"

    手头目前的一个项目(.Net4.0)中有这样一个需求:在程序中要进行视频采集,并且要在视频影像区域进行绘图编辑,对绘图能进行拉伸,拖拽和删除.从需求来看,必须得在视频影像区的上方盖一层画布才能这么操作 ...

  4. OC导航栏自定义返回按钮

    [iOS]让我们一次性解决导航栏的所有问题 在默认情况下,导航栏返回按钮长这个样子   导航栏默认返回按钮 导航栏左上角的返回按钮,其文本默认为上一个ViewController的标题,如果上一个Vi ...

  5. 自定义常用input表单元素三:纯css实现自定义Switch开关按钮

    自定义常用input表单元素的第三篇,自定义一个Switch开关,表面上看是和input没关系,其实这里采用的是checkbox的checked值的切换.同样,采用css伪类和"+" ...

  6. VB6史无前例的子类化之透明按钮

    [原创文章,转发请保留版权信息] 作者:mezstd 文章地址:http://www.cnblogs.com/imez/p/3299728.html 效果图: 请原谅笔者无耻地称之为史无前例,至少在笔 ...

  7. WPF 无边框透明按钮

    在实际开发过程中,有时候要设置一个无边框的按钮,或者无边框的透明按钮. 按钮效果如下: 1.当你应用telerik组件中的Button时,这个直接就可以设置 telerik:StyleManager. ...

  8. Mono自定义图片按钮

    首先,我们编写一个MyImageButton类,继承自LinearLayout public class MyPhoneImageButton:LinearLayout { private Image ...

  9. SharePoint 2013 关于自定义显示列表表单的bug

    1.在SharePoint 2013中,我们隐藏列表Dispform页面的ListFormWebPart部件,转而使用自定义显示列表表单进行展示,因为这样更容易定制我们需要的显示: 2.之后发现文件夹 ...

随机推荐

  1. Java爬虫--Https绕过证书

    https网站服务器都是有证书的. 是由网站自己的服务器签发的,并不被浏览器或操作系统广泛接受. 在使用CloseableHttpClient时经常遇到证书错误(知乎的网站就是这样) 现在需要SSL绕 ...

  2. 谈谈单元測试之(二):測试工具 JUnit 3

    前言 上一篇文章<为什么要进行烦人的单元測试?>讨论了一下现阶段软件开发中,程序猿们測试情况的现状.这篇文章中,我打算介绍一下单元測试的工具(插件).而且推荐大家以后在开发中,真正的用上单 ...

  3. iWeb峰会(HTML5峰会)2015年7月19日上海站会后感想

         上周日专门从南京跑到上海參加了iWeb峰会(HTML5峰会),感觉这一天去的挺值的.几个演讲都挺精彩,干货不少啊.       总体感觉随着2014年HTML5标准的终于定稿,最近HTML5 ...

  4. poj 2299 Ultra-QuickSort(树状数组求逆序数+离散化)

    题目链接:http://poj.org/problem?id=2299 Description In this problem, you have to analyze a particular so ...

  5. UVA 11324 The Largest Clique(强连通分量+缩点DAG的DP)

    题意:给定一个有向图,求出一个最大的结点集,这个节点集中的随意两个点之间至少一个能到达还有一个点. 思路:假设一个点在这个节点集中,那么它所在的强连通分量中的点一定所有在这个节点集中,反之亦然, 求出 ...

  6. 关于使用Xcode9.0使用[UIImage imageNamed:]返回null的问题

    最近升级Xcode9.0,没少折腾,再加上iOS11出现的问题,又要适配一些奇怪的问题.这都没啥,但是如果Xcode出问题,那问题可真是难找.因为习惯的操作潜意思的告诉自己这样做是不会错的. 在Xco ...

  7. [array] leetcode - 34. Search for a Range - Medium

    leetcode - 34. Search for a Range - Medium descrition Given an array of integers sorted in ascending ...

  8. xml文件解析(使用解析器)

    一.Xml解析,解析xml并封装到list中的javabean中 OM是用与平台和语言无关的方式表示XML文档的官方W3C标准.DOM是以层次结构组织的节点或信息片断的集合.这个层次结构允许开发人员在 ...

  9. 初探XRebel

    一.什么是XRebel? 1.介绍 XRebel 是不间断运行在 web 应用的交互式分析器.可以看到网页上的每一个操作在前端以及服务端.数据库.网络传输都花费多少时间,当发现问题会在浏览器中显示警告 ...

  10. ExperDot的博客目录导航

    最近活动 我更新了博客!粒子系统:从零开始画一棵树 Github:[ UWP ] [ JavaScript ] 自然编程  奇幻元纪 上帝创世篇:如何画一颗静态树 女娲补天篇:仿人工拼接碎片 吴刚伐桂 ...