安裝win8 64位,vs2013(包含wp8 sdk),百度各類獲得學生開發者帳戶以後,終於能夠試一下將本身的app部署到手機上的感受了。shell
首先來個簡單練練手的照相機功能express
即從主界面進入到照相機界面,進行拍照,並對照片進行保存app
對已拍照片管理,查看,刪除ide
MainPage.xaml函數
<phone:PhoneApplicationPage x:Class="OpenCamera.MainPage" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone" xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" FontFamily="{StaticResource PhoneFontFamilyNormal}" FontSize="{StaticResource PhoneFontSizeNormal}" Foreground="{StaticResource PhoneForegroundBrush}" SupportedOrientations="Portrait" Orientation="Portrait" shell:SystemTray.IsVisible="True"> <Grid> <Button Width="200" Height="200" Content="拍照" Click="ButtonBase_OnClick"></Button> </Grid> </phone:PhoneApplicationPage>
MainPage.xaml.csthis
public partial class MainPage : PhoneApplicationPage { // 構造函數 public MainPage() { InitializeComponent(); } private void ButtonBase_OnClick(object sender, RoutedEventArgs e) { this.NavigationService.Navigate(new Uri("/Camera.xaml", UriKind.RelativeOrAbsolute)); } }
意思就很簡單了,點擊拍照,就進入照相界面spa
下面拍照界面Camera.xaml設計
<Grid x:Name="LayoutRoot" Background="Transparent"> <Grid.RowDefinitions> <RowDefinition/> <RowDefinition Height="200"/> </Grid.RowDefinitions> <Canvas> <Canvas.Background> <VideoBrush x:Name="VideoBrush"></VideoBrush> </Canvas.Background> </Canvas> <StackPanel Grid.Row="1"> <Button Width="200" Height="200" Content="拍照" Click="ButtonBase_OnClick"> </Button> </StackPanel> </Grid>
一個Canvas用於顯示照相機捕捉到的圖像
一個按鈕,用於拍照調試
上MSDN查詢:http://msdn.microsoft.com/zh-cn/library/microsoft.devices.photocamera(v=vs.92).aspxcode
備註中提到一些實用方法,其中提到了幾個方法
OnNavigatedTo(導航到本頁面時觸發)
OnNavigatedFrom(離開本頁面後觸發)
OnNavigatingFrom(離開本頁面以前觸發)
在Camera.xaml.cs中依次重寫了3個方法,都打上斷點,看執行順序,發現執行過程是 點擊拍照按鈕=》OnNavigatedTo=》點擊返回=>OnNavigatingFrom=》OnNavigatedFrom
好,如今就明白了,在OnNavigatedTo中來初始化PhotoCamera對象實例,並捕捉圖像到Canvas上
protected override void OnNavigatedTo(NavigationEventArgs e) { _cam = new PhotoCamera(CameraType.Primary); VideoBrush.SetSource(_cam); base.OnNavigatedTo(e); }
好,此刻已按捺不住激動的心情了,編譯,在模擬器中調試....,可是,程序出錯。再次查看MSDN,發現這裏
有個東西須要設置一下
好,如今在編譯,運行,模擬器中以下
心想,這該沒有什麼問題了吧,插上手機,部署
運行,果真可以顯示圖像了。有點小興奮。
拍照就很簡單了,調用一個方法便可
private void ButtonBase_OnClick(object sender, RoutedEventArgs e) { _cam.CaptureImage(); }
調用了CaptrueImage方法,本覺得會返回照片,可是繼續查看MSDN發現須要註冊一個事件,來得到圖片。
這裏還用到了一個類MediaLibrary:http://msdn.microsoft.com/query/dev12.query?appId=Dev12IDEF1&l=ZH-CN&k=k(Microsoft.Xna.Framework.Media.MediaLibrary);k(TargetFrameworkMoniker-WindowsPhone,Version%3Dv8.0);k(DevLang-csharp)&rd=true
可是,這裏須要注意一下,使用MediaLibrary來保存數據還須要這一步設置,以下圖:
這樣,MediaLibrary才能正常使用(MSDN上沒有說明這個:坑呀)
這裏註冊圖片可用事件
protected override void OnNavigatingFrom(NavigatingCancelEventArgs e) { if (_cam != null) { _cam.Dispose(); _cam.Initialized -= _cam_Initialized; _cam.CaptureCompleted -= _cam_CaptureCompleted; _cam.CaptureImageAvailable -= _cam_CaptureImageAvailable; _cam.CaptureThumbnailAvailable -= _cam_CaptureThumbnailAvailable; } base.OnNavigatingFrom(e); } protected override void OnNavigatedTo(NavigationEventArgs e) { _cam = new PhotoCamera(CameraType.Primary); _library = new MediaLibrary(); VideoBrush.SetSource(_cam); _cam.Initialized += _cam_Initialized; _cam.CaptureCompleted += _cam_CaptureCompleted;//照相完成事件 _cam.CaptureImageAvailable += _cam_CaptureImageAvailable;//圖片可用事件 _cam.CaptureThumbnailAvailable += _cam_CaptureThumbnailAvailable;//縮略圖可用事件 base.OnNavigatedTo(e); }
在OnNvaigatingForm中取消訂閱事件
如今主要關注CaptureImageAvailable事件,該事件當照相生成的圖片可使用時觸發,先不要關注註釋部分的代碼,這樣就能將照片保存到手機相冊裏了
void _cam_CaptureImageAvailable(object sender, ContentReadyEventArgs e) { string fileName = string.Format("{0}-{1}-{2}", DateTime.Now.Hour, DateTime.Now.Minute, DateTime.Now.Second) + ".jpg"; _library.SavePictureToCameraRoll(fileName, e.ImageStream); #region 獨立存儲 //string floderName = "Photo"; //string fileName = string.Format("{0}-{1}-{2}", DateTime.Now.Hour, DateTime.Now.Minute, DateTime.Now.Second) + ".jpg"; //string fullName = Path.Combine(floderName, fileName); //using (IsolatedStorageFile file = IsolatedStorageFile.GetUserStoreForApplication()) //{ // if (!file.DirectoryExists(floderName)) // { // file.CreateDirectory(floderName); // } // if (!file.FileExists(fullName)) // { // using (IsolatedStorageFileStream fileStream = file.OpenFile(fullName, FileMode.Create, FileAccess.Write)) // { // byte[] readBuffer = new byte[4069]; // int bytesRead = -1; // while ((bytesRead = e.ImageStream.Read(readBuffer, 0, readBuffer.Length)) > 0) // { // fileStream.Write(readBuffer, 0, bytesRead); // } // } // } //} #endregion e.ImageStream.Close(); }
可是,咱們要製做本身的相冊,就須要獨立存儲。
獨立存儲這一塊請看MSDN吧,http://msdn.microsoft.com/zh-cn/library/system.io.isolatedstorage.isolatedstoragefile(v=vs.110).aspx
註釋部分的代碼就是將圖片保存到獨立存儲中,而不是手機的相冊中。
相冊就是將所拍的照片展現出來,暫時用ListBox實現
界面Photo.xaml
<Grid x:Name="LayoutRoot" Background="Transparent"> <Grid.RowDefinitions> <RowDefinition Height="Auto"/> <RowDefinition Height="*"/> </Grid.RowDefinitions> <!--TitlePanel 包含應用程序的名稱和頁標題--> <StackPanel Grid.Row="0" Orientation="Horizontal" Margin="12,17,0,28"> <TextBlock Text="相冊" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/> <Image x:Name="TestImage"></Image> </StackPanel> <!--ContentPanel - 在此處放置其餘內容--> <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0"> <ListBox ItemsSource="{Binding AllPhoto}"> <ListBox.ItemTemplate> <DataTemplate> <StackPanel> <Image Source="{Binding}"></Image> </StackPanel> </DataTemplate> </ListBox.ItemTemplate> </ListBox> </Grid> </Grid>
Photo.xaml.cs
#region 字段 private ObservableCollection<BitmapImage> _allPhoto; #endregion #region 屬性 public ObservableCollection<BitmapImage> AllPhoto { get { return _allPhoto; } set { _allPhoto = value; OnPropertyChanged("AllPhoto"); } } #endregion public Photos() { InitializeComponent(); this.DataContext = this; AllPhoto=new ObservableCollection<BitmapImage>(); } #region 導航事件 protected override void OnNavigatedTo(NavigationEventArgs e) { using(IsolatedStorageFile file=IsolatedStorageFile.GetUserStoreForApplication()) { if (file.DirectoryExists("PhotoTH")) { string[] fileNames = file.GetFileNames("/PhotoTH/"); foreach (var fileName in fileNames) { using (IsolatedStorageFileStream fileStream = file.OpenFile("/PhotoTH/" + fileName, FileMode.Open)) { BitmapImage bitmapImage=new BitmapImage(); bitmapImage.SetSource(fileStream); AllPhoto.Add(bitmapImage); } } } } base.OnNavigatedTo(e); } #endregion public event PropertyChangedEventHandler PropertyChanged; private void OnPropertyChanged(string propertyName) { if (PropertyChanged != null) { PropertyChanged(this,new PropertyChangedEventArgs(propertyName)); } }
這樣就能將圖所拍照片的圖片顯示出來了。
這裏通常都是長按相片,而後彈出菜單能夠選擇「刪除」選項,這個就用到相似於WPF的ContextMenu,可是弄死在WP8項目中就是沒有ContextMenu,各類百度以後,得知須要引用MicroSoft.Phone.Control.ToolKit
該Dll在http://www.nuget.org/packages/wptoolkit
下載以後,咱們的Photo界面就要稍微修改,下面是修改以後的Photo.xaml
<!--LayoutRoot 是包含全部頁面內容的根網格--> <Grid x:Name="LayoutRoot" Background="Transparent"> <Grid.RowDefinitions> <RowDefinition Height="Auto"/> <RowDefinition Height="*"/> </Grid.RowDefinitions> <!--TitlePanel 包含應用程序的名稱和頁標題--> <StackPanel Grid.Row="0" Orientation="Horizontal" Margin="12,17,0,28"> <TextBlock Text="相冊" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/> <Image x:Name="TestImage"></Image> </StackPanel> <!--ContentPanel - 在此處放置其餘內容--> <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0"> <ListBox ItemsSource="{Binding AllPhoto}"> <ListBox.ItemTemplate> <DataTemplate> <Button Width="200" Height="200"> <Button.Template> <ControlTemplate TargetType="Button"> <Grid> <Grid.Background> <ImageBrush ImageSource="{Binding Source}"> <ImageBrush.RelativeTransform> <CompositeTransform CenterX="0.5" CenterY="0.5" Rotation="90"></CompositeTransform> </ImageBrush.RelativeTransform> </ImageBrush> </Grid.Background> </Grid> </ControlTemplate> </Button.Template> <toolkit:ContextMenuService.ContextMenu> <toolkit:ContextMenu> <toolkit:MenuItem Header="刪除" Click="MenuItem_OnClick" Tag="{Binding}"></toolkit:MenuItem> </toolkit:ContextMenu> </toolkit:ContextMenuService.ContextMenu> </Button> </DataTemplate> </ListBox.ItemTemplate> </ListBox> </Grid> </Grid>
這裏須要注意一下,一開始咱們直接綁定的BitmapImage來獲取圖片,可是這樣在刪除的時候,不只要從集合中刪除BitmapImage,還要從獨立存儲中刪除該圖片,而BitmapImage獲取UriSource不到(但願有同窗解釋一下),這裏只能變通一下,建立類Photo
public class Photo { public string FileName { get; set; } public string FullName { get; set; } public BitmapImage Source { get; set; } }
這樣咱們集合中存儲的就是該Photo類型的變量,有文件名,還有包含整個路徑的文件名,還有BitmapImage對象,這樣刪除的時候,就很是容易了,下面是刪除圖片的代碼
private void MenuItem_OnClick(object sender, RoutedEventArgs e) { MenuItem item = sender as MenuItem; Photo photo = item.Tag as Photo; AllPhoto.Remove(photo); using (IsolatedStorageFile file = IsolatedStorageFile.GetUserStoreForApplication()) { if (file.FileExists(photo.FullName)) { file.DeleteFile(photo.FullName); } } }
好了,至此,大體的功能就完成了。覺得是一個很簡單的東西,其實其中還包含了一些未知的東西,如獨立存儲,還有配置文件(勾選相機功能可用的那個)等等,目前也就是學了個大概,後面還要慢慢深刻。
Demo:http://files.cnblogs.com/HelloMyWorld/OpenCamera.rar
人生還有無限可能,不要放棄努力。