zoukankan      html  css  js  c++  java
  • 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 谢谢。

      完毕。^_^

  • 相关阅读:
    BZOJ 1412: [ZJOI2009]狼和羊的故事
    Bzoj 2443: [Usaco2011 Open]奇数度数
    Bzoj 1101: [POI2007]Zap
    BZOJ 2186: [Sdoi2008]沙拉公主的困惑
    BZOJ 4804: 欧拉心算 欧拉函数
    Luogu P3121 [USACO15FEB]审查(黄金)Censoring (Gold)
    Luogu P3000 [USACO10DEC]牛的健美操Cow Calisthenics
    BZOJ 2060: [Usaco2010 Nov]Visiting Cows 拜访奶牛
    BZOJ 3297: [USACO2011 Open]forgot
    BZOJ 2456: mode
  • 原文地址:https://www.cnblogs.com/hanyonglu/p/2431625.html
Copyright © 2011-2022 走看看