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();

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM