Win10/UWP 让你的App使用上扫描仪
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使用上扫描仪的更多相关文章
- Win10 UWP开发系列:使用VS2015 Update2+ionic开发第一个Cordova App
安装VS2015 Update2的过程是非常曲折的.还好经过不懈的努力,终于折腾成功了. 如果开发Cordova项目的话,推荐大家用一下ionic这个框架,效果还不错.对于Cordova.PhoneG ...
- Win10/UWP开发—使用Cortana语音与App后台Service交互
上篇文章中我们介绍了使用Cortana调用前台App,不熟悉的移步到:Win10/UWP开发—使用Cortana语音指令与App的前台交互,这篇我们讲讲如何使用Cortana调用App的后台任务,相比 ...
- Win10 UWP开发系列:实现Master/Detail布局
在开发XX新闻的过程中,UI部分使用了Master/Detail(大纲/细节)布局样式.Win10系统中的邮件App就是这种样式,左侧一个列表,右侧是详情页面.关于这种 样式的说明可参看MSDN文档: ...
- Win10 UWP开发实现Bing翻译
微软在WP上的发展从原来的Win7到Win8,Win8.1,到现在的Win10 UWP,什么是UWP,UWP即Windows 10 中的Universal Windows Platform简称.即Wi ...
- Win10/UWP新特性—SharedStorageAccessManager 共享文件
首先先给大家推荐一个UWP/Win10开发者群:53078485 里面有很多大婶,还有很多学习资源,欢迎大家来一起讨论Win10开发! 在UWP开发中,微软提供了一个新的特性叫做SharedStor ...
- 【Win10 UWP】QQ SDK(二):SDK的回调处理
上一讲,我们介绍了QQ SDK的使用方法,请看<[Win10 UWP]QQ SDK(一):SDK基本使用方法> 一. 回调的基本形式 从前面的介绍中我们知道,我们的应用和QQ客户端之间需要 ...
- Win10 UWP应用发布流程
简介 Win10 UWP应用作为和Win8.1 UAP应用不同的一种新应用形式,其上传至Windows应用商店的流程也有了一些改变. 这篇博文记录了我们发布一款Win10 UWP应用的基本流程,希望为 ...
- win10 uwp DataContext
本文告诉大家DataContext的多种绑法. 适合于WPF的绑定和UWP的绑定. 我告诉大家很多个方法,所有的方法都有自己的优点和缺点,可以依靠自己喜欢的用法使用.当然,可以在新手面前秀下,一个页面 ...
- 【广告】win10 uwp 水印图床 含代码
本文主要是广告我的软件. 图床可以加速大家写博客上传图片的时间,通过简化我们的操作来得到加速. 在写博客的时候,我们发现,我们需要上传一张图片,需要先打开图片,然后选择本地图片,然后上传. 但是我经常 ...
随机推荐
- python【6】-函数式编程
一.高阶函数 map,reduce 1.map() 函数接收两个参数,一个是函数,一个是序列,map将传入的函数依次作用到序列的每个元素,并把结果作为新的list返回. def f(x): retur ...
- MHA+Atlas+mysql一主一从开启gtid安装配置与实验
各节点架构 (说明:生产环境有两个节点可以组成一套完整集群,我是测试环境,因此对于manager以及atlas和binlog server都是单点,如果生产环境,相应的将manager以及atlas和 ...
- Socket通信 简单实现私聊、群聊(dos命令下)
很久以前的一个Demo,这里服务器只做转发功能,根据ID地址和端口号来标识身份,群聊和私聊只是简单实现, 服务器代码如下: import java.util.*; import java.io.*; ...
- java IO学习
1.如何将byte[]转换为String byte byt[] = new byte[1024]; int b = file.read(byt); //b是byt的实际读取到的长度 String st ...
- 2018. The Debut Album
http://acm.timus.ru/problem.aspx?space=1&num=2018 真心爱过,怎么能彻底忘掉 题目大意: 长度为n的串,由1和2组成,连续的1不能超过a个,连续 ...
- 在MAC上搭建cordova3.4.0的IOS和android开发环境
Hello,大家好,今天给大家说说在mac上搭建cordova3.4.0的iOS和Android开发环境,首先下载cordova,地址:https://cordova.apache.org/#down ...
- mysql数据库每日定时自动备份
使用navicat
- 爬虫:selenium + phantomjs 解决js抓取问题(一)
selenium模块主要用来做测试,模拟键盘.鼠标来操作浏览器. phantomjs 就像一个无界面的浏览器一样. 两个结合能很好的解决js抓取的问题. 测试代码: #coding=utf-8 fro ...
- linux内核学习之七 可执行程序的装载和运行
一 程序的装载和运行的基本知识补充 1 当进程开始执行一个新的程序时,从父进程继承的所有页被释放,以便在新的用户地址空间开始执行新的计算,甚至进程的特权都可能发生改变,但是,进程的PID不会改变 ...
- C++多线程1
一个多线程的实例 #include "stdafx.h" #include <windows.h> DWORD __stdcall Func(LPVOID pm) { ...