所以抽时间实现了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/ztJnMX2jYqaK3

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

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

相关文章: