C# Winform控件贴透明png图片遇到的问题

用C# winform开发界面时会遇到很多小问题,首先贴透明的png图片后,图片无法透明,这点可以通过属性设置:外观/BackColor (Web TransParent)可以解决。

      但当用多个控件时,如PictureBox,控件都贴png透明图片后,两个PictureBox有重叠的地方,希望重叠的地方能透明,就是透视下面的控件部分,结果测试后发现两控件重叠透明的地方对整个框架的背景透明,但对下面控件无法透明,最后在网上找了一段代码,解决了这个问题。

对每个控件使用:ControlTrans(pic,pic.Image);然后层叠之后就可以透明了。

[c-sharp]  view plain copy
  1.   /// <summary>  
  2.  /// 根据图片计算GraphicsPath路径  
  3.   /// </summary>  
  4. /// <param name="img">gif或者png图片</param>  
  5. /// <returns>图片不透明区域路径</returns>  
  6. /// 用这个代码的时候需要选择项目属性->生成->勾选"允许不安全代码"  
  7. /// 因为这里用到了指针,C#用指针式不安全的,具体可查看msdn  
  8. private unsafe static GraphicsPath subGraphicsPath(Image img)  
  9. {  
  10.     if (img == nullreturn null;  
  11.   
  12.     // 建立GraphicsPath, 给我们的位图路径计算使用   
  13.     GraphicsPath g = new GraphicsPath(FillMode.Alternate);  
  14.   
  15.     Bitmap bitmap = new Bitmap(img);  
  16.   
  17.     int width = bitmap.Width;  
  18.     int height = bitmap.Height;  
  19.     BitmapData bmData = bitmap.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);  
  20.     byte* p = (byte*)bmData.Scan0;  
  21.     int offset = bmData.Stride - width * 3;  
  22.     int p0, p1, p2;         // 记录左上角0,0座标的颜色值  
  23.     p0 = p[0];  
  24.     p1 = p[1];  
  25.     p2 = p[2];  
  26.   
  27.     int start = -1;  
  28.     // 行座标 ( Y col )   
  29.     for (int Y = 0; Y < height; Y++)  
  30.     {  
  31.         // 列座标 ( X row )   
  32.         for (int X = 0; X < width; X++)  
  33.         {  
  34.             if (start == -1 && (p[0] != p0 || p[1] != p1 || p[2] != p2))     //如果 之前的点没有不透明 且 不透明   
  35.             {  
  36.                 start = X;                            //记录这个点  
  37.             }  
  38.             else if (start > -1 && (p[0] == p0 && p[1] == p1 && p[2] == p2))      //如果 之前的点是不透明 且 透明  
  39.             {  
  40.                 g.AddRectangle(new Rectangle(start, Y, X - start, 1));    //添加之前的矩形到  
  41.                 start = -1;  
  42.             }  
  43.   
  44.             if (X == width - 1 && start > -1)        //如果 之前的点是不透明 且 是最后一个点  
  45.             {  
  46.                 g.AddRectangle(new Rectangle(start, Y, X - start + 1, 1));      //添加之前的矩形到  
  47.                 start = -1;  
  48.             }  
  49.             //if (p[0] != p0 || p[1] != p1 || p[2] != p2)  
  50.             //    g.AddRectangle(new Rectangle(X, Y, 1, 1));  
  51.             p += 3;                                   //下一个内存地址  
  52.         }  
  53.         p += offset;  
  54.     }  
  55.     bitmap.UnlockBits(bmData);  
  56.     bitmap.Dispose();  
  57.     // 返回计算出来的不透明图片路径   
  58.     return g;  
  59. }  
  60.   
  61. /// <summary>  
  62. /// 调用此函数后使图片透明  
  63. /// </summary>  
  64. /// <param name="control">需要处理的控件</param>  
  65. /// <param name="img">控件的背景或图片,如PictureBox.Image  
  66. ///   或PictureBox.BackgroundImage</param>  
  67. public static void ControlTrans(Control control,Image img)  
  68. {  
  69.     GraphicsPath        g;  
  70.     g                   = subGraphicsPath(img);  
  71.     if (g == null)  
  72.         return;  
  73.     control.Region        = new Region(g);  
  74. }  

 

posted @   星火燎猿*  阅读(541)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
点击右上角即可分享
微信分享提示