TWAIN 的 C++ 包装器






4.89/5 (37投票s)
2000 年 2 月 8 日

651188

15688
TWAIN 的 C++ 包装器。允许您实现扫描界面。
我的一个应用程序需要一些扫描仪支持。我认为进入 TWAIN 并尝试一下是个好主意。嗯,这是结果。
注意:您的系统上需要安装 TWAIN_32.DLL 才能使此应用程序正常工作。
首先,这不是 TWAIN 规范的完整实现。我遵循了 1.8 版,并使用了基本功能来从扫描仪获取图像,实际上,也可以连续获取多个图像。顺便说一句 - 它也可以与数码相机一起使用 - 任何导出 TWAIN 接口的设备都支持。
好吧,让我们深入了解一下。但在我们这样做之前,我必须提到我无法在这里告诉你关于 TWAIN 的所有信息。您可以在 http://www.twain.org 下载规范。如果您没有扫描仪并想尝试 TWAIN,他们还有一个示例 Twain 源。
为了我们这里的目的,重要的是数据源管理器 (DSM) 和数据源 (DS) 本身。DS 是实现 TWAIN 的实际扫描仪、数码相机或任何其他源。DSM 是为我们提供 DSM 接口的模块。是的,这是 TWAIN 的一个非常简化的视图(我想象 TWAIN 设计者会如何看待我的描述,我不寒而栗)。
现在来看类本身。首先,必须包含 Twain.h 头文件。我不太有创意地将我的类命名为 CTwain
。现在这个类需要加载 TWAIN_32.DLL 模块。我处理它的方式是维护一个静态模块句柄并增减引用计数。当接口最后一次释放时,模块将被卸载。
该类在很大程度上独立于其他所有内容。但它确实需要一个窗口句柄,DSM 可以通过该句柄发送消息。这些消息并非用于应用程序本身,而是用于 TWAIN 实现者,在这种情况下是 CTwain
。此窗口句柄可以传递给构造函数,或者,如果窗口尚未准备好,则更有可能在调用 InitTwain
时传递。
CTwain
类是一个抽象类,因为它有一个纯虚方法。因此,要使用此类,您必须从 CTwain
派生。
我现在将解释重要的方法 - 那些能让您开始扫描的方法。
CTwain(HWND hWnd= NULL)
构造函数 hwnd 是可选的。如果给定了非空值,则使用此句柄初始化 Twain 接口。
~CTwain()
析构函数
InitTwain(HWND hWnd)
初始化 TWAIN
如果传递给构造函数的句柄不为空,则构造函数会调用此函数。否则,以后可以调用它。加载 Twain Dll 并初始化它。
ReleaseTwain()
释放 Twain 接口
注意:如果 TWAIN 已初始化,则必须在传递给它的窗口句柄被销毁之前调用此函数。否则会导致资源和内存泄漏。
GetIdentity()
标识应用程序
InitTwain 调用此函数来初始化 TW_IDENTITY 结构。请参考 twain.h 获取结构成员,并参考 CTwain::GetIdentity 获取如何填充这些成员的示例。目前,只要默认行为适合您,您就不需要实现它。
IsValidDriver()
如果驱动程序已成功加载,则返回 true
SourceSelected()
如果已成功选择源,则返回 true
SourceEnabled()
如果源已启用,则返回 true
在 TWAIN 的术语中,源被启用意味着扫描正在进行中。
SelectDefaultSource()
为当前机器选择默认源
SelectSource()
显示“选择源”对话框并允许用户选择一个
Acquire(int numImages=1)
开始图像采集 这并不一定意味着扫描过程已开始。实际上,它仅仅意味着源已被启用,并且通常已经打开了扫描参数对话框。扫描通常从那里开始。numImages 是应用程序可以处理的图像数量,或者 TWCPP_ANYCOUNT 表示任意数量。
ProcessMessage(MSG msg)
处理来自 Twain 的消息 这应该从最初传递给类的窗口的消息循环中调用。
注意:所有消息都可以传递给此例程。它会忽略所有非 Twain 消息,并且除非源已启用,否则不会对其进行操作 - 因此它也不是性能瓶颈。
ShouldTransfer(TW_IMAGEINFO& info)
每次要扫描图像时都会调用此方法。它应该返回以下值之一:
- TWCPP_CANCELTHIS
- 取消此图像传输
- TWCPP_CANCELALL
- 中止所有传输
- TWCPP_DOTRANSFER
- 继续传输
默认实现返回 TWCPP_DOTRANSFER。
CopyImage(HANDLE hBitmap,TW_IMAGEINFO& info)
这是一个纯虚方法,每次从 TWAIN 传输图像时都会调用它。图像如何使用取决于应用程序。
好了 - 这些是您通常会使用到的例程。您可能还可以做更多的事情,但 TWAIN 规范在这里可能比我能为您提供的帮助更多。
现在来看看演示应用程序。
我所做的是使用多重继承与 CMainFrame
相关联。我认为这是处理事情的最简单方法。所以 CMainFrame
从 CTwain
派生。InitTwain
从 CMainFrame
的 OnCreate
成员调用。尽管析构函数在窗口关闭时会自动调用,但那时窗口句柄将无效。所以我从 CMainFrame
的 OnClose
成员函数调用 ReleaseTwain
。
文件菜单中的两个新增项是
- 选择源
- 采集
选择源会显示默认对话框,其中列出了可用的 TWAIN 源。采集开始实际的采集过程。
CTwain::ProcessMessage
从 CMainFrame
的 PreTranslateMessage
成员调用。
此外,CMainFrame
实现 CopyImage
。这反过来又调用 CMainFrame::SetImage
,它创建一个新的文档以及一个框架,并将扫描的位图分配给该文档。因此,随着新图像的扫描,会创建新文档。
我想关于解释就到这里了。我现在将非常简要地回顾一下开始扫描所需的步骤。
首先,创建一个派生自 CTwain
的类。实现 CopyImage
来处理位图。位图作为设备无关位图的句柄发送。在演示应用程序中,这由一个类 - CDIB 来处理。
现在,在窗口类的 pretranslate 成员中,插入这一行
ProcessMessage(*pMsg);
像演示应用程序中的 CMainFrame
一样,添加“选择源”和“采集”这两个菜单项。
好了 - 您就完成了。就这样 - 您真正需要做的工作就是 CopyImage
。