1. 程式人生 > 其它 >WinForm(三)揭開視覺化控制元件的面紗

WinForm(三)揭開視覺化控制元件的面紗

  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 OnMouseDown(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 OnMouseHover(EventArgs e) { base.OnMouseHover(e); state = Checked ? CheckBoxState.CheckedHot : CheckBoxState.UncheckedHot; Invalidate(); } protected override void OnMouseUp(MouseEventArgs e) { base.OnMouseUp(e); this.OnMouseHover(e); } protected override void OnMouseLeave(EventArgs e) { base.OnMouseLeave(e); state = Checked ? CheckBoxState.CheckedNormal : CheckBoxState.UncheckedNormal; Invalidate(); } } }

  我只是簡單的實現了一下,重點在DrawSwitch這個方法,就是畫兩個半圓,中間是一個正方形,然後在上面畫一個白圓,根據Checked屬性,最上面的白圓在兩邊切換,僅此而以。

  通過上面例子,不知你是否瞭解了視覺化控制元件的實現方式。如果你是初學者,完整的思路不太通,沒關係,理解到控制元件是畫出來的就夠了,後面應該會說到GDI+的詳細技術點。如果你是WinForm老手,可以自己實現一套自己的專用控制元件,把Window上的應用Run出Mac的感覺,甚至IOS的感覺。

  想要更快更方便的瞭解相關知識,可以關注微信公眾號