C#使用Twain协议实现扫描仪连续扫描功能

作者:Healer007 时间:2023-02-15 18:14:38 

C#调用Twain接口实现扫描仪连续扫描。在监听的TwainCommand.TransferReady状态中,是调用扫描仪扫描图片的。我开始的时候尝试修改twain类中TransferPictures的方法,但是结果证实不可行。其实这是一个误区,我们只需要修改一下twain的启动扫描事件,可以根据是否连续扫描给扫描仪传不同的参数以达到此效果。只需一行代码,就可实现一次扫描多张,且不需要更改扫描仪的任何设置。

如果用Twain协议实现一次扫描多张图片?相信有接触过Twain协议与扫描仪通信的朋友都遇到过这样的问题。按照网上的例子,在连续送纸的扫描仪中,调用一次却只能扫描一张图片,怎么破?

关于这个问题 我研究了好久,终于在困扰了我7天之后,我搞定了,下面分享一下我的解决经验。

新建一个ScanCommon类,在调用界面,写下调用扫描的方法:

ScanCommon  scan = new RS_ScanCommon(fileName, this.Handle);
   scan.PassDataBetweenForm += new RS_ScanCommon.PassDataBetweenFormHandler(scan_PassDataBetweenForm);
   //是否连续扫描
   scan.bContinuousScan = true;
   scan.dtRow = dtRow;
   this.Enabled = false;
   scan.StartScan();

在ScanCommon类中,调用Twain的接口类(Twain类网络上可以找到,本文略),主要代码如下:

// 添加一个委托
       public delegate void PassDataBetweenFormHandler(object sender, PassDataEventArgs e);
       // 添加一个PassDataBetweenFormHandler 类型的事件
       public event PassDataBetweenFormHandler PassDataBetweenForm;
     public ScanCommon(string fileName, IntPtr Handle)
       {
           this.fileName = fileName;
           this.Handle = Handle;
           //扫描初始化(默认使用TWAIN方式进行连接)
           tw = new Twain();
           tw.Init(Handle, out rc);
           //tw.Select();
       }
      //启动扫描
      public void StartScan()
       {
           if (rc != TwRC.Success)
           {
               MessageBox.Show("设备初始化失败,请检查硬件及驱动!");
           }
           else
           {              
               string path = "XXX路径" + "\\ScannerFile\\" + frmName;
               if (Scanning(path) == false)
               {                  
                       MessageBox.Show("设备未找到或设备不支持TWAIN组件,无法自动创建扫描任务。") ;                    

//回调主窗口
                   PassDataEventArgs args = new PassDataEventArgs("exit");
                   PassDataBetweenForm(this, args);
                   GC.Collect();
               }
           }
       }

在ScanCommon类中,主要的扫描方法均可以通过调用twain类实现,Scanning是调用驱动实现扫描的方法。Application.AddMessageFilter是添加扫描仪的事件监听,在监听事件中返回扫描仪的不同状态以实现取消和扫描的一些操作。

主要代码如下:

#region 扫描的一些方法
private bool Scanning(string filePath)
{          
    if (!msgfilter)
    {
        msgfilter = true;
        Application.AddMessageFilter(this);
    }
    ScanPath = filePath;
    return tw.Acquire(ref strScanErrorMessage, bContinuousScan);
}

/// <summary>
/// 保存图片
/// </summary>
/// <param name="dibhandp"></param>
private void ImageSave(IntPtr dibhandp)
{
    bmprect = new Rectangle(0, 0, 0, 0);
    if (dibhandp != IntPtr.Zero) dibhand = dibhandp;
    bmpptr = GlobalLock(dibhand);
    pixptr = GetPixelInfo(bmpptr);
}

public void EndingScan()
{
    if (msgfilter)
    {
        tw.Finish();
        RemoveMessageFilter(this);
        msgfilter = false;
    }
}

public static void RemoveMessageFilter(IMessageFilter value)
{
    Application.RemoveMessageFilter(value);
}
#endregion

在监听的TwainCommand.TransferReady状态中,是调用扫描仪扫描图片的。我开始的时候尝试修改twain类中TransferPictures的方法,但是结果证实不可行。

其实这是一个误区,我们只需要修改一下twain的启动扫描事件,可以根据是否连续扫描给扫描仪传不同的参数以达到此效果。

只需一行代码,就可实现一次扫描多张,且不需要更改扫描仪的任何设置。

如果设备支持连续送纸,启动扫描时扫描仪会直接连扫直到纸张全部扫完

//此行代码是连续扫描
TwCapability cap = new TwCapability(TwCap.XferCount, -1);

代码如下:

/// <summary>
/// 启动扫描
/// </summary>
/// <param name="strScanErrorMessage"></param>
/// <returns></returns>      
public bool Acquire(ref string strScanErrorMessage, bool MultiScan)
{
   try
   {
       TwRC rc;
       CloseSrc();
       if (appid.Id == IntPtr.Zero)
       {
           Init(hwnd, out rc);
           if (appid.Id == IntPtr.Zero)
               strScanErrorMessage = "未找到扫描仪设备,请查看是否安装扫描仪驱动!";
           return false;
       }
       rc = DSMident(appid, IntPtr.Zero, TwDG.Control, TwDAT.Identity, TwMSG.OpenDS, srcds);
       if (rc != TwRC.Success)
       {
           strScanErrorMessage = "未找到扫描仪设备";
           return false;
       }

if (MultiScan)
       {
           //如果是连续扫描
           TwCapability cap = new TwCapability(TwCap.XferCount, -1);
           rc = DScap(appid, srcds, TwDG.Control, TwDAT.Capability, TwMSG.Set, cap);
       }
       else
       {
           //否则只扫描一张
           TwCapability cap = new TwCapability(TwCap.XferCount, 1);
           rc = DScap(appid, srcds, TwDG.Control, TwDAT.Capability, TwMSG.Set, cap);
       }

if (rc != TwRC.Success)
       {
           strScanErrorMessage = "未找到扫描仪设备";
           CloseSrc();
           return false;
       }

TwUserInterface guif = new TwUserInterface();
       guif.ShowUI = 1;
       guif.ModalUI = 1;
       guif.ParentHand = hwnd;
       rc = DSuserif(appid, srcds, TwDG.Control, TwDAT.UserInterface, TwMSG.EnableDS, guif);
       if (rc != TwRC.Success)
       {
           strScanErrorMessage = "扫描仪中没有纸";
           CloseSrc();
           GC.Collect();
           return false;
       }
   }
   catch (Exception e)
   {
       strScanErrorMessage = e.Message;
       GC.Collect();
       return false;
   }
   GC.Collect();
   return true;
}

扫描结束后,回调主窗口返回数据,主窗口添加如下事件:

private void scan_PassDataBetweenForm(object sender, PassDataEventArgs e)
 {
     if (e.EventStr == "exit")
     {
         this.Cursor = Cursors.WaitCursor;
         frm.dtRow = this.dtRow;

//处理图片的一些方法....

this.Enabled = true;
         this.Cursor = Cursors.Default;
         GC.Collect();
     }
 }

来源:https://www.cnblogs.com/healer007/p/6240730.html

标签:C#,Twain,扫描仪
0
投稿

猜你喜欢

  • Mybatis实现单个和批量定义别名typeAliases

    2023-02-11 06:27:03
  • android采用FFmpeg实现音视频合成与分离

    2022-03-05 09:18:16
  • C#实现对图片文件的压缩、裁剪操作实例

    2022-07-09 01:50:51
  • 23种设计模式(14)java迭代器模式

    2021-12-12 15:28:49
  • Java中ArrayList集合的常用方法大全

    2023-09-01 15:23:30
  • Feign调用可重试的最佳方案分享

    2021-06-09 12:19:23
  • Android获取SHA1的方法

    2022-11-18 20:55:12
  • Android实现支付宝手势密码功能

    2021-07-26 01:16:34
  • Android 中SP与DP的区别实例详解

    2021-12-26 22:43:13
  • java自定义注解验证手机格式的实现示例

    2023-06-24 10:42:44
  • Java 实现协程的方法

    2022-02-18 22:55:05
  • C# Socket通信的实现(同时监听多客户端)

    2023-07-11 09:25:10
  • Java Swing中JDialog实现用户登陆UI示例

    2021-10-12 13:58:00
  • Java C++题解leetcode886可能的二分法并查集染色法

    2023-08-29 01:12:52
  • Android使用CrashHandler来获取应用的crash信息的方法

    2023-07-25 20:27:38
  • 浅谈Java中ThreadLocal内存泄露的原因及处理方式

    2021-06-12 21:08:37
  • Android 跨进程通Messenger(简单易懂)

    2022-03-24 00:48:25
  • Java多线程 自定义线程池详情

    2022-12-02 09:22:08
  • 基于Java的MathML转图片的方法(示例代码)

    2023-11-25 14:29:39
  • Android Studio卡很久(loading)的问题解决办法

    2023-12-08 02:22:23
  • asp之家 软件编程 m.aspxhome.com