WindowsPhone8.1 二维码扫描

随着 WinRT 8.1 API 的发布Windows 8.1  Windows Phone 8.1 (基于 WinRT) 应用程序开发模型经历戏剧性收敛性一些特定于平台的考虑我们现在可以 Windows 使用几乎相同的 XAML 框架 API 来开发 Windows Phone 开发应用程序

"旧的"基于 Windows Phone 8.0 Silverlight API 继续得到支持改善基于 WinRT 融合模型显然未来

 

所以抽时间实现了wp8.1实现二维码扫描的功能

1. 在项目中添加对Zxing的引用

  Zxing示例代码下载地址:http://zxingnet.codeplex.com/

2.添加页面代码

  

 <Grid x:Name="LayoutRoot"  Background="Black">
        <Grid Background="Black">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="50"/>
                <ColumnDefinition Width="300"/>
                <ColumnDefinition Width="50"/>
            </Grid.ColumnDefinitions>
            <Grid Grid.Column="0" Height="366" Margin="0,0,0,0">

            </Grid>
            <!--取景器区域-->
            <Grid Grid.Column="1" x:Name="ScanViewGrid" Margin="0,0,0,0">
                <Grid.Resources>
                    <Storyboard x:Name="myStoryboard">
                        <DoubleAnimation
                                    Storyboard.TargetName="imgScan"
                                    Storyboard.TargetProperty="(Canvas.Top)"
                                    Duration="0:0:2.5"
                                    From="0"
                                    To="300"
                                    RepeatBehavior="Forever"/>
                    </Storyboard>
                </Grid.Resources>
                <!--扫描线-->
                
                    <Canvas Width="300"  Canvas.Top="170"  Height="300">
                        <CaptureElement  Stretch="UniformToFill" x:Name="VideoCapture"  Width="300" Height="300"  >
                         
                        </CaptureElement>
                        <Image x:Name="imgScan" Source="/Assets/img/light.png"  Width="300" Height="40" Stretch="Fill"/>

                        <Image x:Name="CaptureImage" Width="300" Height="300"  Visibility="Collapsed" />
                    </Canvas>
              
          
            </Grid>
            <Grid Grid.Column="2" Margin="0,0,0,0"/>
        </Grid>
      
        <TextBlock x:Name="Error" VerticalAlignment="Bottom" FontSize="32" Width="400" TextAlignment="Center" />
        <TextBlock x:Name="ScanResult" Text="hhh" FontSize="25" Foreground="White" VerticalAlignment="Bottom" TextAlignment="Center" Width="400"/>
    </Grid>
 

3.功能实现

 

  public sealed partial class QCodeView : Page
    {
        private readonly MediaCapture _mediaCapture = new MediaCapture();
        private Result _result;
        private NavigationHelper navigationHelper;
        private ObservableDictionary defaultViewModel = new ObservableDictionary();
        private DispatcherTimer _timer;
      
        public QCodeView()
        {
            this.InitializeComponent();
            //设备屏幕方向
            DisplayInformation.AutoRotationPreferences = DisplayOrientations.Portrait;
            ///隐藏StatusBar
            var statusBar = StatusBar.GetForCurrentView();
            statusBar.HideAsync();
            this.navigationHelper = new NavigationHelper(this);
            this.navigationHelper.LoadState += this.NavigationHelper_LoadState;
            this.navigationHelper.SaveState += this.NavigationHelper_SaveState;
        }

        /// <summary>
        /// 获取与此 <see cref="Page"/> 关联的 <see cref="NavigationHelper"/>/// </summary>
        public NavigationHelper NavigationHelper
        {
            get { return this.navigationHelper; }
        }

        /// <summary>
        /// 获取此 <see cref="Page"/> 的视图模型。
        /// 可将其更改为强类型视图模型。
        /// </summary>
        public ObservableDictionary DefaultViewModel
        {
            get { return this.defaultViewModel; }
        }

        /// <summary>
        /// 使用在导航过程中传递的内容填充页。  在从以前的会话
        /// 重新创建页时,也会提供任何已保存状态。
        /// </summary>
        /// <param name="sender">
        /// 事件的来源; 通常为 <see cref="NavigationHelper"/>
        /// </param>
        /// <param name="e">事件数据,其中既提供在最初请求此页时传递给
        /// <see cref="Frame.Navigate(Type, Object)"/> 的导航参数,又提供
        /// 此页在以前会话期间保留的状态的
        /// 字典。 首次访问页面时,该状态将为 null。</param>
        private void NavigationHelper_LoadState(object sender, LoadStateEventArgs e)
        {
        }

        /// <summary>
        /// 保留与此页关联的状态,以防挂起应用程序或
        /// 从导航缓存中放弃此页。值必须符合
        /// <see cref="SuspensionManager.SessionState"/> 的序列化要求。
        /// </summary>
        /// <param name="sender">事件的来源;通常为 <see cref="NavigationHelper"/></param>
        ///<param name="e">提供要使用可序列化状态填充的空字典
        ///的事件数据。</param>
        private void NavigationHelper_SaveState(object sender, SaveStateEventArgs e)
        {

        }

        #region NavigationHelper 注册

        /// <summary>
        /// 此部分中提供的方法只是用于使
        /// NavigationHelper 可响应页面的导航方法。
        /// <para>
        /// 应将页面特有的逻辑放入用于
        /// <see cref="NavigationHelper.LoadState"/>
        ///<see cref="NavigationHelper.SaveState"/> 的事件处理程序中。
        /// 除了在会话期间保留的页面状态之外
        /// LoadState 方法中还提供导航参数。
        /// </para>
        /// </summary>
        /// <param name="e">提供导航方法数据和
        /// 无法取消导航请求的事件处理程序。</param>
        protected  override void OnNavigatedTo(NavigationEventArgs e)
        {
          
            myStoryboard.Begin();
            InitVideoCapture();
            InitVideoTimer();
                
            this.navigationHelper.OnNavigatedTo(e);
        }


        /// <summary>
        /// 初始化摄像
        /// </summary>
        private async void InitVideoCapture()
        {
            ///摄像头的检测
            var cameras = await DeviceInformation.FindAllAsync(DeviceClass.VideoCapture);
            if (cameras.Count < 1)
            {
                Error.Text = "设备没有摄像头,读取本地资源";
                await DecodeStaticResource();
                return;
            }
           
            ///  创建 MediaCaptureInitializationSettings 对象的新实例。
            var settings = new MediaCaptureInitializationSettings
            {
                StreamingCaptureMode = StreamingCaptureMode.AudioAndVideo,
                MediaCategory = MediaCategory.Other,
                AudioProcessing = Windows.Media.AudioProcessing.Default,
                VideoDeviceId = cameras[1].Id
            };
            //if (cameras.Count == 1)
            //{
            //    settings = new MediaCaptureInitializationSettings { VideoDeviceId = cameras[0].Id }; // 0 => front, 1 => back
            //}
            //else
            //{
            //    settings = new MediaCaptureInitializationSettings { VideoDeviceId = cameras[1].Id }; // 0 => front, 1 => back
            //}

            await _mediaCapture.InitializeAsync(settings);
            VideoCapture.Source = _mediaCapture;
            await _mediaCapture.StartPreviewAsync();
        }
        private void InitVideoTimer()
        {
            _timer = new DispatcherTimer();
            _timer.Interval = TimeSpan.FromSeconds(6);
            _timer.Tick += _timer_Tick;
            _timer.Start();

        }
        private bool IsBusy = false;
        async void _timer_Tick(object sender, object e)
        {
            try
            {
                while (_result == null)
                {
                    if (!IsBusy)
                    {
                        IsBusy = true;
                        ///获取焦点
                        //var autoFocusSupported = _mediaCapture.VideoDeviceController.FocusControl.SupportedFocusModes.Contains(FocusMode.Auto);
                        //if (autoFocusSupported)
                        //{
                        //    var focusSettings = new FocusSettings
                        //    {
                        //        Mode = FocusMode.Auto,
                        //        AutoFocusRange = AutoFocusRange.Normal
                        //    };
                        //    _mediaCapture.VideoDeviceController.FocusControl.Configure(focusSettings);
                        //    //await _mediaCapture.VideoDeviceController.FocusControl.FocusAsync().AsTask(_cancellationTokenSource.Token);
                        //}

                        var photoStorageFile = await KnownFolders.PicturesLibrary.CreateFileAsync("qcode.jpg", CreationCollisionOption.ReplaceExisting);
                        await _mediaCapture.CapturePhotoToStorageFileAsync(ImageEncodingProperties.CreateJpeg(), photoStorageFile);

                        var stream = await photoStorageFile.OpenReadAsync();
                        // initialize with 1,1 to get the current size of the image
                        var writeableBmp = new WriteableBitmap(1, 1);
                        writeableBmp.SetSource(stream);
                        // and create it again because otherwise the WB isn‘t fully initialized and decoding
                        // results in a IndexOutOfRange
                        writeableBmp = new WriteableBitmap(writeableBmp.PixelWidth, writeableBmp.PixelHeight);
                        stream.Seek(0);
                        writeableBmp.SetSource(stream);
                        _result = ScanBitmap(writeableBmp);
                        await photoStorageFile.DeleteAsync(StorageDeleteOption.PermanentDelete);
                    }
                    if (_result != null)
                    {
                        await _mediaCapture.StopPreviewAsync();
                        VideoCapture.Visibility = Visibility.Collapsed;
                        CaptureImage.Visibility = Visibility.Visible;
                        ScanResult.Text = _result.Text;
                        _timer.Stop();
                        myStoryboard.Stop();
                        imgScan.Visibility = Visibility.Collapsed;
                       
                    }  
                    IsBusy = false;
                 
                }
            }
            catch (Exception ex)
            {
               
                IsBusy = false;
                //Error.Text = ex.Message;
            }
        }
        /// <summary>
        /// 读取本地资源
        /// </summary>
        /// <returns></returns>
        private async System.Threading.Tasks.Task DecodeStaticResource()
        {
            var file = await Windows.ApplicationModel.Package.Current.InstalledLocation.GetFileAsync(@"Assets\1.png");
            var stream = await file.OpenReadAsync();
            // initialize with 1,1 to get the current size of the image
            var writeableBmp = new WriteableBitmap(1, 1);
            writeableBmp.SetSource(stream);
            // and create it again because otherwise the WB isn‘t fully initialized and decoding
            // results in a IndexOutOfRange
            writeableBmp = new WriteableBitmap(writeableBmp.PixelWidth, writeableBmp.PixelHeight);
            stream.Seek(0);
            writeableBmp.SetSource(stream);
            CaptureImage.Source = writeableBmp;
            VideoCapture.Visibility = Visibility.Collapsed;
            CaptureImage.Visibility = Visibility.Visible;

            _result = ScanBitmap(writeableBmp);
            if (_result != null)
            {
                ScanResult.Text += _result.Text;
            }
            return;
        }
        /// <summary>
        /// 解析二维码图片
        /// </summary>
        /// <param name="writeableBmp">拍摄的图片</param>
        /// <returns></returns>
        private Result ScanBitmap(WriteableBitmap writeableBmp)
        {
            var barcodeReader = new BarcodeReader
            {
                TryHarder = true,
                AutoRotate = true
            };
            var result = barcodeReader.Decode(writeableBmp);

            if (result != null)
            {
                CaptureImage.Source = writeableBmp;
            }

            return result;
        }
        /// <summary>
        /// 页面离开时对_mediaCapture对象进行释放 
        /// 防止内存溢出及资源占用
        /// </summary>
        /// <param name="e"></param>
        protected override async void OnNavigatedFrom(NavigationEventArgs e)
        {
            try
            {
                await _mediaCapture.StopPreviewAsync();
                await _mediaCapture.StopRecordAsync();
                _mediaCapture.Dispose();
            }
            catch (Exception)
            {

            }
            this.navigationHelper.OnNavigatedFrom(e);
        }
        #endregion
    }

 源码下载地址:http://vdisk.weibo.com/s/ztJnMX2jYpttV

  注意事项: 在调试时如果出现死机现象 ,请长按锁屏键+音量(-)键 方可重启手机。

 学习交流QQ群:157153754 (入群成员请将您的昵称改为: 城市-昵称 )

WindowsPhone8.1 二维码扫描

上一篇:C#防止窗体多次打开


下一篇:程序windows上可以上传附件,部署到 linux服务器后出现 “上传目录 不可写” 怎么解决?