Win10/UWP开发:让你的App使用上扫描仪

Cle****-he UID.1073626
2015-12-03 发表

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 命名空间下的成员,有几个很重要的成员先介绍下:

QuoteImageScanner 类
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
然后创建一个页面,前台代码如下
[mw_shl_code=csharp,true]<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>[/mw_shl_code]


后台代码如下
[mw_shl_code=csharp,true]/// <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 = 14 };
dialog.Content = new Scaning() { Width = 200, Height = 200 };
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 = 0; i < files.ScannedFiles.Count; i++)
{
//创建文件读取流
using (var fileStream = await files.ScannedFiles.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.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(0, 12, 0, 0) };

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();
}
[/mw_shl_code]



用到的一个UserControl –> Scaning, 是用来显示扫描中动画的,前台代码如下
[mw_shl_code=csharp,true]<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>[/mw_shl_code]


最后的效果
***图片停止解析***

具有设置选项的效果
***图片停止解析***
本文出自:53078485群大咖Aran

敬告:
为防止不可控的内容风险,本站已关闭新用户注册,新贴的发表及评论;
你现在看到的内容只是互联网用户曾经发表的言论快照,仅用于老用户留存纪念,且仅与科技行业相关,全部内容不代表本站观点及立场;
本站重新开放前已针对包括用户隐私、版权保护、信息安全、国家政策在内的各种互联网法律法规要求,执行了隐患内容的自查、屏蔽和删除;
本站目前所属个人主体,未有任何盈利安排与计划,且与原WFUN.COM所属公司不存在任何关联关系;
如果本帖内容或者相关资源侵犯到您的合法权益,或者您认为存在问题,那么请您务必点此举报或投诉!
全部回复:
zhangshengyou UID.302226
2015-12-03 使用 Lumia 1520 回复

技术流,看不懂

前面的路 UID.932351
2015-12-03 使用 Lumia 920T 回复

Quotezhangshengyou 发表于 2015-12-3 10:48
技术流,看不懂


一样的路过

t46****381 UID.971921
2015-12-03 使用 Lumia 920 回复

不知道说的什么但感觉很厉害的样子

qiqiminmin UID.638527
2015-12-05 回复

嗯,这个东西很不错。。。。

我还真没设计过 Desktop Extension。。。。

Qu****.W UID.1248939
2015-12-08 使用 Lumia 640 XL 回复

给力!
对扫描仪的描述很详细,多谢分享。

本站使用Golang构建,点击此处申请开源鄂ICP备18029942号-4联系站长投诉/举报