UWP的扫描仪功能现在被微软划分到了[Windows Desktop Extensions for the UWP]中,如果要使用扫描仪扫描图片到自己的App中,首先我们要添加[Windows Desktop Extensions for the UWP]的引用,这个dll中的所有类都是只能在Desktop设备上才能正常运行的。添加[Windows Desktop Extensions for the UWP]

扫描仪需要用Windows.Devices.Scanners 命名空间下的成员,有几个很重要的成员先介绍下:

ImageScanner 类

  • ImageScanner.DefaultScanSource       //获取为此扫描仪设备选择的默认扫描源
  • ImageScanner.DeviceId            //获取此扫描仪设备的 PnP 设备标识符
  • ImageScanner.FlatbedConfiguration    //获取并设置平板扫描单元的扫描设置,如扫描分辨率和颜色模式
  • ImageScanner.FromIdAsync        //创建基于扫描仪设备信息 ID 的 ImageScanner 对象的实例
  • ImageScanner.ScanFilesToFolderAsync        //扫描文件到文件夹 ,支持进度报告
  • ImageScanner.ScanPreviewToStreamAsync    //扫描文件到流

ImageScannerFlatbedConfiguration 类(这个类里面有很多属性都是和设置扫描仪有关的,主要的如下,其他就不一一列举了)

  • ImageScannerFlatbedConfiguration.ColorMode    //获取或设置平板扫描仪的颜色模式如黑白灰度等
  • ImageScannerFlatbedConfiguration.DesiredResolution    //获取或设置应用程序请求的扫描仪平板的水平和垂直扫描分辨率(以 DPI 为单位)
  • ImageScannerFlatbedConfiguration.Format        //获取或设置从扫描仪的平板到客户端应用程序的图像数据获取的当前文件传输格式。
  • ImageScannerFlatbedConfiguration.SelectedScanRegion    //获取或设置选定扫描区域的原始坐标(水平和垂直)和维度(宽度和高度)(以英寸为单位)

接下来,我们需要一台扫描仪,扫描仪装好驱动,并支持WIA 2.0 .我的是TOSHIBA 2008S

然后创建一个页面,前台代码如下:

 <Page.BottomAppBar>
<CommandBar>
<CommandBar.Content>
<Grid/>
</CommandBar.Content>
<AppBarButton Icon="Scan" Label="Scan Images" x:Name="Bar_ScanFiles" Click="Bar_ScanFiles_Click"/>
</CommandBar>
</Page.BottomAppBar> <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}" >
<Viewbox>
<Grid>
<Path Data="M0,589.122C7.23756,591.35,15.1453,592.686,23.5452,592.686L734.433,592.686C742.831,592.686,750.74,591.35,758,589.122L746.228,633.25C746.228,642.477,735.684,650,722.639,650L35.3397,650C22.3137,650,11.7945,642.477,11.7945,633.25z M410.134,418.119L541.24,418.119 635.51,532.435 363.028,532.435z M209.217,402.719C198.74,402.719,195.772,408.064,187.462,416.255L73.5126,540.241C73.5126,547.715,81.9774,553.729,92.4548,553.729L378.964,553.729 665.473,553.729C675.95,553.729,684.484,547.715,684.484,540.241L570.516,416.255C562.228,408.064,559.258,402.719,548.757,402.719L378.964,402.719z M168.384,389.421L378.964,389.421 589.591,389.421C602.638,389.421,606.277,396.102,616.622,406.219L758,560.028C758,569.288,747.43,576.795,734.433,576.795L378.964,576.795 23.5452,576.795C10.5443,576.795,0,569.288,0,560.028L141.375,406.219C151.651,396.102,155.358,389.421,168.384,389.421z M164.949,0L378.966,0 593.029,0C606.078,-5E-06,616.621,7.50893,616.621,16.7822L616.621,358.018C616.621,367.277,606.078,374.785,593.029,374.785L378.966,374.785 164.949,374.785C151.925,374.785,141.379,367.277,141.379,358.018L141.379,16.7822C141.379,7.50893,151.925,-5E-06,164.949,0z" Stretch="Uniform" Fill="#FF434343" Width="160" Height="160" Margin="0,0,0,0" RenderTransformOrigin="0.5,0.5">
<Path.RenderTransform>
<TransformGroup>
<TransformGroup.Children>
<RotateTransform Angle="0" />
<ScaleTransform ScaleX="0.5" ScaleY="0.5" />
</TransformGroup.Children>
</TransformGroup>
</Path.RenderTransform>
</Path>
</Grid>
</Viewbox> <GridView x:Name="ImgList"></GridView> </Grid>

后台代码如下:

 /// <summary>
/// 开始扫描
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private async void Bar_ScanFiles_Click(object sender, RoutedEventArgs e)
{
var scanner = await GetScanner();
if (scanner == null) return; //保存至用户图片库
//var results = await scanner.ScanFilesToFolderAsync(scanner.DefaultScanSource, KnownFolders.PicturesLibrary); //取消任务的Token
cancellationToken = new CancellationTokenSource(); //扫描中的对话框
ContentDialog dialog = new ContentDialog();
dialog.Title = new TextBlock { Text = "扫描中...", FontSize = };
dialog.Content = new Scaning() { Width = , Height = };
dialog.PrimaryButtonText = "取消";
dialog.PrimaryButtonClick += (s, a) =>
{
cancellationToken.Cancel();
cancellationToken.Token.Register(() =>
{
dialog.Hide();
});
};
dialog.ShowAsync();
try
{
//获取预览 ->直接返回 Stream 不过图片质量很差
//IRandomAccessStream stream = new InMemoryRandomAccessStream();
//await scanner.ScanPreviewToStreamAsync(scanner.DefaultScanSource, stream).AsTask(cancellationToken.Token); //扫描 -> 获取到扫描完成的文件
var files = await Scanner.ScanFilesToFolderAsync(Scanner.DefaultScanSource, KnownFolders.SavedPictures).AsTask(cancellationToken.Token); for (int i = ; i < files.ScannedFiles.Count; i++)
{
//创建文件读取流
using (var fileStream = await files.ScannedFiles[i].OpenStreamForReadAsync())
{
var bitmap = new BitmapImage();
await bitmap.SetSourceAsync(fileStream.AsRandomAccessStream());
ImgList.Items.Add(new Image { Source = bitmap });
}
//用完流后删除下图片
await Task.Factory.StartNew(() => File.Delete(files.ScannedFiles[i].Path));
}
}
catch (TaskCanceledException)
{
Debug.WriteLine("A task was canceled.");
}
catch (Exception)
{
Debug.WriteLine("扫描出错");
}
finally
{
dialog.Hide();
}
} /// <summary>
/// 获取扫描仪对象
/// </summary>
/// <returns>ImageScanner</returns>
private async Task<ImageScanner> GetScanner()
{
try
{
var device = await DeviceInformation.FindAllAsync(DeviceClass.ImageScanner);
var scanner = await ImageScanner.FromIdAsync(device.FirstOrDefault().Id);
return scanner;
}
catch (Exception)
{
await OpenScannerWithError("你可以尝试以下操作后重试:\r\n1、未发现可用的扫描仪设备\r\n2、没有安装适合的WIA2.0兼容驱动程序",
true, "重试", true, "取消",
() => { Bar_ScanFiles_Click(null, null); });
return null;
}
} /// <summary>
/// 弹出错误提示
/// </summary>
/// <param name="error">错误描述</param>
/// <param name="hasPrimaryBtn">是否具有主按钮</param>
/// <param name="primaryBtnText">主按钮Text</param>
/// <param name="hasSecondaryBtn">是否具有副按钮</param>
/// <param name="secondaryBtnText">副按钮Text</param>
/// <param name="primaryBtnClick">主按钮点击后执行的方法</param>
/// <param name="secondaryBtnClick">副按钮点击后执行的方法</param>
/// <returns>null</returns>
private async Task OpenScannerWithError(string error, bool hasPrimaryBtn = false, string primaryBtnText = null, bool hasSecondaryBtn = false, string secondaryBtnText = null, Action primaryBtnClick = null, Action secondaryBtnClick = null)
{
ContentDialog dialog = new ContentDialog();
var dialogTitle = new StackPanel(); dialogTitle.Children.Add(new TextBlock { Text = "出错啦 ( ▼-▼ )", Foreground = new SolidColorBrush(Colors.Red) }); var dialogContent = new StackPanel() { Margin = new Thickness(, , , ) }; dialogContent.Children.Add(new TextBlock { Text = error }); dialog.Title = dialogTitle; dialog.Content = dialogContent; if (hasPrimaryBtn)
{
dialog.PrimaryButtonText = "重试";
if (primaryBtnClick != null)
{
dialog.Hide();
dialog.PrimaryButtonClick += (s, a) =>
{
primaryBtnClick();
};
}
} if (hasSecondaryBtn)
{
dialog.SecondaryButtonText = "取消"; dialog.SecondaryButtonClick += (s, a) =>
{
dialog.Hide();
if (secondaryBtnClick != null)
{
secondaryBtnClick();
}
};
}
await dialog.ShowAsync();
}

用到的一个UserControl –> Scaning, 是用来显示扫描中动画的,前台代码如下:

 <UserControl
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:ScannerDeviceSample.UserControls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:Interactivity="using:Microsoft.Xaml.Interactivity" xmlns:Core="using:Microsoft.Xaml.Interactions.Core" xmlns:Media="using:Microsoft.Xaml.Interactions.Media"
x:Class="ScannerDeviceSample.UserControls.Scaning"
mc:Ignorable="d"
d:DesignHeight="200"
d:DesignWidth="200">
<UserControl.Resources>
<Storyboard x:Name="ScaningStoryboard" AutoReverse="True" RepeatBehavior="Forever">
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.TranslateY)" Storyboard.TargetName="recScanning">
<EasingDoubleKeyFrame KeyTime="0" Value="0"/>
<EasingDoubleKeyFrame KeyTime="0:0:2" Value="-200"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</UserControl.Resources> <Interactivity:Interaction.Behaviors>
<Core:EventTriggerBehavior EventName="Loaded">
<Media:ControlStoryboardAction Storyboard="{StaticResource ScaningStoryboard}"/>
</Core:EventTriggerBehavior>
</Interactivity:Interaction.Behaviors> <Grid>
<Path Data="M2.8160041,17.083004L2.8160041,18.351004 15.944004,18.351004 15.944004,17.083004z M2.8160041,13.907004L2.8160041,15.174004 15.944004,15.174004 15.944004,13.907004z M2.8160041,10.731004L2.8160041,11.999004 15.944004,11.999004 15.944004,10.731004z M0,1.356853E-05L10.572985,1.356853E-05 10.572985,7.9669956 18.761999,7.9669956 18.761999,21.176014 0,21.176014z M11.945004,0L18.761988,6.6610196 11.945004,6.6610196z" Stretch="Uniform" Fill="Black" Width="128" Height="128" Margin="0,0,0,0" RenderTransformOrigin="0.5,0.5">
<Path.RenderTransform>
<TransformGroup>
<RotateTransform Angle="0" />
<ScaleTransform ScaleX="0.8" ScaleY="1" />
</TransformGroup>
</Path.RenderTransform>
</Path>
<Rectangle x:Name="recScanning" Height="2" RenderTransformOrigin="0.5,0.5" VerticalAlignment="Bottom" d:LayoutOverrides="Height">
<Rectangle.RenderTransform>
<CompositeTransform/>
</Rectangle.RenderTransform>
<Rectangle.Projection>
<PlaneProjection/>
</Rectangle.Projection>
<Rectangle.Fill>
<LinearGradientBrush EndPoint="0,0.5" StartPoint="1,0.5">
<GradientStop Color="#331CF106" Offset="0.15"/>
<GradientStop Color="#331CF106" Offset="0.85"/>
<GradientStop Color="#FF1CF106" Offset="0.5"/>
</LinearGradientBrush>
</Rectangle.Fill>
</Rectangle>
</Grid>
</UserControl>

最后的效果:

推荐一个UWP开发群:53078485 大家可以进来一起学习~~

Win10/UWP 让你的App使用上扫描仪的更多相关文章

  1. Win10 UWP开发系列:使用VS2015 Update2+ionic开发第一个Cordova App

    安装VS2015 Update2的过程是非常曲折的.还好经过不懈的努力,终于折腾成功了. 如果开发Cordova项目的话,推荐大家用一下ionic这个框架,效果还不错.对于Cordova.PhoneG ...

  2. Win10/UWP开发—使用Cortana语音与App后台Service交互

    上篇文章中我们介绍了使用Cortana调用前台App,不熟悉的移步到:Win10/UWP开发—使用Cortana语音指令与App的前台交互,这篇我们讲讲如何使用Cortana调用App的后台任务,相比 ...

  3. Win10 UWP开发系列:实现Master/Detail布局

    在开发XX新闻的过程中,UI部分使用了Master/Detail(大纲/细节)布局样式.Win10系统中的邮件App就是这种样式,左侧一个列表,右侧是详情页面.关于这种 样式的说明可参看MSDN文档: ...

  4. Win10 UWP开发实现Bing翻译

    微软在WP上的发展从原来的Win7到Win8,Win8.1,到现在的Win10 UWP,什么是UWP,UWP即Windows 10 中的Universal Windows Platform简称.即Wi ...

  5. Win10/UWP新特性—SharedStorageAccessManager 共享文件

    首先先给大家推荐一个UWP/Win10开发者群:53078485  里面有很多大婶,还有很多学习资源,欢迎大家来一起讨论Win10开发! 在UWP开发中,微软提供了一个新的特性叫做SharedStor ...

  6. 【Win10 UWP】QQ SDK(二):SDK的回调处理

    上一讲,我们介绍了QQ SDK的使用方法,请看<[Win10 UWP]QQ SDK(一):SDK基本使用方法> 一. 回调的基本形式 从前面的介绍中我们知道,我们的应用和QQ客户端之间需要 ...

  7. Win10 UWP应用发布流程

    简介 Win10 UWP应用作为和Win8.1 UAP应用不同的一种新应用形式,其上传至Windows应用商店的流程也有了一些改变. 这篇博文记录了我们发布一款Win10 UWP应用的基本流程,希望为 ...

  8. win10 uwp DataContext

    本文告诉大家DataContext的多种绑法. 适合于WPF的绑定和UWP的绑定. 我告诉大家很多个方法,所有的方法都有自己的优点和缺点,可以依靠自己喜欢的用法使用.当然,可以在新手面前秀下,一个页面 ...

  9. 【广告】win10 uwp 水印图床 含代码

    本文主要是广告我的软件. 图床可以加速大家写博客上传图片的时间,通过简化我们的操作来得到加速. 在写博客的时候,我们发现,我们需要上传一张图片,需要先打开图片,然后选择本地图片,然后上传. 但是我经常 ...

随机推荐

  1. UIKit框架

    在今后的应用程序构建中,会陆续使用各式各样的控件,因此UIKit框架的引入是必不可少的! 一.简介 UIKitk框架提供一系列的Class(类)来建立和管理iPhone OS应用程序的用户界面接口.应 ...

  2. blade and soul pvp guide

    PvP PvP in Blade and Soul is categorized into two types, a personal PvP called Arena and a large-sca ...

  3. scala 打印一个乘法口诀表 (<<scala 编程>> P87)

    (for(i <- 1 to 9;j <- 1 to i; s = s"$j*$i=${i*j}\t") yield {if(j==1) s"$s\n&quo ...

  4. EasyUI表单内容整理

    <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding= ...

  5. TRACERT命令

    这半个月  服务器从联通线路换到移动线路 导致基层用联通和电信线路的用户 上不去收费软件 tracert 120.194.42.142:8090 发现路由器 解析地址绕过很多条街后 出现丢包现象 联系 ...

  6. Mvc4学习笔记一(Ajax.ActionLink)

    <style type="text/css"> #left {width:200px; min-height:500px;border:1px solid #ccc;f ...

  7. MiniTwitter记住密码等功能实现

    一.SharedPreferences的用法:(相关实现功能的只是了解) 由于SharedPreferences是一个接口,而且在这个接口里没有提供写入数据和读取数据的能力.但它是通过其Editor接 ...

  8. Y+的一些讨论

    一.关于 fluent计算时壁面函数法和网格的关系,还有一个小问题 1:各位用 fluent的同仁和高手们,我想要比较好的使用 fluent软件,最重要的就是要学好理 论,在这里我想请教各位一个问题, ...

  9. C++多线程1

    一个多线程的实例 #include "stdafx.h" #include <windows.h> DWORD __stdcall Func(LPVOID pm) { ...

  10. hibernate的一种报错

    Exception in thread "main" java.lang.NoClassDefFoundError: javax/tools/StandardJavaFileMan ...