扫描程序设计说明文档

扫描程序设计说明文档
一、TWAIN的文件组成

TWAIN共包括4个二进制文件。如果要使用该接口,就必须要保证他们被成功地安装在本地计算机上。

 

文 件 名
 说 明
 
TWAIN_32.DLL
 32位应用程序的支持文件,32位程序使用TWAIN通讯必须使用该文件。
 
TWAIN.DLL
 16位应用程序的支持文件,16位程序使用TWAIN通讯必须使用该文件。
 
TWUNKER_32.EXE
 实现32位应用程序与32位数据源进行通讯,它运行时不可见。
 
TWUNKER_16.EXE
 实现32位应用程序与16位数据源进行通讯,它运行时不可见。

注意:在Windows NT 环境下16位数据源不能够正常工作。
 

 

在Windows 操作系统中,Microsoft已经把这些文件作为系统文件随同操作系统一起发布了。可以在Windows安装目录中查找到这些文件。通过TWAIN提供的头文件,可以实现扫描功能。

 

二、TWAIN的结构

TWAIN依靠三个组件协同完成与图像设备的通讯和数据传输工作,这三个组件就是 Application、Source Manager和Source。

 

组件
 说明
 
Application
 就是你要编写的应用程序。
 
Source Manager
 是由TWAIN提供的一个Source的管理器,它不仅可以收集本地系统已经安装了的图像设备,还可以根据需要去加载设备。同时,它最重要的功能是担任Application 与Source通讯的桥梁。(其实,它就是我们前面提到的组成文件中的dll文件。)
 
Source
 在这里可以看作是图像设备。事实上它是由设备厂家提供的一个dll文件。这个dll文件是支持twain接口的。
 

 

它们的层次结构图如下:

 

 


从上图可以看到,Application要从Source获得图像数据,必须通过Source Manager传递来实现。Application与Source Manager 间的通讯是靠调用TWAIN提供的OpenDSM( )函数实现。而Application不能直接与Source 通讯,Source Manager与Source 间的通讯是靠调用TWAIN提供的OpenDS()函数实现。

 

三、消息定义

TWAIN把它定义的操作称为Triplets操作,就是每个操作用三个定义的参数来表示。这个三个参数用不同前缀名来区分。这三个参数类型分别是Data Group、 Data Argument和 Message ID。每个Triplets操作都是唯一的,不会有歧意,它们代表一个特定的操作行为。

 

四、TWAIN的接口函数

要编写应用程序实现与支持TWAIN标准的图像设备通讯,只需要了解上面提到的OpenDSM( )接口函数。TWAIN定义了大约140个操作消息。只要把这些消息通过OpenDSM( )函数发给Source Manager,就可以实现对选定的Source进行相应的操作。Source Manager会分辨那些消息属于自己,那些消息是该转发给Source。

在使用OpenDSM( )前,必须要加载TWAIN_32.DLL文件以获得OpenDSM( )函数指针。  TWAIN所有的操作都是通过OpenDSM( )函数来实现的。

   

五、TWAIN的操作流程

Application、 Source Manager 和 Source要实现数据传输,必须遵循一个操作流程。你要进行的操作应该在这个流程规定的动作队列中按逻辑去执行。比如,在没有加载Source Manager前,Application是不能要求Source传输数据的。为了更好的去描述这个流程,TWAIN为该流程定义了7个状态(1-7)。

 

状态位 1, 2, 3

这几个状态是用于描述Source Manager的,它们是Source Manager专有的状态位,所以Source Manager 的标志位是不会大于3的.

状态位4, 5, 6, 7

这几个状态是Source专有的。如果Source打开了,Source 的标志位就不会小于4;如果Source关闭了,Source就没有了标志位。

 

应用程序可以使用了多个Source,每个与Source的连接都是一个单独的会话,对于打开的每个Source,他们的标志位都是相互独立的,不互相关联。

 

流程标志位说明

状态 1 – 准备会话

在Application和Source Manager建立会话前,Source Manager的标志位是1。

在这个时候,Source Manager还没有被加载到内存中。如果Source Manager 被加载到内存中,则状态位是2或者3。

 

状态2 –加载Source Manager

Source Manager现在已经被成功地加载到了程序中,但是没有打开Source Manager。

在这个时候, Source Manager开始准备去接受Application的Triplets操作。

 

状态3 – 打开Source Manager

Source Manager已经打开并且准备去管理Source。Source Manager现在准备向Source发送打开操作,去打开指定的Source,并等待所有针对Source的操作结束后,去关闭打开的Source。Source Manager在会话关闭前,状态位将保持为3。 当Application打开的Source没有关闭时,Source Manager 会拒绝关闭。

 

状态 4 – 打开Source     

在响应Application的一个指定的Triplets操作后,Source被加载到系统中,并且被Source manager 打开。Source在加载前将检测是否有足够的系统资源让自己运行(内存、设备是否可用等等…)。 Application不仅可以查询Source的性能参数(当前解析度、是否支持彩色或黑白图像、自动文档传送是否可用), Application还可以去设置的Source的性能参数。比如Application可以要求Source按指定的分辨率传输黑白图像。

 

注意: 可以在Source的状态位是4, 5, 6, 或 7时,去查询Source的性能参数。但是要想设置Source的性能参数必须在状态位是4的时候设置,除非Application和Source有特殊的约定,否则在标志位为其他数的时候都不可以进行性能参数设置。

 

状态 5 – Source可用         

现在可以让Source工作了,此时Source开始为数据传输做准备。在该状态下,可以执行一个Triplets操作,用以选择是否让Source显示它自己的用户界面(Source提供的软件界面)。当Source准备好给Application传输数据时,标志位就从5变为6了。

 

状态 6 –准备数据传输

该状态下,Source已经准备好了为Application传输数据。在传输工作开始前,Application应该查询将要被传输的图像的相关信息(分辨率,图像大小…)。

 

状态 7 –传输开始       

Source开始进行数据传输,它把获得的数据传输给你的应用程序。 传输工作要么成功完成,要么提前中止。在传输工作完成后, Source将会发送一个返回代码去表示传输工作的最终结果。

 

八、TWAIN的应用实现

 

1.       初始化TWAIN

void CLcTwain::InitializeTwain(HWND hMainWnd)

{

       appID.Id = 0;                                           appID.Version.MajorNum = 1;

       appID.Version.MinorNum = 703;

       appID.Version.Language = TWLG_USA;

       appID.Version.Country  = TWCY_USA;

#ifdef WIN32

       lstrcpy (appID.Version.Info,  "TWAIN_32 Twacker 1.7.0.3  01/18/1999");

       lstrcpy (appID.ProductName,   "TWACKER_32");

#else

       lstrcpy (appID.Version.Info,  "TWAIN Twacker 1.7.0.3  01/18/1999");

       lstrcpy (appID.ProductName,   "TWACKER_16");

#endif

       appID.ProtocolMajor = 1;//TWON_PROTOCOLMAJOR;

       appID.ProtocolMinor = 7;//TWON_PROTOCOLMINOR;

       appID.SupportedGroups =  DG_IMAGE | DG_CONTROL;

       lstrcpy (appID.Manufacturer,  "TWAIN Working Group");

       lstrcpy (appID.ProductFamily, "TWAIN Toolkit");

       // pass app particulars to glue code

       ASSERT(&appID);

       ASSERT(hMainWnd);

       hWnd = hMainWnd;       // get copy of app window handle

       OpenDSM();

       return;

}

 

2.       选择默认的扫描仪

BOOL CLcTwain::TWSelectDefaultDS()

{

       TW_UINT16 twRC = TWRC_FAILURE;

       TW_IDENTITY NewDSIdentity;

       memset(&NewDSIdentity, 0, sizeof(TW_IDENTITY));

       if (TWDSOpen)

       {

                twRC = TWRC_FAILURE;

       }

       else

       {

                twRC = CallDSMEntry(&appID,

                          NULL,

                          DG_CONTROL,

                          DAT_IDENTITY,

                          MSG_GETDEFAULT,

                          (TW_MEMREF)&NewDSIdentity);

                dsID = NewDSIdentity;

       }

       return (twRC);

}

3.       打开Source Manager

BOOL CLcTwain::OpenDSM()

{

  TW_UINT16     twRC = TWRC_FAILURE;

  OFSTRUCT      OpenFiles;

  #define       WINDIRPATHSIZE 160

  char          WinDir[WINDIRPATHSIZE];

  TW_STR32      DSMName;

 

  memset(&OpenFiles, 0, sizeof(OFSTRUCT));

  memset(WinDir, 0, sizeof(char[WINDIRPATHSIZE]));

  memset(DSMName, 0, sizeof(TW_STR32));

 

  if (TWDSMOpen!=TRUE)

  {

      GetWindowsDirectory (WinDir, WINDIRPATHSIZE);

      strcpy(DSMName,"TWAIN_32.DLL");

      if ((hDSMDLL =     LoadLibrary(DSMName)) != NULL &&

          (hDSMDLL >= (HANDLE)VALID_HANDLE) &&

          (lpDSM_Entry = (DSMENTRYPROC)GetProcAddress(hDSMDLL, MAKEINTRESOURCE (1))) != NULL)

      {

          twRC = CallDSMEntry(&appID,

              NULL,

              DG_CONTROL,

              DAT_PARENT,

              MSG_OPENDSM,

              (TW_MEMREF)&hWnd);

         

          switch (twRC)

          {

          case TWRC_SUCCESS:

              TWDSMOpen = TRUE;

              break;

             

          case TWRC_FAILURE:

             

          default:

              // Trouble opening the SM, inform. the user

              TWDSMOpen = FALSE;

             

              break;

          }

      }

      else

          return -1;

     

  } 

  // Let the caller know what happened

  return (TWDSMOpen);

}

 

4.       打开Source

BOOL CLcTwain::OpenDS()

{

  TW_UINT16 twRC = TWRC_FAILURE;

  if (TWDSMOpen==FALSE)

  {

      OpenDSM();

  }

  else

  {

      if (TWDSOpen==TRUE)

      {

      }

      else

      {

          twRC = CallDSMEntry(&appID,

              NULL,

              DG_CONTROL,

              DAT_IDENTITY,

              MSG_OPENDS,

              &dsID);

         

          switch (twRC)

          {

          case TWRC_SUCCESS:

              // do not change flag unless we successfully open

              TWDSOpen = TRUE;

              break;

             

          case TWRC_FAILURE:

              break;

             

          default:

             

              break;

          }

      }

  }

  return TWDSOpen;

}

5.       处理Source的事件

BOOL CLcTwain::ProcessTWMessage(LPMSG lpMsg, HWND hWnd)

{

  TW_UINT16  twRC = TWRC_NOTDSEVENT;

  TW_EVENT   twEvent;

 

  memset(&twEvent, 0, sizeof(TW_EVENT));

 

  ASSERT(lpMsg);

 

  ASSERT(hWnd);

  if ((IsDSMOpen()) && (TWIsDSOpen()))

  {

     

      twEvent.pEvent = (TW_MEMREF)lpMsg;

      if(((lpMsg->wParam != 0) && (lpMsg->lParam == 0)) ||((lpMsg->wParam == 0) && (lpMsg->lParam != 0)))

      {

      twRC = CallDSMEntry(&appID,

          &dsID,

          DG_CONTROL,

          DAT_EVENT,

          MSG_PROCESSEVENT,

          (TW_MEMREF)&twEvent);

     

      switch (twEvent.TWMessage)

      {

      case MSG_XFERREADY:

          //If AcqFlag >0 then we are in state 5

          if (AcqFlag)

          {

              TWTransferImage(hWnd);

          }

          break;

         

      case MSG_CLOSEDSREQ:

      case MSG_CLOSEDSOK:

          if (TWDisableDS())

          {

      //      if (CloseDS())

              {

          //      CloseDSM(NULL);

              }

          }

          break;

      case MSG_NULL:

      default:

          break;

      }  

      }

  }

  // tell the caller what happened

  return (twRC==TWRC_DSEVENT);           // returns TRUE or FALSE

}

6.       使用本地模式传输数据

void CLcTwain::DoNativeTransfer(HWND hWnd)

{

  TW_PENDINGXFERS     twPendingXfer;

  TW_UINT16           twRC = TWRC_FAILURE;

  TW_UINT16           twRC2 = TWRC_FAILURE;

  TW_UINT32           hBitMap = NULL;

  HANDLE              hbm_acq = NULL;         char buffer[2048];

  CString Weishu1, strTemp, test;

  static CString str;

  LPBITMAPINFOHEADER lpdib = NULL;

  BOOL g_bSpecialMenu = FALSE;

  memset(&twPendingXfer, 0, sizeof(TW_PENDINGXFERS));

  memset(buffer, 0, sizeof(char[2048]));

 

  ASSERT(hWnd);

 

  twPendingXfer.Count = 0;

  do

  {

     

      twRC = CallDSMEntry(&appID,

          &dsID,

          DG_IMAGE,

          DAT_IMAGENATIVEXFER,

          MSG_GET,

          (TW_MEMREF)&hBitMap);

        CFileFind finder;

      test.Format("%s//%s//*.%s",Folder,pici,FileFormat);

      BOOL bWorking = finder.FindFile(test);

      int j = 0;

      int k = 1;

      while (bWorking)

      {

          bWorking = finder.FindNextFile();

          if(finder.GetFileName() !='.' && finder.GetFileName() != ".." && finder.GetFileName()!="Thumbs.db")

          {

              ++k;

              strTemp.Format("%d",k);

              j = strlen(strTemp);

              if(j == 0 || j==1)

                  j =0;

              strTemp.Format("%d",j);

          }

          test = finder.GetFileName();

          str.Format("%s//%s//%s",Folder,pici,test);

      }

      if(i == 0)

      {

              int n = atoi(Weishu);

              int m = n -j;

              switch(m)

              {

                  case 0: Weishu1 = "";break;

                  case 1: Weishu1 = "";break;

                  case 2: Weishu1 = "0";break;

                  case 3: Weishu1 = "00";break;

                  case 4: Weishu1 = "000";break;

                  case 5: Weishu1 = "0000";break;

                  case 6: Weishu1 = "00000";break;

                  case 7: Weishu1 = "000000";break;

                  case 8: Weishu1 = "0000000";break;

                  case 9: Weishu1 = "00000000";break;

              }

                         

          str.Format("%s//%s//%s%s%d.%s",Folder,pici,FileName,Weishu1,k,FileFormat);

          int type = FindType(FileFormat);

          CxImage* ima = new CxImage();

          ima->CreateFromHANDLE((HBITMAP)hBitMap);   

          ima->Save(str, type);

          if(Single == "0")

          {

              i++;

          }

      }

      else

      {

            //单页tiff

          {

              FILE* fdest=fopen(str, "r+b");

              CxImageTIF* ima2app = new CxImageTIF;

              ima2app->CreateFromHANDLE((HBITMAP)hBitMap);

 

              ima2app->SetFrame(i);

              ima2app->Encode(fdest, true);

              delete ima2app;

              fclose(fdest);

          }

      }

//

      switch (twRC)

      {

      case TWRC_XFERDONE:

          hbm_acq = (HBITMAP)hBitMap;

          g_bSpecialMenu = FALSE;

          twRC2 = CallDSMEntry(&appID,

              &dsID,

              DG_CONTROL,

              DAT_PENDINGXFERS,

              MSG_ENDXFER,

              (TW_MEMREF)&twPendingXfer);

          if (twRC2 != TWRC_SUCCESS)

          {

          }

         

          wsprintf(buffer,"Pending Xfers = %d/r/n",twPendingXfer.Count);

             

          if (twPendingXfer.Count == 0)

          {  

              if (hbm_acq&&(lpdib = (LPBITMAPINFOHEADER)GlobalLock(hbm_acq))!=NULL)

              {

                  if(!g_bSpecialMenu)

                  {

                      CloseConnection(NULL);

                  }

                  GlobalUnlock(hbm_acq);

              }

          }

         

          if (hbm_acq >= (HANDLE)VALID_HANDLE)

          {

              SendMessage(hWnd, PM_XFERDONE, (WPARAM)hbm_acq, 0);                 }

          else

          {

              SendMessage(hWnd, PM_XFERDONE, NULL, 0);

          }

          break;

      case TWRC_CANCEL:

          twRC2 = CallDSMEntry(&appID,

              &dsID,

              DG_CONTROL,

              DAT_PENDINGXFERS,

              MSG_ENDXFER,

              (TW_MEMREF)&twPendingXfer);

          if (twRC2 != TWRC_SUCCESS)

          {

          }

          if (twPendingXfer.Count == 0)

          {

              if(!g_bSpecialMenu)

              {

                  CloseConnection(NULL);

              }

          }

          SendMessage(hWnd, PM_XFERDONE, NULL, 0);

          break;

         

      case TWRC_FAILURE:

          twRC2 = CallDSMEntry(&appID,

              &dsID,

              DG_CONTROL,

              DAT_PENDINGXFERS,

              MSG_ENDXFER,

              (TW_MEMREF)&twPendingXfer);

         

          if (twRC2 != TWRC_SUCCESS)

          {

          }

         

          if (twPendingXfer.Count == 0)

          {

              if(!g_bSpecialMenu)

              {

                  CloseConnection(NULL);

              }

          }

         

          SendMessage(hWnd, PM_XFERDONE, NULL, 0);

          break;

      default:

          twRC2 = CallDSMEntry(&appID,

              &dsID,

              DG_CONTROL,

              DAT_PENDINGXFERS,

              MSG_ENDXFER,

              (TW_MEMREF)&twPendingXfer);

         

          if (twRC2 != TWRC_SUCCESS)

          {

          }

         

          if (twPendingXfer.Count == 0)

          {

              if(!g_bSpecialMenu)

              {

                  CloseConnection(NULL);

              }

          }

         

          SendMessage(hWnd, PM_XFERDONE, NULL, 0);

          break;

      }  

     

  }while(twPendingXfer.Count != 0);

  AcqFlag = 0;

}

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值