示範程式
介紹;
由於我第一次寫關於代碼介紹方面的文章,請原諒我的英語很差。我只是在學校中和一些工作中接觸過英文。
我希望每個人可以理解這篇文章的內容。如果有問題我很願意解答。如果發現有錯,請即使糾正-感謝協助我學習英文;-)。
好現在開始
這個小程式示範了,用C#開發的一個DirectShow的播放軟體可以播放視頻和聲音。
該程式包含以下控制:MainMenu, ToolBar, StatusBar, Panel, ImageList,和一個 Timer。
這些屬性都是在屬性欄中填好了,所以我建議你下載該項目,除非你並不是一個初學者。
另一方面,案例程式包含 DirectShow類用來播放視頻和聲音。
...
程式示範了以下內容:
怎樣用OpenFileDialog類來在磁碟上選擇一個媒體檔案。
怎樣啟用工具列桑的按鈕。
怎樣狀態列的資訊。
怎樣使用一個Timer控鍵。
怎樣使用時鐘控制事件。
這樣使用主菜單事件。
怎樣使用工具列事件。
怎樣使用視窗事件。
怎樣用DirectShow播放媒體。
怎樣判定媒體是否已經播放完了。
使用者介面
除了3個按鈕用來播放,停止視頻和聲音的播放,同時用菜單來選擇要播放的媒體檔案,所以在你要播放一個媒體檔案之前,你必須開啟檔案在菜單"File -> Open..."下。如果檔案成功載入,就可以通過按 "Play"按鈕來播放。在播放過程中,程式在狀態列上顯示播放進度。如果播放結束,你可以按"Play"重新播放或選擇另一個檔案。
菜單的"Info"命令用來顯示資訊對話方塊。
關於DirectShow:
我們通常用DirectShow類來播放視頻和聲音,它是DirectX中的一個開發工具。通過DirectShow可以非常容易的播放視頻和音效檔,使用它只需要正確設定參數和方法。
不幸的是.NET和C#在DirectX中不包含官方的支援平台,所以DirectX 9中不包含DirectShow。我們用C#開發DirectX通過使用Visual Basic的類型庫API版本是7到8。該文章介紹如何在C#中使用DirectX VB類庫。
在開始.NET DirectShow開發之前,我們需要建立一個到DirectShow COM DLL的引用。拷貝"Interop.QuartzTypeLib.dll"到你的專案檔夾中。在 Visual Studio.NET中通過在項目菜單中選擇和添加來完成。
按"Browse..." 選擇DirectShow COM DLL。
using QuartzTypeLib;
關於代碼:
怎樣建立DirectShow並選擇媒體檔案?
在選擇了主菜單下的"File -> Open..."後,顯示"Open File"對話方塊然後使用者可以選擇一個媒體檔案。在C#中通過建立一個OpenFileDialog類對象並使用ShowDialog()方法來實現。
OpenFileDialog openFileDialog = new OpenFileDialog();
openFileDialog.Filter = "Media Files|*.mpg;*.avi;*.wma;*.mov;" +
"*.wav;*.mp2;*.mp3|All Files|*.*";
if (DialogResult.OK == openFileDialog.ShowDialog())
{
.
.
.
在以上完成之後,我們開始建立了DirectShow並開始渲染媒體檔案。
通過以下幾步完成:
建立圖象過濾管理(FGM)
建立圖象過濾(通過FGM)
播放圖象並返回事件
以下代碼示範怎樣建立圖象過濾管理和圖象過濾:
CollapseCleanUp();
m_objFilterGraph = new FilgraphManager();
m_objFilterGraph.RenderFile(openFileDialog.FileName);
m_objBasicAudio = m_objFilterGraph as IBasicAudio;
try
{
m_objVideoWindow = m_objFilterGraph as IVideoWindow;
m_objVideoWindow.Owner = (int) panel1.Handle;
m_objVideoWindow.WindowStyle = WS_CHILD | WS_CLIPCHILDREN;
m_objVideoWindow.SetWindowPosition(panel1.ClientRectangle.Left,
panel1.ClientRectangle.Top,
panel1.ClientRectangle.Width,
panel1.ClientRectangle.Height);
}
catch (Exception ex)
{
m_objVideoWindow = null;
}
m_objMediaEvent = m_objFilterGraph as IMediaEvent;
m_objMediaEventEx = m_objFilterGraph as IMediaEventEx;
m_objMediaEventEx.SetNotifyWindow((int) this.Handle, WM_GRAPHNOTIFY, 0);
m_objMediaPosition = m_objFilterGraph as IMediaPosition;
m_objMediaControl = m_objFilterGraph as IMediaControl;
通過CleanUp()我們刪除對象,如果對象存在。在我們可以開始渲染一個檔案時,我們必須建立FilterGraphManager的幾個新對象用新的方法。RenderFile()方法建立了一個圖象過濾器用來渲染指定檔案。IBasicAudio類用來設定聲音的大小和品質。IVideoWindow類用來設定視窗風格,視窗位置。該函數是附加的,如果你播放音效檔,你如果調用該方法。可是播放音效檔不需要IVideoWindow類,所以將m_objVideoWindow設定成NULL。IMediaEvent和IMediaEventEx類用來偵聽訊息,用來發送DirectShow資訊到父視窗。通過IMediaPosition類,可以設定當前的位置。通過IMediaControl類來控制開始,停止視頻和聲音的播放。
想瞭解更多關於DirectShow的內容請讀一下MSDN的文檔。
怎樣播放媒體檔案?
用IMediaControl類的Run()方法來開始播放一個視頻或音效檔。
m_objMediaControl.Run();
怎樣暫停播放?
如果你想要暫停播放一個視頻或音效檔,使用IMediaControl類的Pause()方法。
m_objMediaControl.Pause();
怎樣停止播放?
用IMediaControl類的Stop()方法來停止播放一個視頻或聲音。
m_objMediaControl.Stop();
怎樣得到檔案的播放進度和期間?
當媒體檔案被播放時,我們在狀態列指定當前的播放進度和檔案長度。我們讀取全部100MS內IMediaPosition類得到的當前進度並將大小顯示在狀態列。為了得到檔案長度我們讀取了IMediaPosition類的Duration成員變數。
private void timer1_Tick(object sender, System.EventArgs e)
{
if (m_CurrentStatus == MediaStatus.Running)
{
UpdateStatusBar();
}
}
時間函數每隔100MS調用UpdateStatusBar()方法,用來顯示當前位置和檔案進度。
Collapseprivate void UpdateStatusBar()
{
switch (m_CurrentStatus)
{
case MediaStatus.None : statusBarPanel1.Text = "Stopped"; break;
case MediaStatus.Paused : statusBarPanel1.Text = "Paused "; break;
case MediaStatus.Running: statusBarPanel1.Text = "Running"; break;
case MediaStatus.Stopped: statusBarPanel1.Text = "Stopped"; break;
}
if (m_objMediaPosition != null)
{
int s = (int) m_objMediaPosition.Duration;
int h = s / 3600;
int m = (s - (h * 3600)) / 60;
s = s - (h * 3600 + m * 60);
statusBarPanel2.Text = String.Format("{0:D2}:{1:D2}:{2:D2}", h, m, s);
s = (int) m_objMediaPosition.CurrentPosition;
h = s / 3600;
m = (s - (h * 3600)) / 60;
s = s - (h * 3600 + m * 60);
statusBarPanel3.Text = String.Format("{0:D2}:{1:D2}:{2:D2}", h, m, s);
}
else
{
statusBarPanel2.Text = "00:00:00";
statusBarPanel3.Text = "00:00:00";
}
}
當檔案播放結束時會怎樣?
為了判定,檔案是在結束狀態,我們重寫了WndProc函數,處理EC_COMPLETE訊息,當檔案結束播放時,將向視窗發送DirectShow訊息。
Collapseprotected override void WndProc(ref Message m)
{
if (m.Msg == WM_GRAPHNOTIFY)
{
int lEventCode;
int lParam1, lParam2;
while (true)
{
try
{
m_objMediaEventEx.GetEvent(out lEventCode,
out lParam1,
out lParam2,
0);
m_objMediaEventEx.FreeEventParams(lEventCode, lParam1, lParam2);
if (lEventCode == EC_COMPLETE)
{
m_objMediaControl.Stop();
m_objMediaPosition.CurrentPosition = 0;
m_CurrentStatus = MediaStatus.Stopped;
UpdateStatusBar();
UpdateToolBar();
}
}
catch (Exception)
{
break;
}
}
}
base.WndProc(ref m);
}