扫描程序设计说明文档
一、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;

}

扫描程序设计说明文档相关推荐

  1. SDYY大学普通话考试报名系统说明文档

    系列文章目录 健康云平台开发说明文档 SD申报系统迭代说明文档 漏刻有时物联网传感器API接口对接说明文档 Echarts数据分析系统Data Analysis Platform使用说明文档 漏刻有时 ...

  2. 程序设计文档编写_编写有效的设计系统文档的6个技巧

    程序设计文档编写 重点 (Top highlight) I wrote this article to document what I'm learning professionally while ...

  3. Caysn打印机IOS平台打印开发包、接口说明文档及示例程序_20170717

    打印机开发包,接口说明文档,打印示例程序下载地址:Caysn打印机IOS开发包.接口说明文档.打印示例程序_20170717 Framework版本要求:IOS8  Framework架构:armv7 ...

  4. 数据产品经理基础技能:数据需求说明文档怎么写?

    公众号后台回复"图书",了解更多号主新书内容作者:草帽小子来源:一个数据人的自留地 作者介绍 @草帽小子 数据产品经理一枚~ 用户画像.埋点.指标体系.BI.广告投放等系列文章作者 ...

  5. Caysn打印机IOS平台打印示例及接口说明文档 - 20161008

    打印示例下载地址: Caysn打印机IOS打印示例程序 - sample_20161008 接口说明文档下载地址: Caysn打印机IOS开发包接口说明文档 - PrinterLibs For IOS ...

  6. linux在开始ubifs前错误,UBIFS文件系统说明文档答题.docx

    UBIFS文件系统说明文档 注意:在了解UBIFS之前一定要注意到UBIFS和任何传统的文件系统是不一样的:UBIFS不是运行在block device之上的(如hard disk,MMC/SD卡,U ...

  7. 【课程作业】发电及互联系统可靠性计算程序说明文档

    本文为电力系统可靠性课程编程大作业的程序说明文档,可靠性的计算方式为通过构建停运表形成发电系统及互联系统的裕度表,并计算可靠性指标.关于电力系统可靠性的概念.计算方式等将不会在本文说明. 在此分享程序 ...

  8. LEADTOOLS 20帮助说明文档

    LEADTOOLS 20帮助说明文档 LEADTOOLS 20使用DICOM挂起协议创建多学科DICOM查看器 毫无疑问,DICOM挂起协议是忙碌的医生的重要功能.只需查看不同应用程序提供的大量显示布 ...

  9. 【java】将自己写的类生成说明文档的方法

    使用工具: jdk中的javadoc 实现步骤: 1.将java文件放到一个目录之下 2.进入doc(win+R,输入cmd) 3.通过cd指令进入存放java文件的文件夹 4.编译java文件 代码 ...

最新文章

  1. MLNLP顶会论文发表总榜:谷歌最狂,清北入前十,周明、张岳、刘挺华人前三...
  2. OSPF(Open Shortest Path First开放式最短路径优先)
  3. [原创]java WEB学习笔记02:javaWeb开发的目录结构
  4. 显示point data的时均值注意事项
  5. python api调用展示_Python百视api调用示例
  6. iOS :Object-C 语言merge两个字典对象
  7. 请教 indy 中的 tldUdpServer 如何实现对本地端口6100进行监听!
  8. Quartz入门到精通
  9. linux 文件查找
  10. 安徽省湖泊河流ArcGIS地形图shp图层文件下载
  11. 阿里巴巴分布式调度引擎tbschedule实战四tbschedule的配置使用
  12. 弹性系数和线径的计算公式_压缩弹簧弹力的计算公式
  13. 拼音搜索函数(C# and java)
  14. 【电脑讲解】笔记本怎么连接宽带,拨号和无线网络连接方法
  15. python解析xml读取指定属性_python批量修改xml某些内容和属性
  16. 基于协同过滤推荐+余弦相似度算法实现新闻推荐系统
  17. linux探针,存活探针(Liveness)、就绪探针(Readiness)、启动探针(Startup)、容器钩子
  18. 提醒大家有关越狱组it学院vip会员有猫腻,要小心。。。
  19. 3个月疫情倒闭了近90000家企业,为什么互联网公司每天都在招人?招聘一个程序员要多少成本
  20. MIT发现语言模型内的事实知识可被修改??

热门文章

  1. 一个人的发财史,很经典
  2. CEO张一鸣:当代优秀年轻人需要哪些特质?
  3. android社交软件。平台,基于Android平台的社交软件设计及实现.pdf
  4. Docker 解决Operation not permitted问题
  5. 邮件smtp服务器服务器是什么,smtp服务器和pop3服务器是什么
  6. 微信小程序 更新版本操作
  7. Mysql RR隔离级别下,当前事务的更新前后ReadView查询结果不一致
  8. 连接服务器ssh命令和scp命令
  9. HTML form表单重置按钮无效问题
  10. 粉阿吉整理(6)之------Flex 弹性盒