本文概述
- 要求
- 1.添加WIA参考
- 2.列出扫描仪设备
- 3.使用设备进行扫描
- 4.更改WIA属性
- 5.捕捉异常
- 6.显示扫描进度
- 实施实例
WIA使需要与成像硬件进行交互的应用程序开发人员, 设备制造商和扫描仪用户变得容易。该API集通过提供对以下方面的支持, 使成像应用程序具有静止图像采集硬件功能:
- 枚举可用的图像采集设备(Windows中已安装的扫描仪)。
- 同时创建到多个设备的连接。
- 以标准且可扩展的方式查询设备的属性。
- 通过使用标准和高性能传输机制来获取设备数据。
- 跨数据传输维护图像属性。
- 设备状态通知和扫描事件处理。
要求
- Visual Studio> = 2007(我们将使用Visual Studio社区)
- 已安装且功能正常的扫描仪
1.添加WIA参考 使用最新的.NET Framework版本(或旧的C#项目)创建一个新的WinForms项目。然后继续直接从Visual Studio引用Windows Image Acquisition COM组件。组件对象模型(COM)是独立于平台, 分布式, 面向对象的系统, 用于创建可以交互的二进制软件组件。 .NET组件可以调用COM组件并与之交互。
转到位于Visual Studio右上角的解决方案资源管理器, 并右键单击你的项目, 然后单击” 添加” > ” 引用” 。
文章图片
在紧急窗口中, 选择左侧菜单中的COM选项, 然后搜索Microsoft Windows Image Acquisition Library v2.0, 然后单击OK。
文章图片
单击确定后, 引用将添加到你的项目中。现在, 你需要将WIA组件的Embed Interop Types属性设置为False。使用Visual Studio转到” 解决方案资源管理器” 并选择你的项目, 然后在项目中单击树视图组件中的” 引用” 并搜索WIA。选择WIA参考, 然后在” 属性” 面板中查找” 嵌入互操作类型” 选项, 并将此值设置为False:
文章图片
现在, 你将可以在项目中使用WIA。
2.列出扫描仪设备 要列出设备, 你需要从WIA的DevicesManager对象中检索列表。第一步, 你需要在类顶部的代码中导入WIA组件:
using WIA;
然后只需遍历设备管理器以列出设备:
// Create a DeviceManager instancevar deviceManager = new DeviceManager();
// Loop through the list of devicesfor (int i = 1;
i <
= deviceManager.DeviceInfos.Count;
i++){// Skip the device if it's not a scannerif (deviceManager.DeviceInfos[i].Type != WiaDeviceType.ScannerDeviceType){continue;
}// Print something like e.g "WIA Canoscan 4400F"Console.WriteLine(deviceManager.DeviceInfos[i].Properties["Name"].get_Value());
// e.g Canoscan 4400F//Console.WriteLine(deviceManager.DeviceInfos[i].Properties["Description"].get_Value());
// e.g \\.\Usbscan0//Console.WriteLine(deviceManager.DeviceInfos[i].Properties["Port"].get_Value());
}
Properties对象具有其他属性, 例如Id, Port, Manufacturer和Type, 请访问有关WIA设备信息类的MSDN页面以获取更多信息。
3.使用设备进行扫描 要保存扫描的图像, 你将需要导入以下类型:
using WIA;
using System.IO;
然后, 使用扫描仪的逻辑如下:
- 检索要使用的扫描仪的DeviceInfo实例。
- 使用DeviceInfo实例连接到扫描仪。
- 通过带有连接实例的items属性内具有索引1的元素选择扫描程序。
- 使用所选扫描仪的传输方法, 并提供扫描图像的输出格式作为第一个参数。
- 将返回的图像数据保存到文件中。
注意 如果处理不当, 选择扫描仪, 然后使用其余代码启动扫描过程的过程可能会有些棘手。例如, 我们建议你向列表中添加一个列表框项, 并追加一个新项, 该项也显示名称和DeviceInfos对象(你将在本文结尾看到一个示例)。
// Create a DeviceManager instancevar deviceManager = new DeviceManager();
// Create an empty variable to store the scanner instanceDeviceInfo firstScannerAvailable = null;
// Loop through the list of devices to choose the first availablefor (int i = 1;
i <
= deviceManager.DeviceInfos.Count;
i++){// Skip the device if it's not a scannerif (deviceManager.DeviceInfos[i].Type != WiaDeviceType.ScannerDeviceType){continue;
}firstScannerAvailable = deviceManager.DeviceInfos[i];
break;
}// Connect to the first available scannervar device = firstScannerAvailable.Connect();
// Select the scannervar scannerItem = device.Items[1];
// Retrieve a image in JPEG format and store it into a variablevar imageFile = (ImageFile)scannerItem.Transfer(FormatID.wiaFormatJPEG);
// Save the image in some path with filenamevar path = @"C:\Users\<
username>
\Desktop\scan.jpeg";
if (File.Exists(path)){File.Delete(path);
}// Save image !imageFile.SaveFile(path);
如果你对其进行测试, 则代码将起作用并且扫描仪将启动, 但是大多数扫描仪上的图像将不完整。这是因为我们没有设置扫描仪的任何常用属性, 你将在接下来的步骤中学习设置。
4.更改WIA属性 WIA有一些可修改的属性, 例如扫描宽度和高度, 颜色模式等。要设置此属性, 我们需要检索WIA.Properties类的属性, 然后设置新值。首先导入所需的类型:
using WIA;
using System.IO;
以下方法AdjustScannerSettings将通过帮助器函数SetWIAProperty设置一些基本属性, 以使其至少在大多数扫描设备中都起作用。请注意, 你需要在AdjustScannerSettings(通过连接实例的items属性内具有索引1的元素选择并分配给变量的扫描仪)方法中提供第一个参数作为扫描仪项目, 并在函数中记录其他参数。
重要 请记住, WIA具有许多可以修改的属性常数, 并且这些常数在不同的扫描设备上可能不可用(例如, 使用常数6147来修改水平分辨率), 请阅读以下MSDN页面以获取更多信息。
/// <
summary>
/// Adjusts the settings of the scanner with the providen parameters./// <
/summary>
/// <
param name="scannnerItem">
Scanner Item<
/param>
/// <
param name="scanResolutionDPI">
Provide the DPI resolution that should be used e.g 150<
/param>
/// <
param name="scanStartLeftPixel">
<
/param>
/// <
param name="scanStartTopPixel">
<
/param>
/// <
param name="scanWidthPixels">
<
/param>
/// <
param name="scanHeightPixels">
<
/param>
/// <
param name="brightnessPercents">
<
/param>
/// <
param name="contrastPercents">
Modify the contrast percent<
/param>
/// <
param name="colorMode">
Set the color mode<
/param>
private static void AdjustScannerSettings(IItem scannnerItem, int scanResolutionDPI, int scanStartLeftPixel, int scanStartTopPixel, int scanWidthPixels, int scanHeightPixels, int brightnessPercents, int contrastPercents, int colorMode){const string WIA_SCAN_COLOR_MODE = "6146";
const string WIA_HORIZONTAL_SCAN_RESOLUTION_DPI = "6147";
const string WIA_VERTICAL_SCAN_RESOLUTION_DPI = "6148";
const string WIA_HORIZONTAL_SCAN_START_PIXEL = "6149";
const string WIA_VERTICAL_SCAN_START_PIXEL = "6150";
const string WIA_HORIZONTAL_SCAN_SIZE_PIXELS = "6151";
const string WIA_VERTICAL_SCAN_SIZE_PIXELS = "6152";
const string WIA_SCAN_BRIGHTNESS_PERCENTS = "6154";
const string WIA_SCAN_CONTRAST_PERCENTS = "6155";
SetWIAProperty(scannnerItem.Properties, WIA_HORIZONTAL_SCAN_RESOLUTION_DPI, scanResolutionDPI);
SetWIAProperty(scannnerItem.Properties, WIA_VERTICAL_SCAN_RESOLUTION_DPI, scanResolutionDPI);
SetWIAProperty(scannnerItem.Properties, WIA_HORIZONTAL_SCAN_START_PIXEL, scanStartLeftPixel);
SetWIAProperty(scannnerItem.Properties, WIA_VERTICAL_SCAN_START_PIXEL, scanStartTopPixel);
SetWIAProperty(scannnerItem.Properties, WIA_HORIZONTAL_SCAN_SIZE_PIXELS, scanWidthPixels);
SetWIAProperty(scannnerItem.Properties, WIA_VERTICAL_SCAN_SIZE_PIXELS, scanHeightPixels);
SetWIAProperty(scannnerItem.Properties, WIA_SCAN_BRIGHTNESS_PERCENTS, brightnessPercents);
SetWIAProperty(scannnerItem.Properties, WIA_SCAN_CONTRAST_PERCENTS, contrastPercents);
SetWIAProperty(scannnerItem.Properties, WIA_SCAN_COLOR_MODE, colorMode);
}/// <
summary>
/// Modify a WIA property/// <
/summary>
/// <
param name="properties">
<
/param>
/// <
param name="propName">
<
/param>
/// <
param name="propValue">
<
/param>
private static void SetWIAProperty(IProperties properties, object propName, object propValue){Property prop = properties.get_Item(ref propName);
prop.set_Value(ref propValue);
}
值得再次说明, 这取决于你对属性的自定义, 但是我们为你提供了一种使用SetWIAProperty方法自定义属性的简单方法。
最后, 要正确开始扫描, 你只需要在初始化扫描器之前执行AdjustScannerSettings方法(混合步骤3和4):
// Create a DeviceManager instancevar deviceManager = new DeviceManager();
// Create an empty variable to store the scanner instanceDeviceInfo firstScannerAvailable = null;
// Loop through the list of devices to choose the first availablefor (int i = 1;
i <
= deviceManager.DeviceInfos.Count;
i++){// Skip the device if it's not a scannerif (deviceManager.DeviceInfos[i].Type != WiaDeviceType.ScannerDeviceType){continue;
}firstScannerAvailable = deviceManager.DeviceInfos[i];
break;
}// Connect to the first available scannervar device = firstScannerAvailable.Connect();
// Select the scannervar scannerItem = device.Items[1];
/** * Set the scanner settings */int resolution = 150;
int width_pixel = 1250;
int height_pixel = 1700;
int color_mode = 1;
AdjustScannerSettings(scannerItem, resolution, 0, 0, width_pixel, height_pixel, 0, 0, color_mode);
// Retrieve a image in JPEG format and store it into a variablevar imageFile = (ImageFile)scannerItem.Transfer(FormatID.wiaFormatJPEG);
// Save the image in some path with filenamevar path = @"C:\Users\<
username>
\Desktop\scan.jpeg";
if (File.Exists(path)){File.Delete(path);
}// Save image !imageFile.SaveFile(path);
5.捕捉异常 WIA函数方法会引发可通过错误代码识别的异常。错误代码列表可以在MSDN网站上的WIA文档中找到。要处理WIA的错误, 请捕获COMException对象。切记之前要导入InteropServices类型:
using System.Runtime.InteropServices;
然后将使用WIA的代码包装在try-catch语句中。你可以使用异常的ErrorCode属性来标识错误, 但请记住将其转换为其uint表示形式, 以便能够将其与MSDN中表的错误代码进行比较。
try{// Some code that uses WIA// e.g //// var device = firstScannerAvailable.Connect();
// var scannerItem = device.Items[1];
// var imageFile = (ImageFile)scannerItem.Transfer(FormatID.wiaFormatJPEG);
}catch (COMException e){ // Convert the error code to UINTuint errorCode = (uint)e.ErrorCode;
// See the error codesif (errorCode ==0x80210006){Console.WriteLine("The scanner is busy or isn't ready");
}else if(errorCode == 0x80210064){Console.WriteLine("The scanning process has been cancelled.");
}else if(errorCode == 0x8021000C){Console.WriteLine("There is an incorrect setting on the WIA device.");
}else if(errorCode == 0x80210005){Console.WriteLine("The device is offline. Make sure the device is powered on and connected to the PC.");
}else if(errorCode == 0x80210001){Console.WriteLine("An unknown error has occurred with the WIA device.");
}}
6.显示扫描进度 要显示扫描仪的进度, 可以使用CommonDialogClass的ShowTransfer方法。 CommonDialog控件是一个运行时不可见的控件, 可以在调用CreateObject时使用” WIA.CommonDialog” 作为ProgID来创建, 也可以通过将CommonDialog对象放在窗体上来创建。你可以通过将扫描结果(从ShowTransfer方法返回的对象)转换为ImageFile类型来检索图像。
文章图片
此方法将显示一个带有进度条的微型对话框, 该进度条指示并在扫描过程中进行更新。它希望将扫描仪项目作为第一个参数, 将扫描图像的格式作为第二个参数, 并将指示是否应显示” 取消扫描” 按钮的布尔值作为第三个参数。如果用户取消了扫描过程, 请注意添加try-catch语句以防止你的应用程序崩溃。在班级顶部导入以下类型:
using WIA;
using System.Runtime.InteropServices;
然后选择扫描仪并开始扫描过程
// Create a DeviceManager instancevar deviceManager = new DeviceManager();
// Create an empty variable to store the scanner instanceDeviceInfo firstScannerAvailable = null;
// Loop through the list of devices to choose the first availablefor (int i = 1;
i <
= deviceManager.DeviceInfos.Count;
i++){// Skip the device if it's not a scannerif (deviceManager.DeviceInfos[i].Type != WiaDeviceType.ScannerDeviceType){continue;
}firstScannerAvailable = deviceManager.DeviceInfos[i];
break;
}// Connect to the first available scannervar device = firstScannerAvailable.Connect();
// Select the scannervar scannerItem = device.Items[1];
CommonDialogClass dlg = new CommonDialogClass();
try{object scanResult = dlg.ShowTransfer(scannerItem, WIA.FormatID.wiaFormatPNG, true);
if (scanResult != null){ImageFile image = (ImageFile)scanResult;
// Do the rest of things as save the image }}catch (COMException e){ // Display the exception in the console.Console.WriteLine(e.ToString());
uint errorCode = (uint)e.ErrorCode;
// Catch 2 of the most common exceptionsif (errorCode ==0x80210006){Console.WriteLine("The scanner is busy or isn't ready");
}else if(errorCode == 0x80210064){Console.WriteLine("The scanning process has been cancelled.");
}}
通过所有这些基本说明, 你将能够使用C#在WinForms中创建自己的扫描应用程序。
实施实例 我们刚刚编写了一个示例应用程序, 该应用程序在列表框中列出了所有可用的扫描仪设备, 并允许你扫描文件并将其保存在自定义路径中。它实现了扫描进度对话框, 并允许你将图像保存为PNG, JPEG或TIFF的不同格式:
只需克隆存储库, 使用Visual Studio打开项目并进行测试。可以在此Github存储库中找到源代码。
【使用C#在Winforms中创建扫描应用程序】编码愉快!
推荐阅读
- 如何在Symfony 3中将Markdown转换为HTML
- 无法与主机smtp.gmail.com(173.194.205.108)建立SwiftMailer连接[#0]
- centos7如何查看已有用户
- RocketMQ消息发送流程
- 全面认识Windows环境变量
- [C++] 类与对象(中) 一篇带你解决运算符重载实例--日期类Date
- Windows环境下实现WireShark抓取HTTPS
- SpringBoot Mail邮件任务
- Windows下PATH等环境变量详解