900字范文,内容丰富有趣,生活中的好帮手!
900字范文 > C# 控件透明背景(winform)

C# 控件透明背景(winform)

时间:2021-03-03 15:33:40

相关推荐

C# 控件透明背景(winform)

原文出自:C# 实现真正的透明控件(Windows桌面程序)_yangshengchuan的博客-CSDN博客_c# 控件透明

修改了一点bug和方式,现在可以根据任意指定颜色镂空,还可以一次性镂空多个颜色

使用方法:

using System;using System.Collections.Generic;using ponentModel;using System.Drawing;using System.Drawing.Drawing2D;using System.Data;using System.Linq;using System.Text;using System.Windows.Forms;namespace UControlTran{public partial class UserControl1 : UserControl{/************************************************************************************************//******** 构造函数里画图用的文本text必须跟 OnPaint 里面的 text 一模一样,否则文字就错位了*********//******** 自己修改一下构造函数,可以把text作为参数传入,然后保存,OnPaint 直接调用保存的 *********//************************************************************************************************/private const TextFormatFlags textFormatFlags = TextFormatFlags.NoPadding | TextFormatFlags.NoPrefix | TextFormatFlags.PreserveGraphicsClipping;public UserControl1(){InitializeComponent();var bit = new Bitmap(1, 1);var g = Graphics.FromImage(bit);var text = "关于其他双缓存,半透明,请参考其他相关知识";Size size = TextRenderer.MeasureText(g, text, this.Font, new Size(-1, 0), textFormatFlags);TextSize = size;//长宽要保留下来,下面 OnPaint 需要用到g.Dispose();var bitmap = new Bitmap(size.Width, size.Height);g = Graphics.FromImage(bitmap);//首先要明白,这里用text来画,并不是就把text画到控件上了//而是参照图片画一个跟文字形状一样的图片!!!!!!!!!!!!!!//所以要在 OnPaint 重新画文字g.DrawString(text, this.Font, Brushes.Red,-1,0);//随手用 text 画了一个测试图片g.Dispose();Region = APub.ImageToRegionPx(bitmap, Color.FromArgb(0, 0, 0, 0));//将所有透明的区域全部镂空.这样控件里面就不会显示上面 text 内容以外的区域bitmap.Dispose();}public Size TextSize { get; set; }/// <summary>/// 重写OnPaint方法/// </summary>/// <param name="e"></param>protected override void OnPaint(PaintEventArgs e){var text = "关于其他双缓存,半透明,请参考其他相关知识";base.OnPaint(e);var g = e.Graphics;var brush = new SolidBrush(Color.Red);//为什么要在这里再画一次文本,是因为构造函数里面的方法只是以文字的像素/点阵信息为矩阵,画了一个跟文字一样的控件出来,//所以颜色是黑色的,那么要实现自己的颜色就必须真正的把颜色文字绘制到控件.g.DrawString(text, this.Font, brush, -1, 0);brush.Dispose();g.Dispose();Size = TextSize;}protected override void OnMouseHover(EventArgs e){this.Cursor = Cursors.SizeAll;base.OnMouseHover(e);}protected override void OnMouseLeave(EventArgs e){this.Cursor = Cursors.Default;base.OnMouseLeave(e);}}}

//镂空方法

/// <summary>/// 从图片中获取除指定颜色以外的色块区域图.同时对png透明兼容./// 这个要在自定义控件/// </summary>/// <param name="Picture">取其区域的图片。</param>/// <param name="TransparentColor">要镂空的颜色,必须是ARGB,必须带A,/// 因为如果是黑色,rgb=0,0,0,如果没有A通道,黑色就直接被过滤掉了.所以如果要过滤png图片的透明层,就要填Color.FromArgb(0, 0, 0,0)</param>/// <returns>图片中非透明色部分的区域</returns>public unsafe static Region ImageToRegionPx(Image Picture, Color TransparentColor){return ImageToRegionPx(Picture, new List<Color>() { TransparentColor });}/// <summary>/// 从图片中获取除指定颜色以外的色块区域图.同时对png透明兼容/// </summary>/// <param name="Picture">取其区域的图片。</param>/// <param name="keyColors">要镂空的颜色,必须是ARGB,必须带A,/// 因为如果是黑色,rgb=0,0,0,如果没有A通道,黑色就直接被过滤掉了.所以如果要过滤png图片的透明层,就要填Color.FromArgb(0, 0, 0,0)</param>/// <returns>图片中非透明色部分的区域</returns>public unsafe static Region ImageToRegionPx(Image Picture, List<Color> keyColors){if (Picture == null) return null;Region rgn = new Region();rgn.MakeEmpty();Bitmap bitmap = null;if (Picture.GetType() != typeof(Bitmap))bitmap = new Bitmap(Picture);elsebitmap = (Bitmap)Picture;int width = bitmap.Width;int height = bitmap.Height;BitmapData bmData = bitmap.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);byte* p = (byte*)bmData.Scan0;int offset = bmData.Stride - width * 4;Rectangle curRect = new Rectangle();curRect.Height = 1;int start = -1;// 行座标 ( Y ) for (int Y = 0; Y < height; Y++){// 列座标 ( X ) for (int X = 0; X < width; X++){///如果像素色彩不是列表中要排除的颜色///p[3] > 0 如果不透明度是0,就说明是空白像素,强制排除if (start == -1 && p[3] > 0 && keyColors.All(argb => p[3] > argb.A || p[2] != argb.R || p[1] != argb.G || p[0] != argb.B)){start = X; //记录这个点curRect.X = X;curRect.Y = Y;}//如果当前像素是要排除的颜色,将 start 要复位else if (start > -1 && keyColors.Any(argb => p[3] <= argb.A && p[2] == argb.R && p[1] == argb.G && p[0] == argb.B)){curRect.Width = X - curRect.X;rgn.Union(curRect);start = -1;}if (X == width - 1 && start > -1) //如果 之前的点是不透明 且 是最后一个点{curRect.Width = X - curRect.X;rgn.Union(curRect);start = -1;}p += 4;//下一个内存地址}p += offset;}bitmap.UnlockBits(bmData);bitmap.Dispose();return rgn;}

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。