zoukankan      html  css  js  c++  java
  • 第一个WP8程序,照相机

    安装win8 64位,vs2013(包含wp8 sdk),百度各种得到学生开发者账户之后,终于可以试一下将自己的app部署到手机上的感觉了。

    首先来个简单练练手的照相机功能

    • 照相

    即从主界面进入到照相机界面,进行拍照,并对照片进行保存

    • 相册

    对已拍照片管理,查看,删除


    • 界面设计

     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.cs

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

    意思就很简单了,点击拍照,就进入照相界面

    下面拍照界面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用于显示照相机捕捉到的图像
    一个按钮,用于拍照

    • PhotoCamera

    上MSDN查询:http://msdn.microsoft.com/zh-cn/library/microsoft.devices.photocamera(v=vs.92).aspx

    备注中提到一些实用方法,其中提到了几个方法

    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

    人生还有无限可能,不要放弃努力。

  • 相关阅读:
    div 和 span的区别
    div 和 span的区别
    javascript类的定义及成员修改
    C# bho操作dom 同时带有隐藏工具栏功能,菜单栏
    javascript类的定义及成员修改
    数据库原理8个例子sql语句
    数据库原理8个例子sql语句
    C++的声明和定义的出别
    C++的声明和定义的出别
    Visual Studio 添加图标和版本
  • 原文地址:https://www.cnblogs.com/HelloMyWorld/p/3797767.html
Copyright © 2011-2022 走看看