最近做 Windows 上的項目,客戶要求要做的“炫”一點,所以,動態的窗口背景永遠是必不可少的內容(比如手機qq的登錄界面對吧?
我本以為這是一個很容易實現的功能於是就滿口答應下來……是的,在 winform 裡,並不是那麼容易就能達到你想要的效果的。
理所當然,我們想到如果要播放視頻,那麼就用系統自帶的 media player,只要添加一個控件就可以搞定——結果就是播放的視頻要么被按鈕擋住,要么就是永遠在第一,把按鈕擋住……
所以了,想要實現播放視頻,還是要老老實實的使用 圖片框 。
那麼這就要用到所謂的 mciSendString 方法,比如說這樣:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
private class LibWrap { [DllImport(("winmm.dll"), EntryPoint = "mciSendString", CharSet = CharSet.Auto)] public static extern int mciSendString(string lpszCommand, string lpszReturnString, uint cchReturn, IntPtr hwndCallback); } private void PlayViedo() { PictureBox PlayScreen = new PictureBox(); PlayScreen = this.pictureBox; string mciCommand; string path = string.Empty; path = System.Windows.Forms.Application.StartupPath + @"\Background"; if (!Directory.Exists(path)) { Directory.CreateDirectory(path); } path += @"\bg.wmv"; mciCommand = "open " + path + " alias MyAVI"; mciCommand = mciCommand + " parent " + PlayScreen.Handle.ToInt32() + " style child"; LibWrap.mciSendString(mciCommand, null, 0, IntPtr.Zero); Rectangle r = PlayScreen.ClientRectangle; mciCommand = "put MyAVI window at 0 0 " + r.Width + " " + r.Height; LibWrap.mciSendString(mciCommand, null, 0, IntPtr.Zero); // LibWrap.mciSendString("play MyAVI", null, 0, IntPtr.Zero); LibWrap.mciSendString("play MyAVI repeat", null, 0, IntPtr.Zero); } |
但這個是不能用的,即使把官方的代碼拷貝過來,也無法得到正確的結果——就是不播放你有脾氣?
最終,我還是用 OpenCV的 實現了這個效果,當然,給 C# 用,我們得找 OpenCV 的 .net 封裝,也就是 EmguCV。
這裡我就大略的記錄一下實現過程,首先你要去下載 Emgu 庫安裝一下,地址在這裡:https://sourceforge.net/projects/emgucv/files/emgucv/3.2/libemgucv-windesktop-3.2.0.2682.exe/download
你要注意下載的版本,如果有更新的版本,請下載新版。
原理
其實使用 emgu 的原理和上文用 pictureBox 播放視頻應該是一致的,都是把視頻按照時間獲取幀,然後顯示一張圖片罷了。使用 emgu 的另外一個好處是它可以把任意視頻做成這樣,比如你的 mp4,或者是串流地址。
環境配置
下載安裝後,默認的安裝位置為: C:\Emgu\emgucv-windesktop 3.2.0.2682\箱子 具體版本號可能會有變化。現在我們打開 vs,在裡邊導入 emgu:
-
- 點開你的程序項目,在「設計」模式下左側的「工具箱」中點鼠標右鍵,選擇「選擇項…」;
- 在彈出的對話框中點下邊的「瀏覽」,找到 emgu 的安裝位置,選中 Emgu.簡歷.UI.DLL、 Zedgraph.DLL 這兩個進行打開;
- VS 會自動導入並選中這些 emgu 的控件,確定即可;
- 在項目右側的「解決方案資源管理器」中,找到「引用」,在裡邊點右鍵選擇「添加引用」;
- 在彈出的對話框左側選擇「瀏覽」,然後手動導入 Emgu.簡歷.UI.DLL、 Zedgraph.DLL 、 Emgu.簡歷.UI.GL.DLL 、 Emgu.簡歷.世界.DLL 這四個文件。
這樣,環境就配置好了。
使用控件
這個時候你就可以從工具箱中拖入要用的 emgu 控件了,這裡我們用 emgu 的 ImageBox ,拖入後把它命名為 VideoBox 備用。
這裡我們要用到的類變量,注意聲明在類中:
1 2 3 |
VideoCapture camCapter = null; Mat frame; System.Windows.Forms.Timer PlayerTimer = new System.Windows.Forms.Timer(); |
當要播放視頻的時候,就這麼做:
1 2 3 4 5 6 7 8 |
camCapter = new VideoCapture(videoUrl); VideoBox.Dock = DockStyle.Fill; camCapter.SetCaptureProperty(Emgu.CV.CvEnum.CapProp.PosFrames, 2241); var tmp = (camCapter.GetCaptureProperty(Emgu.CV.CvEnum.CapProp.Fps) > 0) ? (camCapter.GetCaptureProperty(Emgu.CV.CvEnum.CapProp.Fps)) : 24; int delay = (int)(1000 / tmp); PlayerTimer.Interval = delay; PlayerTimer.Tick += VideoController; PlayerTimer.Start(); |
這裡有兩點需要注意:
- 第 4 行獲取視頻的幀率,並不是所有的視頻都能正確獲取到,所以如果不能獲取,我們就給一個默認的 24 FPS,當然,你也可以默認 25 或者 30;
- 第 8 行注意這裡一定要調用啟動,不然視頻就不會播放了,不會自動啟動計時器的。
現在我們再來看看 視頻控制器 的實現,這裡最重要,因為計時器會在規定的時間輪詢這個控制器,具體的顯示操作就是由這個控制器來完成的:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
void VideoController(object sender, EventArgs e) { if (camCapter == null) { return; } if (frame != null) { frame.Dispose(); } if (VideoPlayNeedsStop) { frame = null; PlayerTimer.Stop(); } frame = camCapter.QueryFrame(); if (frame == null) { Console.WriteLine("Video End"); //camCapter = new VideoCapture(videoUrl); //PlayerTimer.Stop(); return; } VideoBox.Image = frame; } |
注意如果你想要連續播放(重複循環播放),那麼就在高亮的一行重新初始化一個 視頻截取 就可以了。
加入透明背景的控件
當然,最後我們還要加入控件,比如說一個 按鍵 ,你需要一個具有透明設定的 png 來作為按鈕的內容,然後就做如下配置:
1 2 3 4 5 6 7 8 |
this.ll.Text = ""; this.ll.Image = ScreenController.ScreenController.shared.GetImageFrom("ui_images\\liulan.png"); this.ll.BackgroundImageLayout = ImageLayout.None; this.ll.FlatAppearance.BorderSize = 0; this.ll.FlatAppearance.MouseDownBackColor = Color.Transparent; this.ll.FlatAppearance.MouseOverBackColor = Color.Transparent; this.ll.FlatStyle = FlatStyle.Flat; this.ll.BackColor = Color.Transparent; |
這裡 二 是我的一個 按鍵 ,總之,如此配置之後,按鈕就是透明的了,但你會發現它雖然覆蓋在視頻之上,但顯然透明到的還是窗口本身的背景而不是顯示其下視頻的內容。
1 |
this.ll.Parent = VideoBox; |
這時我們可以手動調整按鈕的父級為這我們的 VideoBox ,這樣,它就能顯示出視頻的內容了。
動態鏈接庫
最後,你還需要把運行時依賴的動態鏈接庫拷貝到程序的運行目錄下,這個分為32位和64位,你如果是debug運行,就拷貝32位目錄內的文件即可: C:\Emgu\emgucv-windesktop 3.2.0.2682\箱子\86
參考文獻
- OpenCV的
- Emgu CV: OpenCV的.NET中 (C#, VB, C ++多)
- 如何使用PictureBox播放視頻
- 【Emgu】一起學EmguCV(一)配置與使用
- VS2010+C#+EmguCV讀取和錄製視頻
- [emguCV]播放影片—臨時筆記(未整理)
本文由 落格博客 原創撰寫:落格博客 » winform 使用 視頻 作為窗口背景
轉載請保留出處和原文鏈接:https://www.logcg.com/archives/2893.html