65.9K
CodeProject 正在变化。 阅读更多。
Home

TWAIN 的 C++ 包装器

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.89/5 (37投票s)

2000 年 2 月 8 日

viewsIcon

651188

downloadIcon

15688

TWAIN 的 C++ 包装器。允许您实现扫描界面。

  • 下载演示可执行文件 - 11 Kb
  • 下载源代码文件 - 56 Kb
  • Sample Image - twaintest.jpg

    我的一个应用程序需要一些扫描仪支持。我认为进入 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 相关联。我认为这是处理事情的最简单方法。所以 CMainFrameCTwain 派生。InitTwainCMainFrameOnCreate 成员调用。尽管析构函数在窗口关闭时会自动调用,但那时窗口句柄将无效。所以我从 CMainFrameOnClose 成员函数调用 ReleaseTwain

    文件菜单中的两个新增项是

    • 选择源
    • 采集

    选择源会显示默认对话框,其中列出了可用的 TWAIN 源。采集开始实际的采集过程。

    CTwain::ProcessMessageCMainFramePreTranslateMessage 成员调用。

    此外,CMainFrame 实现 CopyImage。这反过来又调用 CMainFrame::SetImage,它创建一个新的文档以及一个框架,并将扫描的位图分配给该文档。因此,随着新图像的扫描,会创建新文档。

    我想关于解释就到这里了。我现在将非常简要地回顾一下开始扫描所需的步骤。

    首先,创建一个派生自 CTwain 的类。实现 CopyImage 来处理位图。位图作为设备无关位图的句柄发送。在演示应用程序中,这由一个类 - CDIB 来处理。

    现在,在窗口类的 pretranslate 成员中,插入这一行

    ProcessMessage(*pMsg);

    像演示应用程序中的 CMainFrame 一样,添加“选择源”和“采集”这两个菜单项。

    好了 - 您就完成了。就这样 - 您真正需要做的工作就是 CopyImage

    © . All rights reserved.