zoukankan      html  css  js  c++  java
  • Winform的"透明"

      手头目前的一个项目(.Net4.0)中有这样一个需求:在程序中要进行视频采集,并且要在视频影像区域进行绘图编辑,对绘图能进行拉伸,拖拽和删除。从需求来看,必须得在视频影像区的上方盖一层画布才能这么操作了。

      首先是找视频成像控件,在网上找了一圈,找到AForge(http://www.aforgenet.com/framework/downloads.html),写了个测试代码,直接用办公用的笔记本摄像头进行视频采集,发现还不错,DevExpress也有一个视频控件,不过那个设置起来比较麻烦,而且我们也不需要用那么多附加功能,只要能够输出影像就可以。

      然后就开始折腾视频层的上一层了。一开始想法挺简单,panel不就是可以透明的吗,找了网上的一个方法,对panel进行透明设置:

    BackColor=Color.Transparent

    设置完成后调试,哦哟,果然是透明的,然后兴冲冲的把视频控件开启,悲剧的发现那层白花花的panel挡了,看来此法不通。

    然后仔细研究了一下Winform的透明机制,控件的BackColor应该是一个“静态”属性,是在重绘的时候进行颜色的传递,达到透明的目的,其实是把Panel做成了完美的“变色龙”,而视频流应该是无法通过这种方式透传的(不知道我的理解对不对),而我们要的是一块玻璃,因此这种方式不能达到目的。

    然后又开始了各种google,网上找到另一种方式的透明:控制重绘。具体参看 [http://my.oschina.net/HenuToater/blog/520649]

    结果还是没法把视频流透传上来。

    这下抓瞎了,病急乱投医,开始尝试各种方法,而网上能找到的都是第一种方式。

    后来找到一个Demo,是利用Form来做这个透明的,因为Form本身就有透明属性:Opacity,把这个属性调到1以下,就能产生透明效果。

    OK,就用Form的透明吧,然后紧接着第二个问题来了,怎么盖到目标控件上面呢?

    一开始也是各种瞎试,后来找到一个老司机带路

    Form a = new Form();
    a.Show(this);
    
    //设置a的Location

    然后再监听主窗体的移动事件,基本上就可以了。

    接着,我又兴高采烈的开始往下做,在这层Form上画了几个图形,惨烈的发现画出来的图形也是透明的,颜色非常淡。这个就是Form透明设置的结果吧——一透到底,上面的控件什么的都透明了,这个可不是我想要的。

    继续在网上瞎几把找(Winform开发真是累),后来找到了一个商业库(DSkin),国人开发的,价格也算良心,跟作者沟通了自己遇到的问题,作者表示自己的库能解决这个问题,于是花了199大洋买了授权,(以下内容为安利DSkin)看了一下DSkin做得还算不错的,整个控件库看下来,大多是针对特效这块做的,作者对Winform应该是非常通透的。

    买了授权后,开始心急火燎的写测试程序,在和作者一轮沟通交流后,顺利的解决了这个折腾我2天的东西。

    代码:

    GlassDraw.cs 部分

        public partial class GlassDrawer : DSkinForm
        {
            private Image _Backup;
            
            public GlassDrawer()
            {            
                FormBorderStyle = FormBorderStyle.None;
                BackColor = Color.Transparent;
                DoubleBuffered = true;
                ShowInTaskbar = false;
                ShowSystemButtons = false;
                DrawIcon = false;
                ShowIcon = false;
                EnableAnimation = false;
                Text = string.Empty;
                InitializeComponent();
                _Backup = new Bitmap(this.Width, this.Height);          
                _LastLocation = Location;
            }
    
            public Func<GlassDrawer,bool> MoveAssert
            {
                get;set;
            }
    
            public void Draw(Action<Graphics> drawer)
            {
                try
                {
                    Graphics g = Graphics.FromImage(_Backup);
                    drawer(g);
                    g.Dispose();
                    Invalidate();              
                }
                catch(Exception e)
                {
    
                }
            }
            protected override void OnLayeredPaint(PaintEventArgs e)
            {
                if (_Backup != null)
                {
                    e.Graphics.DrawImage(_Backup, 0, 0);
                }           
            }
            protected override void OnMove(EventArgs e)
            {
                
                base.OnMove(e);
            }
            private Point _LastLocation;
            protected override void OnLocationChanged(EventArgs e)
            {
                if (MoveAssert != null)
                {
                    if (!MoveAssert(this))
                    {
                        Location = _LastLocation;
                        return;
                    }
                }
                _LastLocation = Location;
                base.OnLocationChanged(e);
            }
    
            private Point _TargetLocation;
            private Control _Target;
            public void Follow(Control target)
            {
                if(_Target != null)
                {
                    _Target.LocationChanged -= Target_LocationChanged;
                }
                _Target = target;
                target.LocationChanged += Target_LocationChanged; 
                _TargetLocation = PointToScreen( target.Location);
            }
    
            private void Target_LocationChanged(object sender, EventArgs e)
            {
                var p = PointToScreen(_Target.Location);
    
            }
        }

    Form1.cs 部分

    InitializeComponent();
                gd.Width = cameraFrame1.Width;
                gd.Height = cameraFrame1.Height;
                gd.Location = PointToScreen(cameraFrame1.Location);         
                gd.Text = string.Empty;
                gd.MoveAssert = (g) =>
                {
                    var srcp = PointToScreen(g.Location);
                    int top = srcp.Y;
                    int left = srcp.X;
                    int right = srcp.X + g.Width;
                    int bottom = srcp.Y + g.Height;
                    var targetp = PointToScreen(this.Location);
    
                    if (top < targetp.Y ||
                        left < targetp.X ||
                        right > targetp.X + this.Width ||
                        bottom > targetp.Y + this.Height)
                        return false;
                    return true;
                };       
                gd.Show(this);            
                cameraFrame1.Start();
  • 相关阅读:
    Spring AOP 注解开发
    AOP的专业术语
    Java自定义注解的实现和应用
    Spring 声明式事务管理
    另一种线程安全机制:在事务管理中起到巨大作用的 ThreadLocal
    MySQL的二级索引
    数据库的范式化和反范式化
    MySQL为表字段添加索引
    mysql索引(二)----如何高效使用索引
    Alexnet网络
  • 原文地址:https://www.cnblogs.com/ishowfun/p/5826665.html
Copyright © 2011-2022 走看看