官網
http://www.hzhcontrols.com
前提
入行已經7,8年了,一直想做一套漂亮點的自定義控制元件,于是就有了本系列文章,
GitHub:https://github.com/kwwwvagaa/NetWinformControl
碼云:https://gitee.com/kwwwvagaa/net_winform_custom_control.git
如果覺得寫的還行,請點個 star 支持一下吧
歡迎前來交流探討: 企鵝群568015492 
來都來了,點個【推薦】再走吧,謝謝
NuGet
Install-Package HZH_Controls
目錄
https://www.cnblogs.com/bfyx/p/11364884.html
用處及效果
注意觀察各個控制元件交疊的地方,是不是發現他們沒有遮擋?這就是這個控制元件的妙處了,

準備作業
先說明一下這個控制元件的作用,很多時候我們需要一個圖片型別的控制元件,但是有需要密集的放在一起,如果單純的設定背景圖或image的話 交疊在一起的部分就會存在遮擋現象,所有就有了這個控制元件,
該控制元件可以根據設定的采樣圖片來裁剪有用的繪圖區域,這樣的好處就是在交疊的時候,無用區域不會遮擋,
這個用GDI+畫的,另外也用到了一點三角函式,不明白的話 可以先百度下
開始
添加一個類UCSampling ,繼承UserControl
添加屬性
1 /// <summary> 2 /// The sampling imag 3 /// </summary> 4 private Bitmap samplingImag = null; 5 /// <summary> 6 /// Gets or sets the sampling imag. 7 /// </summary> 8 /// <value>The sampling imag.</value> 9 [Browsable(true), Category("自定義屬性"), Description("采樣圖片"), Localizable(true)]10 public Bitmap SamplingImag11 {12 get { return samplingImag; }13 set14 {15 samplingImag = value;16 ResetBorderPath();17 Invalidate();18 }19 }20 21 /// <summary>22 /// The transparent23 /// </summary>24 private Color? transparent = null;25 26 /// <summary>27 /// Gets or sets the transparent.28 /// </summary>29 /// <value>The transparent.</value>30 [Browsable(true), Category("自定義屬性"), Description("透明色,如果為空,則使用0,0坐標處的顏色"), Localizable(true)]31 public Color? Transparent32 {33 get { return transparent; }34 set35 {36 transparent = value;37 ResetBorderPath();38 Invalidate();39 }40 }41 42 /// <summary>43 /// The alpha44 /// </summary>45 private int alpha = 50;46 47 /// <summary>48 /// Gets or sets the alpha.49 /// </summary>50 /// <value>The alpha.</value>51 [Browsable(true), Category("自定義屬性"), Description("當作透明色的透明度,小于此透明度的顏色將被認定為透明,0-255"), Localizable(true)]52 public int Alpha53 {54 get { return alpha; }55 set56 {57 if (value < 0 || value > 255)58 return;59 alpha = value;60 ResetBorderPath();61 Invalidate();62 }63 }64 65 /// <summary>66 /// The color threshold67 /// </summary>68 private int colorThreshold = 10;69 70 /// <summary>71 /// Gets or sets the color threshold.72 /// </summary>73 /// <value>The color threshold.</value>74 [Browsable(true), Category("自定義屬性"), Description("透明色顏色閥值"), Localizable(true)]75 public int ColorThreshold76 {77 get { return colorThreshold; }78 set79 {80 colorThreshold = value;81 ResetBorderPath();82 Invalidate();83 }84 }85 86 /// <summary>87 /// The bit cache88 /// </summary>89 private Bitmap _bitCache;
在大小改變或圖片改變時重新計算邊界
1 /// <summary> 2 /// The m border path 3 /// </summary> 4 GraphicsPath m_borderPath = new GraphicsPath(); 5 6 /// <summary> 7 /// Handles the SizeChanged event of the UCSampling control. 8 /// </summary> 9 /// <param name="sender">The source of the event.</param>10 /// <param name="e">The <see cref="EventArgs"/> instance containing the event data.</param>11 void UCSampling_SizeChanged(object sender, EventArgs e)12 {13 ResetBorderPath();14 }15 16 /// <summary>17 /// Resets the border path.18 /// </summary>19 private void ResetBorderPath()20 {21 if (samplingImag == null)22 {23 m_borderPath = this.ClientRectangle.CreateRoundedRectanglePath(5);24 }25 else26 {27 var bit = new Bitmap(this.ClientRectangle.Width, this.ClientRectangle.Height);28 using (var bitg = Graphics.FromImage(bit))29 {30 bitg.DrawImage(samplingImag, this.ClientRectangle, 0, 0, samplingImag.Width, samplingImag.Height, GraphicsUnit.Pixel);31 }32 _bitCache = bit;33 m_borderPath = new GraphicsPath();34 List<PointF> lstPoints = GetBorderPoints(bit, transparent ?? samplingImag.GetPixel(0, 0));35 m_borderPath.AddLines(lstPoints.ToArray());36 m_borderPath.CloseAllFigures();37 }38 }39 40 /// <summary>41 /// Gets the border points.42 /// </summary>43 /// <param name="bit">The bit.</param>44 /// <param name="transparent">The transparent.</param>45 /// <returns>List<PointF>.</returns>46 private List<PointF> GetBorderPoints(Bitmap bit, Color transparent)47 {48 float diameter = (float)Math.Sqrt(bit.Width * bit.Width + bit.Height * bit.Height);49 int intSplit = 0;50 intSplit = (int)(7 - (diameter - 200) / 100);51 if (intSplit < 1)52 intSplit = 1;53 List<PointF> lstPoint = new List<PointF>();54 for (int i = 0; i < 360; i += intSplit)55 {56 for (int j = (int)diameter / 2; j > 5; j--)57 {58 Point p = GetPointByAngle(i, j, new PointF(bit.Width / 2, bit.Height / 2));59 if (p.X < 0 || p.Y < 0 || p.X >= bit.Width || p.Y >= bit.Height)60 continue;61 Color _color = bit.GetPixel(p.X, p.Y);62 if (!(((int)_color.A) <= alpha || IsLikeColor(_color, transparent)))63 {64 if (!lstPoint.Contains(p))65 {66 lstPoint.Add(p);67 }68 break;69 }70 }71 }72 return lstPoint;73 }74 75 /// <summary>76 /// Determines whether [is like color] [the specified color1].77 /// </summary>78 /// <param name="color1">The color1.</param>79 /// <param name="color2">The color2.</param>80 /// <returns><c>true</c> if [is like color] [the specified color1]; otherwise, <c>false</c>.</returns>81 private bool IsLikeColor(Color color1, Color color2)82 {83 var cv = Math.Sqrt(Math.Pow((color1.R - color2.R), 2) + Math.Pow((color1.G - color2.G), 2) + Math.Pow((color1.B - color2.B), 2));84 if (cv <= colorThreshold)85 return true;86 else87 return false;88 }
1 #region 根據角度得到坐標 English:Get coordinates from angles 2 /// <summary> 3 /// 功能描述:根據角度得到坐標 English:Get coordinates from angles 4 /// 作 者:HZH 5 /// 創建日期:2019-09-28 11:56:25 6 /// 任務編號:POS 7 /// </summary> 8 /// <param name="angle">angle</param> 9 /// <param name="radius">radius</param>10 /// <param name="origin">origin</param>11 /// <returns>回傳值</returns>12 private Point GetPointByAngle(float angle, float radius, PointF origin)13 {14 float y = origin.Y + (float)Math.Sin(Math.PI * (angle / 180.00F)) * radius;15 float x = origin.X + (float)Math.Cos(Math.PI * (angle / 180.00F)) * radius;16 return new Point((int)x, (int)y);17 }18 #endregion
取邊界的思路如下:
1,以控制元件中心為原點,按照一定的角度順時針依次進行旋轉,
2、每次旋轉后,按照此角度從外向內,找到第一個不是透明的點記錄下來,這就是外邊界點
這個取邊界演算法感覺并不是太好,如果哪位小伙伴有更好的演算法,希望可以探討一下
重繪
1 protected override void OnPaint(PaintEventArgs e) 2 { 3 base.OnPaint(e); 4 e.Graphics.SetGDIHigh(); 5 6 this.Region = new System.Drawing.Region(m_borderPath); 7 8 if (_bitCache != null) 9 e.Graphics.DrawImage(_bitCache, 0, 0);10 11 }
最后的話
如果你喜歡的話,請到 https://gitee.com/kwwwvagaa/net_winform_custom_control 點個星星吧
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/4899.html
標籤:WinForm
