隨着 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