--- tags: 110-2視窗程式設計 --- # 實作:影音播放程式 我們已經實際製作了單位轉換程式,還有簡單的計算機程式,其實不知不覺中,練習了很多基本程式概念。 透過實作,你才能瞭解當初一年級學習程式設計的重要概念有哪些?希望同學在學習視窗程式設計的過程中,慢慢體會程式設計的內容。 接下來,我們來實作簡單的影音播放程式,這次我們來帶領同學深入的瞭解 Windows Presentation Foundation (WPF) 在介面設計上的優點。 ## 程式功能 這次我們會設計一個簡易影音播放程式,可以播放幾種常見的影音檔案,包括:MP3、MP4、AVI 等等,並且可以暫停播放,簡單,但是可以學習到怎麼開啟檔案。 ## 試用軟體 同學你可以在以下連結,先把完整的程式下載回去使用看看。 [下載連結](https://fgu365-my.sharepoint.com/:f:/g/personal/chlu_vdi_fgu_edu_tw/ErAp2L7jZPFLtKxozH19ldgBUePawwFRqANx_wo7HsQj9Q?e=fWApLK) ## 開啟新專案 開啟新專案之前有教學過,如果你忘記了或不太熟悉,請點選[這裡](https://hackmd.io/sFFV6T2oT0-ysHotbIybhw?view#WPF-%E7%9A%84%E5%B0%88%E6%A1%88%E8%A8%AD%E5%AE%9A)。 :::success 我們的專案名稱可以叫做「MediaPlayer」,簡單就好。 ::: ## 開始吧! 還記得第二部分的基本視窗程式設計嗎?同樣的,我們依照之前說過的兩個主要程式設計流程來設計: 1. 介面基本設計 2. 程式撰寫 因此,我們也是先初步設計介面,再來進行程式撰寫。 ## 第一步:進行介面基本設計 這次我們介面設計需要再進一步的說明,要來跟同學介紹 WPF 的介面設計可以有很多變化與彈性。 當然請同學開啟好專案之後,我們會看到這個基本的設計畫面。 ![](https://i.imgur.com/MJmGzuT.png) [放大畫面](https://i.imgur.com/MJmGzuT.png) 老師刻意讓同學看到[放大畫面](https://i.imgur.com/MJmGzuT.png),主要是希望告訴同學,除了基本的修改文字內容、字體大小、樣式外,還可以製作更多變化。 ### 修改視窗底色 我們來改一下視窗的底色,請同學選擇「屬性」,並且將「筆刷」項目點開,雖然名字很奇怪叫筆刷,但實際上它可以控制控制項的基本色彩。 ![](https://i.imgur.com/XWu22Wb.png) 你可以隨便測試沒關係,試試看,將「**Background(視窗底色)**」調整成你喜歡的樣子,例如以下的範例,將背景換成一個漸層色調。 ![](https://i.imgur.com/aBPbLLe.png) [放大畫面](https://i.imgur.com/aBPbLLe.png) 甚至也可以是圖片。 ![](https://i.imgur.com/wQh1EgM.png) [放大畫面](https://i.imgur.com/wQh1EgM.png) 不過要注意的是,如果你使用圖片當背景,會在方案總管裡面一同匯入檔案,如果你後來打算不用圖片了,可以把圖片刪除,減少浪費空間。 ![](https://i.imgur.com/mJrP0UY.png) ## XAML 使用者介面描述語言 以上簡單的介面調整,你可能會好奇,那 WPF 是怎麼記錄這些設定?其實這是一種描述語言,稱為「XAML 使用者介面描述語言」。 請點選以下黃色寫著「XAML」的頁籤,你就可以看到這些程式語言。 ![](https://i.imgur.com/c20sdJY.png) [放大畫面](https://i.imgur.com/c20sdJY.png) 同學不要看到「語言」,又看到一堆密密麻麻的英文字就害怕,以為又要學電腦程式了。其實基本的使用者介面調整你不必去改以下的 XAML 語言檔,就像剛剛改背景,你只要滑鼠點選就可以了。 ```xml= <Window x:Class="MediaPlayer.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:MediaPlayer" mc:Ignorable="d" Title="MainWindow" Height="450" Width="800"> <Window.Background> <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0"> <GradientStop Color="Black" Offset="0"/> <GradientStop Color="#FFCD4545" Offset="1"/> <GradientStop Color="#FF3B7B89" Offset="0.523"/> </LinearGradientBrush> </Window.Background> <Grid> </Grid> </Window> ``` 但是我們仍希望同學可以瞭解,正因為我們可以用「描述語言」來編寫「使用者介面」,原則上,只要能描述清楚,大多數的使用者介面都能被「畫」出來,也能用程式來做進一步的變化。 例如,你可以仔細看,第 8 行的部分,就描述了視窗的右上角標題文字,也描述了它的高度與寬度。 ```xml= <Window ... Title(標題)="MainWindow" Height(高度)="450" Width(寬度)="800"> ``` 第 9 行的部分,看英文敘述就知道,是在設定背景的顏色。 ```xml= <Window.Background>(背景設定) <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">(漸層筆刷) <GradientStop Color="Black" Offset="0"/>(起點顏色) <GradientStop Color="#FFCD4545" Offset="1"/>(中點顏色) <GradientStop Color="#FF3B7B89" Offset="0.523"/>(終點顏色) </LinearGradientBrush> </Window.Background> ``` 然後你可以注意到,它們的結構很像以下的內容。通常我們把「<」與「>」所包裹的東西,叫做「標籤」,這種標記法很常運用在「描述」東西,或者用來標記一個物體的特性。 ```xml= <Window> <Window.Background> <LinearGradientBrush> <GradientStop/> <GradientStop/> <GradientStop/> </LinearGradientBrush> </Window.Background> <Grid></Grid> </Window> ``` 如果以上你看不太懂,可能這樣就好理解了。 ```htmlmixed= <學生> <姓名>王小名</姓名> <班級>一年A班</班級> <性別>男</性別> <身體 身高:"180" 體重:"75"/> </學生> ``` 因此 XAML 語言檔可以做更細微的調整與設定,讓你的介面可以更漂亮,設計可以更有彈性。 你除了可以在屬性視窗中修改控制項的內容外,也可以直接修改 XAML 的內文,例如你可以把視窗的右上角標題文字修改一下。 ```xml <Window ... Title(標題)="影音播放程式" Height(高度)="500" Width(寬度)="750"> ``` 你可以發現你修改的過程中,上方的視窗介面設計也會跟著改變。 ## 控制項:影音元件 請同學再到「工具箱」拖一個「MediaElement(影音元件)」控制項進來,「影音元件」是一個可以顯示影音檔案的元件,讓你能夠顯示影片或播放聲音。你可以調整大小,調整成你想要的大小,就像下圖的樣子。 ![](https://i.imgur.com/YmBIIGK.png) 影音元件在「所有WPF控制項中」 ![](https://i.imgur.com/JJV5BLY.png) 把影音元件拖到視窗中,你可以調整大小 ## 其他控制項 請同學依照以下的圖樣,設計出基本的介面,很多你都看過了,請一一拉進去你的視窗,順便再用之前學習到的技巧,將按鍵與字體的顏色調整成你喜歡的樣子! ![](https://i.imgur.com/QzP3gXB.png) 也讓同學把你做好的介面,跟它的 XAML 描述檔比較一下,你可以發現按鍵、輸入文字框也都只是用標籤來標註與描述的。 ```xml= <Grid> <MediaElement HorizontalAlignment="Left" Height="330" Margin="43,68,0,0" VerticalAlignment="Top" Width="659"/> <Button Content="播放" HorizontalAlignment="Left" Margin="43,420,0,0" VerticalAlignment="Top" Width="103" Height="30" Background="#FF6AC928"/> <Button Content="暫停 " HorizontalAlignment="Left" Margin="167,420,0,0" VerticalAlignment="Top" Width="103" Height="30" Background="#FF28A4C9"/> <Button Content="停止" HorizontalAlignment="Left" Margin="294,420,0,0" VerticalAlignment="Top" Width="103" Height="30" Background="#FFC92828" BorderBrush="#FF707070" Foreground="#FF56E6C5"/> <Button Content="停止" HorizontalAlignment="Left" Margin="417,420,0,0" VerticalAlignment="Top" Width="103" Height="30" BorderBrush="#FF707070" Foreground="Black"> <Button.Background> <LinearGradientBrush EndPoint="0.5,1" MappingMode="RelativeToBoundingBox" StartPoint="0.5,0"> <GradientStop Color="Black"/> <GradientStop Color="White" Offset="1"/> </LinearGradientBrush> </Button.Background> </Button> <TextBox HorizontalAlignment="Left" Height="23" Margin="43,40,0,0" TextWrapping="Wrap" Text="TextBox" VerticalAlignment="Top" Width="506"/> <Button Content="開啟檔案" HorizontalAlignment="Left" Margin="554,40,0,0" VerticalAlignment="Top" Width="148" Height="23" Background="#FFDFF7CF"/> </Grid> ``` 也請記得,將每一個控制項設定一個名稱,例如以下的範例名稱: :::info 1. 播放按鍵:btnPlay 2. 暫停按鍵:btnPause 3. 停止按鍵:btnStop 4. 離開按鍵:btnExit 5. 開啟檔案按鍵:btnOpenFile 6. 影音元件:MedShow 7. 輸入文字框:txtFilePath ::: ## 第二部分:程式碼撰寫 完成基本介面設計後,我們就要把程式寫進來,讓程式可以運作。 我們要先設定「開啟檔案按鍵」的事件綁定,請在「開啟檔案按鍵」點兩下,直接開啟程式碼,並且將以下的程式碼輸入。 ```csharp= private void btnOpenFile_Click(object sender, RoutedEventArgs e) { // 檔案開啟物件 var fd = new Microsoft.Win32.OpenFileDialog(); // 設定檔案過濾 fd.Filter = "音訊檔案(*.mp3,*.3gp,*.wma)|*.mp3; *.3gp; *.wma|影片檔案(*.mp4, *.avi, *.mpeg, *.wmv)|*.mp4; *.avi; *.mpeg; *.wmv|所有檔案(*.*)|*.*"; //fd.Filter = "MP3(*.mp3)|*.mp3|MP4(*.mp4)|*.mp4|3GP(*.3gp)|*.3gp|WMA(*.wma)|*.wma|MOV(*.mov)|*.mov|AVI(*.avi)|*.avi|WMV(*.wmv)|*.wmv|MPEG(*.mpeg)|*.mpeg|所有檔案(*.*)|*.*"; // 設定預設開啟檔案位置,設定為桌面 fd.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.Desktop); // 開啟對話框 fd.ShowDialog(); // 如果使用者有選取檔案,就把檔案位置與檔名儲存到filename中 string filename = fd.FileName; if (filename != "") { // 將檔案位置與檔名顯示在輸入文字框裡面 txtFilePath.Text = filename; // 將檔案位置與檔名轉化成URI,一種用來設定檔案資源定位的位置資料 Uri u = new Uri(filename); // 將URI放進影音元件中 MedShow.Source = u; // 設定這個影音的聲音大小(可有可無) MedShow.Volume = 0.5f; // 將影音進行播放 MedShow.LoadedBehavior = MediaState.Play; } } ``` 按下「F5」先來測試程式看看,你可以點選開啟檔案,開啟範例的影音檔試試看,看看能不能開啟? 或者你找一些自己的影片或聲音檔案,也可以測試看看能不能開啟?如果順利的話,你應該可以在視窗中看到影片,或者聽到聲音。 你也可以注意到,輸入文字框中會顯示你開啟檔案的檔案位置與檔名。 ![](https://i.imgur.com/hM2uemw.png) 這時你就已經初步完成這個簡易的影音播放程式了。 ### 電腦程式怎麼開啟檔案 在我們這個簡單的範例中,開啟檔案的方式,主要使用「**Microsoft.Win32.OpenFileDialog()**」這個類別(Class)。 :::info 什麼是「類別(Class)」,它是建立物件的藍圖,描述了所建立的物件共同的特性和方法。 ::: 你會有點昏頭吧?這時你就會想問什麼又是「物件(Object)」? :::info 在程式裡,所謂「物件(Object)」的概念,就是「執行個體」,白話文你可以想成:「一個可以在程式裡直接運用的東西」 ::: 換句話說,假設你有一台機車的設計圖,也有相關零件的規格書,甚至連操作說明書都有。 但是這樣等同有一台機車可以騎嗎?當然不是,你必須要根據設計圖來設計零件,組裝成整台機車,然後依照操作說明來操作這一台機車,這時候你才能把機車騎上路。 因此物件與類別的關係就像下圖: ``` mermaid graph TD; 機車設計圖/規格書/說明書-->機車; 類別-->物件; ``` 在程式裡,你要根據一個類別建立物件的語法,可以這樣寫: ```csharp= //語法 var 物件名稱 = new 類別名稱(); //範例 var fd = new Microsoft.Win32.OpenFileDialog(); ``` 因此 fd 是一個物件(Object),是根據「Microsoft.Win32.OpenFileDialog()」這個類別(Class)所製造出來的,或者是「new」一個出來的。 fd 可以開啟檔案,不過你可以先設定過濾,第6行就能設定只能有哪些檔案可以開啟。第8行則可以設定預設開啟位置,通常我們都先預設為桌面上。 最後我們用「fd.ShowDialog()」來開啟對話框,讓使用者自己找到檔案來開啟。 第16到25行則是讓影音檔案顯示在影印元件上,這部分我們下次上課會進行說明。