DotNet实现PictureBox重叠透明效果

  本文介绍DotNet中PictureBox控件实现重叠透明效果示例。

 

  关于一般的透明效果,这里不多说,相信很多人都会,这种透明效果一般需要设置父控件,是子控件相对于父控件的透明。那么很多人可能更为关心的是多个控件之间的透明效果,比如窗体上有多个PictureBox控件,当这些PictureBox重叠时如何设置为透明,这样的效果估计在项目中会经常用到。本文的目的就是要给大家提供几种参考解决方案。

 

  一般地,在.NET中,多个控件之间重叠时是不会实现透明效果的。 如下图所示:

 

 

  下面开始介绍这几种解决方案:

 

  第一种方案:记录不透明图片的路径,再设置透明效果。参考代码如下:

    /// <summary>
    ///  PictureBox透明示例
    
///  Date:2012-3-4 07:25:56
    
///   </summary>
     public  partial  class Form1 : Form
    {
        [DllImport( " user32.dll ")]
         public  static  extern  int ReleaseCapture();

        [DllImport( " user32.dll ")]
         public  static  extern  int SendMessage(IntPtr hwnd,  int wMsg,  int wParam,  int lParam);

         public  const  int WM_SYSCOMMAND =  0x0112;
         public  const  int SC_MOVE =  0xF010;
         public  const  int HTCAPTION =  0x0002;

         public Form1()
        {
            InitializeComponent();
             // this.picModelImage.Controls.Add(this.picHair);
        }

         private  void picHair_MouseDown( object sender, MouseEventArgs e)
        {
            SetPictureBoxTransparent(picHair, picHair.Image);
             // SetPictureBoxTransparent(picModelImage, picModelImage.Image);
            ReleaseCapture();
            SendMessage( this.picHair.Handle, WM_SYSCOMMAND, SC_MOVE + HTCAPTION,  0);
        }

         //  使用不安全的指针
        
//  返回不透明的图片路径
         private  unsafe GraphicsPath NoteGraphicsPath(Image image)
        {
             if (image ==  null)
                 return  null;

             //  声明GraphicsPath类以便计算位图路径
            GraphicsPath graphicsPath =  new GraphicsPath(FillMode.Alternate);
            Bitmap bitmap =  new Bitmap(image);

             int picWidth = bitmap.Width;
             int picHeight = bitmap.Height;

            BitmapData bitmapdata = bitmap.LockBits( new Rectangle( 00, picWidth, picHeight), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);

             byte* point = ( byte*)bitmapdata.Scan0;
             int offset = bitmapdata.Stride - picWidth *  3;
             int p0, p1, p2;
            p0 = point[ 0];
            p1 = point[ 1];
            p2 = point[ 2];
             int start = - 1;

             for ( int h =  0; h < picHeight; h++)
            {
                 for ( int x =  0; x < picWidth; x++)
                {
                     //  如果之前的点没有不透明且不透明   
                     if (start == - 1 && (point[ 0] != p0 || point[ 1] != p1 || point[ 2] != p2))
                    {
                        start = x;
                    }
                     else  if (start > - 1 && (point[ 0] == p0 && point[ 1] == p1 && point[ 2] == p2))
                    {
                         //  如果之前的点是不透明
                        graphicsPath.AddRectangle( new Rectangle(start, h, x - start -  11));
                        start = - 1;
                    }

                     //  如果之前的点是不透明且是最后一个点  
                     if (x == picWidth -  1 && start > - 1)
                    {
                        graphicsPath.AddRectangle( new Rectangle(start, h, x - start +  11));
                        start = - 1;
                    }

                    point +=  3;
                }

                point += offset;
            }

            bitmap.UnlockBits(bitmapdata);
            bitmap.Dispose();

             return graphicsPath;
        }

         ///   <summary>
        
///  需要设置透明效果的控件调用该方法
        
///   </summary>
        
///   <param name="control"> 要设置透明效果的控件 </param>
        
///   <param name="image"> 控件的图片 </param>
         public  void SetPictureBoxTransparent(Control control, Image image)
        {
            GraphicsPath graphic =  null;
            graphic = NoteGraphicsPath(image);

             if (graphic ==  null)
                 return;

            control.Region =  new Region(graphic);
        }

 

  需要添加2个命名空间:

using System.Drawing.Drawing2D;
using System.Drawing.Imaging;

 

  运行后效果如下所示:

 

 

   注意:由于本示例有不安全的代码[关键字unsafe],需要在项目属性中设置"允许不安全代码",如下图:

 

 

 

  第二种方案:使用GDI +中绘制图像与透明

 

  这种方案是需要我使用GDI+绘制图像,具体步骤如下所示:

 

  1. 需要添加两个组件类:

  PictureBoxModel.cs 和 PanelExtend.cs

 

  PanelExtend.cs 中代码:

using System;
using System.Drawing;
using System.Windows.Forms;
using System.Drawing.Drawing2D;

///   <summary>
///  Panel扩展类
///   </summary>
public  abstract  class PanelExtend : Panel
{
     protected Graphics graphics;

     protected  override CreateParams CreateParams
    {
         get
        {
            CreateParams cp =  base.CreateParams;
            cp.ExStyle |=  0x00000020//  实现透明样式

             return cp;
        }
    }

     public PanelExtend()
    {
    }

     protected  override  void OnPaintBackground(PaintEventArgs pevent)
    {
        
    }

     protected  override  void OnPaint(PaintEventArgs e)
    {
         this.graphics = e.Graphics;

         this.graphics.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias;
         this.graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBilinear;
         this.graphics.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.HighQuality;
         this.graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;

        OnDraw();
    }

     protected  abstract  void OnDraw();

 

  PictureBoxModel.cs  代码:

using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;

///   <summary>
///  实现绘制图像
///   </summary>
public  class PictureBoxModel : PanelExtend
{
     public PictureBoxModel()
    {
         // this.SetStyle(System.Windows.Forms.ControlStyles.SupportsTransparentBackColor, true);
    }

     protected  override  void OnDraw()
    {
         //  获取图像
        Image imageModel =  global::MyPictureBoxDemo.Properties.Resources.model;
        Image imageHair =  global::MyPictureBoxDemo.Properties.Resources.hair;

         // int width = imageModel.Size.Width;
        
// int height = imageModel.Size.Height;

         int width =  this.Width;
         int height =  this.Height;
        Rectangle recModel =  new Rectangle( 00, width, height);
        Rectangle recHair =  new Rectangle( 00, imageHair.Width, imageHair.Height);
        
         this.graphics.DrawImage(imageModel, recModel);
         this.graphics.DrawImage(imageHair, recHair);
    }

 

  实现效果图如下所示:

 

 

 

  示例下载:点击下载

 

  第三种方案: 移动图片时使用GDI清除背景并实时刷新

  我这里实现了这种方案,但是在移动图片时存在着闪烁现象。希望谁能有更好的解决方案可以一起交流。 效果图如下:

 

 

  主要是在程序中未执行PictureBox_MouseUp事件。

 

  示例下载:点击下载

 

  最后,希望转载的朋友能够尊重作者的劳动成果,加上转载地址:http://www.cnblogs.com/hanyonglu/archive/2012/04/04/2431625.html 谢谢。

 

  完毕。^_^

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值