WinForm所见即所得的UI设计框架,开发效率确实有所提升,同时降低了编程门槛,让WinForm更普及。拖拖拽拽就能设计出一个界面,那么我们拖拽的这些东西是什么?它们是什么原理?。
WinForm我觉得很好的一点是,把所有东西都对像化(毕竟C#是面向对象的语言),包括可视化的窗体,控件等,当然有的控件在运行时是能看见的,比如按钮,文本框,下拉列表框等等,还有一类是在运时看不见的,比如Timers,FileSystemWatcher等。这些全都构建成了对象,那么看得见的控件是怎么看得见的呢?答案是绘制出来的,画出来才能看得见。是用GDI+技术画出来的。
为了能够让大家更深入的理解,我们现在画一个Switch控件,Switch是苹果体系里的控件,在WinForm中,系统控件是没有的。Switch的作用非常像CheckBox,所以我们就参照CheckBoxRenderer来画,只不过画的形状不一样,具体代码如下:
using System; using System.Collections.Generic; using System.Drawing.Drawing2D; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms.VisualStyles; namespace WinFormDemo02 { public class Switch : Control { private Rectangle textRectangleValue = new Rectangle(); private CheckBoxState state = CheckBoxState.UncheckedNormal; public Switch(): base() { this.Location = new Point(50, 50); this.Size = new Size(50, 25); this.Font = SystemFonts.IconTitleFont; DoubleBuffered = true; SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.ResizeRedraw | ControlStyles.AllPaintingInWmPaint, true); } public bool Checked { get; set; } = false; void DrawSwitch(Graphics g) { var x = 0; var y = 0; var width = 25; g.SmoothingMode = SmoothingMode.HighQuality; g.PixelOffsetMode = PixelOffsetMode.HighQuality; g.InterpolationMode = InterpolationMode.High; g.CompositingQuality = CompositingQuality.HighQuality; SolidBrush brush; if (Checked) { brush = new SolidBrush(Color.MediumSeaGreen); } else { brush = new SolidBrush(Color.DarkRed); } g.FillPie(brush, new Rectangle(x, y, width, width), 90, 180); g.FillRectangle(brush, new Rectangle(x + width / 2 - 1, y, width, width)); g.FillPie(brush, new Rectangle(x + width - 2, y, width, width), -90, 180); if (Checked) { var selectBrush = new SolidBrush(Color.White); g.FillEllipse(selectBrush, new Rectangle(x + 2, y + 2, width - 4, width - 4)); } else { var selectBrush = new SolidBrush(Color.White); g.FillEllipse(selectBrush, new Rectangle(x + width, y + 2, width - 4, width - 4)); } } public Rectangle TextRectangle { get { using (Graphics g = this.CreateGraphics()) { textRectangleValue.X = ClientRectangle.X + CheckBoxRenderer.GetGlyphSize(g, CheckBoxState.UncheckedNormal).Width; textRectangleValue.Y = ClientRectangle.Y; textRectangleValue.Width = ClientRectangle.Width - CheckBoxRenderer.GetGlyphSize(g, CheckBoxState.UncheckedNormal).Width; textRectangleValue.Height = ClientRectangle.Height; } return textRectangleValue; } } protected override void OnPaint(PaintEventArgs e) { DrawSwitch(e.Graphics); base.OnPaint(e); } public event EventHandler CheckedChanged; protected override void onm ouseDown(MouseEventArgs e) { base.OnMouseDown(e); if (!Checked) { Checked = true; state = CheckBoxState.CheckedPressed; Invalidate(); } else { Checked = false; state = CheckBoxState.UncheckedNormal; Invalidate(); } CheckedChanged(this,new EventArgs()); } protected override void onm ouseHover(EventArgs e) { base.OnMouseHover(e); state = Checked ? CheckBoxState.CheckedHot : CheckBoxState.UncheckedHot; Invalidate(); } protected override void onm ouseUp(MouseEventArgs e) { base.OnMouseUp(e); this.OnMouseHover(e); } protected override void onm ouseLeave(EventArgs e) { base.OnMouseLeave(e); state = Checked ? CheckBoxState.CheckedNormal : CheckBoxState.UncheckedNormal; Invalidate(); } } }
我只是简单的实现了一下,重点在DrawSwitch这个方法,就是画两个半圆,中间是一个正方形,然后在上面画一个白圆,根据Checked属性,最上面的白圆在两边切换,仅此而以。
通过上面例子,不知你是否了解了可视化控件的实现方式。如果你是初学者,完整的思路不太通,没关系,理解到控件是画出来的就够了,后面应该会说到GDI+的详细技术点。如果你是WinForm老手,可以自己实现一套自己的专用控件,把Window上的应用Run出Mac的感觉,甚至IOS的感觉。
想要更快更方便的了解相关知识,可以关注微信公众号
标签:控件,Checked,CheckBoxState,width,可视化,using,new,WinForm From: https://www.cnblogs.com/axzxs2001/p/16970997.html