C#中实现真正的透明的PictrueBox

上一个项目中需要在一个图片上添加头发、装饰品。在实现过程中发现如下问题:



1、C#中的透明,只是对parent的透明,而对于parent上面的其他控件,完全忽略,这样如果后添加的空间又相互重叠,就会出现很奇怪的透明效果。


2、C#中添加控件时,最后添加的控件会出现在最下面。


一个比较资深的朋友告知,此类操作应该定义自己的数据结构,从而实现对图片的编辑和修改。听上去过于复杂的,时间上不允许,于是直接放弃了这个解决方案。到网上搜索,结果大都是同类问题,但是没有找到具体的解决方案,没有办法,只好动手写自己的控件,实现这一效果。


控件是PictureBox的子类,主要思路就是在控件的重绘方法中,遍历父控件的所有子控件,发现有其他子控件在改控件下面,并有重叠部分,画出重叠部分,如果发现有控件在改控件上面,调用Invalidate()方法,重画上面的控件。


代码如下:


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Windows.Forms;


namespace VisualImage
{
    public class TransparentPictureBox:PictureBox
    {
        protected override void OnPaint(PaintEventArgs e)
        {
            Graphics g = e.Graphics;
            ControlCollection cc = this.Parent.Controls;
            if (cc.Count > 1)
            {
                bool isUp = false;
                for (int i = cc.Count - 1; i >= 0; i--)
                {
                    Control c = cc[i];
                    if (isUp)
                    {
                        c.Invalidate();
                    }
                    else
                    {
                        drawRectangleIntersection(g, (TransparentPictureBox)c);
                    }


                    isUp = c == this;
                }
            }


            Bitmap b = new Bitmap(Image);
            g.DrawImage(b, 0, 0, b.Width, b.Height);
            base.OnPaint(e);
        }


        protected void drawRectangleIntersection(Graphics g, TransparentPictureBox tpb)
        {
            Rectangle rectangle1 = new Rectangle(Location.X, Location.Y, Width, Height);
            Rectangle rectangle2 = new Rectangle(tpb.Location.X, tpb.Location.Y, tpb.Width, tpb.Height);


            if (rectangle1.IntersectsWith(rectangle2))
            {
                Rectangle rectangle3 = Rectangle.Intersect(rectangle1, rectangle2);
                if (!rectangle3.IsEmpty)
                {
                    Rectangle srcRect = new Rectangle(rectangle3.Location.X - tpb.Location.X, rectangle3.Location.Y - tpb.Location.Y, rectangle3.Width, rectangle3.Height);
                    Rectangle destRect = new Rectangle(Math.Abs(Location.X - rectangle3.Location.X), Math.Abs(Location.Y - rectangle3.Location.Y), rectangle3.Width, rectangle3.Height);
                    g.DrawImage(tpb.Image, destRect, srcRect, GraphicsUnit.Pixel);
                }
            }
        }
    }
}




改控件只实现了重叠部分的重画,至于将后放置的控件放在父控件的最上层,还需要额外的处理。


使用上述控件代码如下:


        private void decorationPBMouseDown(object sender, MouseEventArgs e)
        {
            mouse_offset = new Point(-e.X, -e.Y);
            beginDrag = true;
        }
        private void decorationPBMouseUp(object sender, MouseEventArgs e)
        {
            beginDrag = false;
        }


        private void decorationPBMouseMove(object sender, MouseEventArgs e)
        {
            if (beginDrag)
            {
                Point mousePos = Control.MousePosition;
                mousePos.Offset(mouse_offset.X, mouse_offset.Y);//设置偏移
                ((Control)sender).Location = ((Control)sender).Parent.PointToClient(mousePos);
                draged = true;
            }
            
        }


        private void button2_Click(object sender, EventArgs e)
        {
            Bitmap image = new Bitmap("hair image location");
            this.SuspendLayout();
            TransparentPictureBox pb = new TransparentPictureBox();
            pb.SizeMode = PictureBoxSizeMode.AutoSize;
            Bitmap temp = new Bitmap(image, 138, image.Height * 138 / image.Width);
            pb.BackColor = Color.Transparent;
            pb.Image = temp;




            pb.Location = new Point(200, 60);
            List<Control> tempList = new List<Control>();
            List<Point> tempLocations = new List<Point>();
            for (int i = 0; i < pictureBox.Controls.Count; i++)
            {
                tempLocations.Add(pictureBox.Controls[i].Location);
                tempList.Add(pictureBox.Controls[i]);
            }
            this.pictureBox.Controls.Clear();
            this.pictureBox.Controls.Add(pb);
            for (int i = 0; i < tempList.Count; i++)
            {
                this.pictureBox.Controls.Add(tempList[i]);
                tempList[i].Location = tempLocations[i];
            }
            this.ResumeLayout(false);
            pb.MouseDown += decorationPBMouseDown;
            pb.MouseMove += decorationPBMouseMove;
            pb.MouseUp += decorationPBMouseUp;
        }


控件下载地址:http://download.csdn.net/source/3469956

  • 4
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值