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實現二維碼掃描的功能async

1. 在項目中添加對Zxing的引用ide

  Zxing示例代碼下載地址:http://zxingnet.codeplex.com/學習

2.添加頁面代碼this

  

 <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.功能實現spa

 

  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調試

  注意事項: 在調試時若是出現死機現象 ,請長按鎖屏鍵+音量(-)鍵 方可重啓手機。code

 學習交流QQ羣:157153754 (入羣成員請將您的暱稱改成: 城市-暱稱 )orm

相關文章
相關標籤/搜索