twain资料

更新时间:2023-10-10 21:20:01 阅读量: 综合文库 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

TWAIN学习笔记(陆) http://swt.iteye.com/blog/251319

http://www.pudn.com/downloads/sourcecode/others/detail1691.html 应用控制TWAIN流程:

之前看到过那个图吧,7步那个,没看到算你倒霉。

首先要正确的打开流程,不一定要从第一步走到第七步,可能走到三之后,四到七不停重复,又或者六七重复。挺灵活的。 下面那章包括那么多项的简单样例。

? ? Load the Source Manager and Get the DSM_Entry (State 1 to 2) ? ? Open the Source Manager (State 2 to 3) ? ? Select the Source (during State 3) ? ? Open the Source (State 3 to 4)

? ? Negotiate Capabilities with the Source (during State 4)

? ? Request the Acquisition of Data from the Source (State 4 to 5) ? ? Recognize that the Data Transfer is Ready (State 5 to 6) ? ? Start and Perform the Transfer (State 6 to 7) ? ? Conclude the Transfer (State 7 to 6 to 5)

? ? Disconnect the TWAIN Session (State 5 to 1 in sequence) 1到2:

用LoadLibrary()装载TWAIN_32.DLL 用GetProcAddress()调用DSM_Entry

C代码

1. DSMENTRYPROC pDSM_Entry; 2. HANDLE hDSMLib; 3. char szSMDir; 4. OFSTRUCT of;

5. // check for the existence of the TWAIN_32.DLL file in the 6. // Windows directory

7. // 检查Win目录下面有没有TWAIN_32.DLL

8. GetWindowsDirectory (szSMDir, sizeof(szSMDir));

9. /*** Could have been networked drive with trailing ‘\\’ ***/ 10. /***网络路径***/

11. if (szSMDir [(lstrlen (szSMDir) - 1)] != ‘\\\\’){ 12. lstrcat( szSMDir, \13. }

14. if ((OpenFile(szSMDir, &of, OF_EXIST) != -1){ 15. // load the DLL

16. if (hDSMDLL = LoadLibrary(“TWAIN_32.DLL”)) != NULL){ 17. // check if library was loaded

18. if (hDSMDLL >= (HANDLE)VALID_HANDLE){

19. if (lpDSM_Entry = (DSMENTRYPROC)GetProcAddress(hDSMDLL,MAKEI

NTRESOURCE (1))) != NULL){

20. if (lpDSM_Entry ){

21. FreeLibrary(hDSMDLL);

22. } 23. } 24. } 25. } 26. }

强烈建议使用动态装载TWAIN_32.DLL,写死的话,如果Win没有装TWAIN_32的话,到时候都不知道是啥了。得到DSM_Entry之后,检查pDSM_Entry(),如果是NULL的话,说明SM没在用户机器上面安装。要是还去用*pDSM_Entry()的话,会出一个UAE(Unrecoverable Application Error). 2到3

SM装载完之后,应用现在要打开SM了,注意,要开始SM了。 操作码:DG_CONTROL / DAT_PARENT / MSG_OPENDSM。

? pOrigin:应用必须分配一个TW_IDENTITY结构,并且给除Id外的坑种萝卜,当结

构准备好之后,pOrigin指向该结构。

在MSG_OPENDSM操作中,SM用唯一Id赋值给TW_IDENTITY。这个是应用到SM的唯一标识。 之后应用保存,之后,应用调用DSM_Entry()的时候,每次都用pOrigin指向的这个。 这个TW_IDENTITY在TWAIN.H里面定义好了。贴一贴:

C代码

1. /* DAT_IDENTITY Identifies the program/library/code */ 2. /* resource. */ 3. typedef struct {

4. TW_UINT32 Id; /* Unique number for identification*/ 5. TW_VERSION Version;

6. TW_UINT16 ProtocolMajor; 7. TW_UINT16 ProtocolMinor;

8. TW_UINT32 SupportedGroups;/*Bit field OR combination */

9. /*of DG_constants fo

und in */

10. /*the TWAIN.H file *

/

11. TW_STR32 Manufacturer; 12. TW_STR32 ProductFamily; 13. TW_STR32 ProductName;

14. } TW_IDENTITY, FAR *pTW_IDENTITY;

? pDest:色即是空(Set to NULL indicating the operation is intended for the

Source Manager.) ? pData:指向hWnd(the window handle),作为源的\。变量类型是TW_INT32

的,在16位系统下,the handle is stored in the low word of the 32 bit integer and the upper word is set to zero. If running under the WIN32 environment, this is a 32 bit window handle。SM为应用保存拷贝一份。

初始化TW_IDENTITY:

C代码

1. TW_IDENTITY AppID; // App’s identity structure

2. AppID.Id = 0; // Initialize to 0 (Source Manager 3. // will assign real value)

4. AppID.Version.MajorNum = 3; //Your app's version number 5. AppID.Version.MinorNum = 5;

6. AppID.Version.Language = TWLG_ENGLISH_USA; 7. AppID.Version.Country = TWCY_USA;

8. lstrcpy (AppID.Version.Info, \9. AppID.ProtocolMajor = TWON_PROTOCOLMAJOR; 10. AppID.ProtocolMinor = TWON_PROTOCOLMINOR;

11. AppID.SupportedGroups = DG_IMAGE | DG_CONTROL;

12. lstrcpy (AppID.Manufacturer, \13. lstrcpy (AppID.ProductFamily, \14. lstrcpy (AppID.ProductName, \ Win下,用DSM_Entry()打开SM:

C代码

1. TW_UINT16 rc;

2. rc = (*pDSM_Entry) (&AppID, 3. NULL,

4. DG_CONTROL, 5. DAT_PARENT, 6. MSG_OPENDSM,

7. (TW_MEMREF) &hWnd);

当AppID是应用设置的TW_IDENTITY结构的id,hWnd是应用的主窗口句柄(main window handle)。

第3步:选择源

开始SM了,SM帮助你找到你的起源。

操作码:DG_CONTROL / DAT_IDENTITY / MSG_USERSELECT

? pOrigin:在应用初始化TW_IDENTITY结构的初始化SupportedGroups的时候就指定

? pDest:四大皆空(Set to NULL.)

? pData: 先过DSM_Entry,然后必须分配这个结构,当它被分配之后,应用必须做

下面的

o id设0

o 产品名(ProductName)设null String(\),要是想臭美一下,将源

的名替代掉null,系统默认的可以用DG_CONTROL / DAT_IDENTITY / MSG_GETDEFAULT,MSG_GETFIRST and MSG_GETNEXT获取

最土的办法通过SM选S是弹出S选择框。然后点选源,走下面几步:

? 应用发送DG_CONTROL / DAT_IDENTITY / MSG_USERSELECT,弹出对话框,列出所有

的已经安装在系统上的能给你数据的源。

用户选择一个源或者按下退出(Cancel)。如果没有设备,你就只能选退出,因为OK是灰的啊,你按不到~

? 应用检查DSM_Entry返回码,英明的判断用户的动作:

o TWRC_SUCCESS:被pData指向的,在TW_IDENTITY里面的源,终于上位 o TWRC_CANCEL:没选,别开源。

o TWRC_FAILURE:用DG_CONTROL/DAT_STATUS/MSG_GET获取失败原因,经常是

因为内存问题,白菜,去加根啦。

当然你也可以不让人选。

第3到第4步:开源啦~不收费的哦 SM帮你开源

操作码: DG_CONTROL / DAT_IDENTITY / MSG_OPENDS

? pOrigin:应用的TW_IDENTITY ? pDest:NULL

? pData:指向TW_IDENTITY

在MSG_OPENDS操作过程中,SM确定S,并且在TW_IDENTITY.Id设定。也有可能不选择源就直接点Acquire了,这个时候,默认的源就是最后安装的那个或者最后一次使用的那个。

第4步:确认源的能力

如果是单张图的话,当前只用确定一个能力CAP_XFERCOUNT,其他都是可选。 操作码:

DG_CONTROL/DAT_CAPABILITY/MSG_GET DG_CONTROL/DAT_CAPABILITY/MSG_SET

? pOrigin:TW_IDENTITY

? pDest:指向源,SM接收到DSM_Entry,判断是传给源还是自己消化,如果是源就通

过DS_Entry往下调 ? pData:TW_CAPABILITY TW_CAPABILITY的结构如下:

?

C代码

1. typedef struct {

2. TW_UINT16 Cap; /* ID of capability to get or set */ 3. TW_UINT16 ConType; /* TWON_ONEVALUE, TWON_RANGE, */

4. /* TWON_ENUMERATION or TWON_ARRA

Y */

5. TW_HANDLE hContainer; /* Handle to container of type */ 6. /* ConType */ 7. } TW_CAPABILITY, FAR *pTW_CAPABILITY;

应用程序分配container,在MSG_SET操作的时候,用hContainer指向,源在MSG_GET的时候返回这个指向。不管怎么样,最后,应用一定要释放掉这东西。

一个操作一个目的 MSG_GET:谁都不是完打印机,都有自己不会的,用这个来确定你会TWAIN定义里面的几种,在TWAIN.H里面有所有的定义。如果能取到,返回当前的,默认的,可用的(Current, Default,

Available)值,这些都能在MSG_SET里面修改原来默认支持的功能。要是出错了,返回码是TWRC_FAILURE,状态码会是下面几个:

? TWCC_CAPUNSUPPORTED:没能力啊

? TWCC_CAPBADOPERATION:有心无力啊(Operation not supported by capability) ? TWCC_CAPSEQERROR:该功能依赖另一个功能

应用程序应该兼容TWCC_BADCAP,早期1.7版本可能会返回。

MSG_SET

由应用来更改当前或者可用值。要做异常判断啊。TWCC_BADVALUE可能是:

? 应用设定能力值超过了源能力 ? 源不允许设定该能力

? 源不允许使用应用设定的能力类型

查询和设置只在第4步做这个操作。记得一定要做异常判断哦。

明确设置应用能传几张图:

代码是CAP_XFERCOUNT,所有的源都必须支持这个能力。必须明确告诉应用在TWAIN中能拿到几张。值范围如下:

? 1:1张

? >1:指定的多张

? -1:任意张,是默认值

? 0:无意义值,在应用中也不要设这个值,源接到这个之后就返回TWRC_FAILURE和

TWCC_BADVALUE

下面是一个例子,说明怎么设定限制:

C代码

1. TW_CAPABILITY twCapability; 2. TW_INT16 count; 3. TW_STATUS twStatus; 4. TW_UINT16 rc; 5. #ifdef _MSWIN_

6. pTW_ONEVALUE pval; 7. #endif

8. #ifdef _MAC_ 9. TW_HANDLE h;

10. pTW_INT16 pInt16; 11. #endif

12. //-----Setup for MSG_SET for CAP_XFERCOUNT 13. twCapability.Cap = CAP_XFERCOUNT; 14. twCapability.ConType = TWON_ONEVALUE; 15. #ifdef _MSWIN_

16. twCapability.hContainer = GlobalAlloc(GHND,

17. sizeof(T

W_ONEVALUE));

18. pval = (pTW_ONEVALUE) GlobalLock(twCapability.hContainer); 19. pval->ItemType = TWTY_INT16;

20. pval->Item = 1; //This app will only accept 1 image 21. GlobalUnlock(twCapability.hContainer); 22. #endif

23. #ifdef _MAC_

24. twCapability.hContainer = (TW_HANDLE)h

25. = NewHandle(sizeof(TW_ONEVALU

E));

26. ((TW_ONEVALUE*)(*h))->ItemType = TWTY_INT16; 27. count = 1; //This app will only accept 1 image 28. pInt16 = ((TW_ONEVALUE*)(*h))->Item; 29. *pInt16 = count; 30. #endif

31. //-----Set the CAP_XFERCOUNT 32. rc = (*pDSM_Entry) (&AppID,

33. &SourceID, 34. DG_CONTROL, 35. DAT_CAPABILITY, 36. MSG_SET,

37. (TW_MEMREF)&twCapability); 38. #ifdef _MSWIN_

39. GlobalFree((HANDLE)twContainer.hContainer); 40. #endif

41. #ifdef _MAC_

42. DisposHandle((HANDLE)twContainer.hContainer); 43. #endif

44. //-----Check Return Codes 45. //SUCCESS

46. if (rc == TWRC_SUCCESS) 47. //the value was set 48. //APPROXIMATION MADE

49. else if (rc == TWRC_CHECKSTATUS){

50. //The value could not be matched exactly 51. //MSG_GET to get the new current value 52. twCapability.Cap = CAP_XFERCOUNT; 53. //Source will specify

54. twCapability.ConType = TWON_DONTCARE16; 55. //Source allocates and fills container 56. twCapability.hContainer = NULL; 57. rc = (*pDSM_Entry) (&AppID,

58. &SourceID, 59. DG_CONTROL, 60. DAT_CAPABILITY, 61. MSG_GET,

62. (TW_MEMREF)&twCapability);

63. //remember current value 64. #ifdef _MSWIN_

65. pval = (pTW_ONEVALUE) GlobalLock(twCapability.hContainer); 66. count = pval->Item;

67. //free hContainer allocated by Source

68. GlobalFree((HANDLE)twCapability.hContainer); 69. #endif

70. #ifdef _MAC_

71. pInt16 = ((TW_ONEVALUE*)(*h))->Item; 72. count = *pInt16;

73. //free hContainer allocated by Source

74. DisposeHandle((HANDLE)twCapability.hContainer); 75. #endif 76. }

77. //MSG_SET FAILED

78. else if (rc == TWRC_FAILURE){ 79. //check Condition Code

80. rc = (*pDSM_Entry) (&AppID,

81. &SourceID, 82. DG_CONTROL, 83. DAT_STATUS, 84. MSG_GET,

85. (TW_MEMREF)&twStatus); 86. switch (twStatus.ConditionCode){ 87. TWCC_BADCAP:

88. TWCC_CAPUNSUPPORTED: 89. TWCC_CAPBADOPERATION: 90. TWCC_CAPSEQERROR:

91. //Source does not support setting this cap 92. //All Sources must support CAP_XFERCOUNT 93. break; 94. TWCC_BADDEST:

95. //The Source specified by pSourceID is not open 96. break; 97. TWCC_BADVALUE:

98. //The value set was out of range for this Source 99. //Use MSG_GET to determine what setting was made 100. //See the TWRC_CHECKSTATUS case handled earlier 101. break; 102. TWCC_SEQERROR:

103. //Operation invoked in invalid state 104. break; 105. } 106. }

关于另外的能力

? Image Type:虽然没说,但是应用应该知道源的ICAP_PIXELTYPE和ICAP_BITDEPTH。 ? Transfer Mode:默认的传输方式是Native。也就是说源会接受一次性把扫到的传

回来给应用。如果可用内存不够大的话,就失败了。

第4到第5步:从源获取数据

源设备被打开了,也知道他能干什么了,应用激活源,然后用他的接口,请求,然后获取数据。

操作码:DG_CONTROL / DAT_USERINTERFACE / MSG_ENABLEDS

? pOrigin:指向应用的TW_IDENTITY结构 ? pDest:指向源的TW_IDENTITY结构

? pData:指向类型是TW_USERINTERFACE的一个结构 TW_USERINTERFACE定义如下:

C代码

1. typedef struct { 2. TW_BOOL ShowUI; 3. TW_BOOL ModalUI; 4. TW_HANDLE hParent;

5. } TW_USERINTERFACE, FAR *pTW_USERINTERFACE;

如果要源显示用户接口就将ShowUI设为TRUE,要么设成FALSE

如果应用要源以modal形式运行,ModalUI设成TRUE,要么就FALSE以Modeless。

? 也就是说,FALSE的时候,是阻塞的,等源的GUI跑完了,才能继续使用应用。 Win下,应用把句柄给Window,作为Source‘s parent。 再解释一下流程就是说:用户选择应用的Acquire菜单,应用激活源,应用通常请求源显示,以帮助用户获得数据。源被告之,获取操作码之后就显示了,以模态非模态显示就看你的ModalUI设置了。源必须检查ShowUI,如果不支持就返回错误码,也就是说忽略ShowUI=FALSE,然后继续。

第5步到第6步:

源来控制从第5步到第6步。

没操作码从应用传过来了。源自娱自乐。

记住,源激活之后,应用就一直转发他的时间循环给源, 操作码:DG_CONTROL /DAT_EVENT / MSG_PROCESSEVENT TW_EVENT结构如下:

C代码

1. typedef struct {

2. TW_MEMREF pEvent; /*Windows pMSG or MAC pEvent */

3. TW_UINT16 TWMessage;/*TW message from the Source to the application*

/

4. } TW_EVENT, FAR *pTW_EVENT;

源当他准备好传输数据的时候,设置TWMessage。应用对每个DG_CONTROL /DAT_EVENT / MSG_PROCESSEVENT都要检查TWMessage,如果MSG_XFERREADY,就到了第6步,源将会等待应用请求真的传输数据了。

第6步到第7步:

源说他I DO了,等着应用上了。应用就大厅图的细节,初始化传输,之后就到第7步。但是如果初始化失败,还留在第六步就。初始化操作码:DG_IMAGE / DAT_IMAGENATIVEXFER / MSG_GET

两个操作可以使用的:

操作码:DG_IMAGE / DAT_IMAGEINFO / MSG_GET

? pOrigin:应用的TW_IDENTITY结构 ? pDest:源的TW_IDENTITY结构

? pData:指向TW_IMAGEINFO型的一个结构 TW_IMAGEINFO定义如下:

C代码

1. typedef struct {

2. TW_FIX32 XResolution; 3. TW_FIX32 YResolution; 4. TW_INT32 ImageWidth; 5. TW_INT32 ImageLength; 6. TW_INT16 SamplesPerPixel; 7. TW_INT16 BitsPerSample[8]; 8. TW_INT16 BitsPerPixel; 9. TW_BOOL Planar; 10. TW_INT16 PixelType; 11. TW_UINT32 Compression;

12. } TW_IMAGEINFO, FAR *pTW_IMAGEINFO;

源填充这个结构,应用不管以什么方法传输(本地,文件,缓存)都从这拿到数据。

操作码:DG_IMAGE / DAT_IMAGENATIVEXFER / MSG_GET

? pOrigin:指向应用的TW_IDENTITY结构 ? pDest:指向源的TW_IDENTITY结构 ? pData:指向TW_UINT32变量

o Windows: This is a pointer to a handle variable. For 16 bit Microsoft

Windows,

the handle is stored in the low word of the 32-bit integer and the upper word is set to

zero. If running under the WIN32 environment, this is a 32 bit window handle. The

Source will set pHandle

应用查询即将接受的图可以用DG_IMAGE / DAT_IMAGEINFO / MSG_GET操作,另外一些,比如DG_IMAGE / DAT_IMAGELAYOUT / MSG_GET提供了附加功能,这些信息可以决定应用是否真的接受数据。

在本地方式传送文件的时候,应用使用操作码DG_IMAGE /DAT_IMAGENATIVEXFER / MSG_GET,本地方式是默认的传输方式,在这方式中,每张图片只要操作一次,源在传输结束的时候,返回TWRC_XFERDONE。这个模式开始了就不能中断。除非提供了特殊源的用户接口。

下面给个例子看看怎么传输,在下半段(7->6->5还有):

C代码

1. // After receiving MSG_XFERREADY 2. TW_UINT16 TransferNativeImage(){ 3. TW_IMAGEINFO twImageInfo; 4. TW_UINT16 rc;

5. TW_UINT32 hBitmap;

6. TW_BOOL PendingXfers = TRUE; 7. while (PendingXfers){

8. rc = (*pDSM_Entry)(&AppId,

9. &SourceId, 10. DG_IMAGE,

11. DAT_IMAGEINFO, 12. MSG_GET,

13. (TW_MEMREF)&twImageInfo); 14. if (rc == TWRC_SUCCESS)

15. Examine the image information 16. // Transfer the image natively 17. hBitmap = NULL;

18. rc = (*pDSM_Entry)(&AppId,

19. SourceId, 20. DG_IMAGE,

21. DAT_IMAGENATIVEXFER, 22. MSG_GET,

23. (TW_MEMREF)&HbITMAP); 24. // Check the return code 25. switch(rc){

26. case TWRC_XFERDONE:

27. //Notes: hBitmap points to a valid image Native image 28. //(DIB or PICT)

29. //The application is now responsible for 30. //deallocating the memory.

31. //The source is currently in state 7. 32. //The application must now acknowledge 33. //the end of the transfer,

34. //determine if other transfers are pending 35. //and shut down the data

36. // source.

37. PendingXfers = DoEndXfer(); //Function found in code 38. //example in

next section

39. break;

40. case TWRC_CANCEL:

41. //The user canceled the transfer.

42. //hBitmap is an invalid handle but memory 43. //was allocated.

44. //Application is responsible for 45. //deallocating the memory.

46. //The source is still in state 7.

47. //The application must check for pending 48. //transfers and shut down 49. // the data source.

50. PendingXfers = DoEndXfer(); //Function found in code 51. //example in

next section

52. break;

53. case TWRC_FAILURE:

54. //The transfer failed for some reason.

55. //hBitmap is invalid and no memory was allocated. 56. //Condition code will contain more information 57. //as to the cause of the failure.

58. // The state transition failed, the source is in state 6

.

59. // The image data is still pending.

60. // The application should abort the transfer.

61. DoAbortXfer(MSG_RESET); //Function in next section

62. PendingXfers = FALSE; 63. break; 64. } 65. } 66. }

67. //Check the return code 68. switch (rc){

69. case TWRC_XFERDONE:

70. //hBitMap points to a valid Native Image (DIB or PICT)

71. //The application is responsible for deallocating the memory 72. //The source is in State 7

73. //Acknowledge the end of the transfer

74. goto LABEL_DO_ENDXFER //found in next section 75. break;

76. case TWRC_CANCEL:

77. //The user canceled the transfer 78. //hBitMap is invalid

79. //The source is in State 7

80. //Acknowledge the end of the transfer

81. goto LABEL_DO_ENDXFER //found in next section 82. break;

83. case TWRC_FAILURE: 84. //The transfer failed

85. //hBitMap is invalid and no memory was allocated 86. //Check Condition Code for more information

87. //The state transition failed, the source is in State 6 88. //The image data is still pending 89. //To abort the transfer

90. goto LABEL_DO_ENDXFER //found in code example for 91. //the next section 92. break; 93. }

第7步到第6步到第5步:终了传输 当开始传输,就到了第7步。当源说传输结束了(TWRC_XFERDONE)或者退出了(TWRC_CANCEL),应用就要开始往前走了。

操作码:DG_CONTROL / DAT_PENDINGXFERS / MSG_ENDXFER

? pOrigin:指向应用TW_IDENTITY结构 ? pDest:指向源TW_IDENTITY结构

? pData:指向TW_PENDINGXFERS型的结构 TW_PENDINGXFERS结构定义如下:

C代码

1. typedef struct { 2. TW_UINT16 Count; 3. TW_UINT32 Reserved;

4. } TW_PENDINGXFERS, FAR *pTW_PENDINGXFERS;

DG_CONTROL / DAT_PENDINGXFERS / MSG_ENDXFER在每个传输结束末尾,由应用传给源。成功或者退出,反正应用得到了他想要的。

当这个操作返回,应用开始检查pData->Count值,看看是否还有更多的图等着传输,pData->Count的值如下:

0:如果是0,源自觉的回到第5步,而不用应用操作。开发人员要注意这个偷偷转。应用将会转会到他的主事件循环,并且被源激活(MSG_XFERREADY/MSG_CLOSEDSREQ)

-1/>0:源还有更多的可用图等着要传,如果-1,意思是源有另外可用图,但是不确定还有多少。这个有可能发生在设备上准备了ADF(a document feeder)和不知道栈里面压了多少东西。

如果知道有多少,Count>0,两种情况,源都会在第6步等应用开始下一个传输。一个MSG_XFERREADY只发一次。

如果有很多图片准备着要传但是你不打算传,操作如下:

? 取消下一个准备的图片:操作码:DG_CONTROL /DAT_PENDINGXFERS / MSG_ENDXFER,

然后检查Count,看看还有没有准备好的图。

? 取消所有准备好的图:操作码:DG_CONTROL / DAT_PENDINGXFERS /MSG_RESET,执

行成功之后到第5步。

下面代码接在刚才第6步到第7步,展现了我天朝结束轮回之美:

C代码

1. void DoEndXfer(){

2. TW_PENDINGXFERS twPendingXfers; 3. //If the return code from

4. //DG_IMAGE/DAT_IMAGENATIVEXFER/MSG_GET was 5. // TWRC_CANCEL or TWRC_DONE

6. // Acknowledge the end of the transfer 7. rc = (*pDSM_Entry)(&AppId,

8. SourceId, 9. DG_CONTROL,

10. DAT_PENDINGXFERS, 11. MSG_ENDXFER,

12. (TW_MEMREF)&twPendingXfers); 13. if (rc == TWRC_SUCCESS){

14. // Check for additional pending xfers 15. if (twPendingXfers.Count == 0){

16. // Source is now in state 5. NOTE THE IMPLIED STATE 17. // TRANSITION! Disable and close the source and

18. // return to TransferNativeImage with a FALSE notifying 19. // it to not attempt further image transfers. 20. DisableAndCloseDS(); 21. return(FALSE); 22. }else{

23. // Source is in state 6 ready to transfer another image 24. if want to transfer this image{

25. // returns to the caller, TransferNativeImage 26. // and allows the next image to transfer 27. return TRUE;

28. }else if want to abort and skip over this transfer{ 29. // The current image will be skipped, and the 30. // next, if exists will be acquired by returning 31. // to TransferNativeImage

32. if (DoAbortXfer(MSG_ENDXFER) > 0) 33. return(TRUE); 34. else

35. return(FALSE); 36. }

37. } 38. } 39. }

40. }//--->好像是多余的

41. TW_UINT16 DoAbortXfer(TW_UINT16 AbortType){ 42. rc = (*pDSM_Entry)(&AppId,

43. SourceId, 44. DG_CONTROL,

45. DAT_PENDINGXFERS, 46. MSG_ENDXFER,

47. (TW_MEMREF)&twPendingXfers); 48. if (rc == TWRC_SUCCESS){

49. // If the next image is to be skipped, but subsequent images 50. // are still to be acquired, the PendingXfers will receive 51. // the MSG_ENDXFER, otherwise, PendingXfers will receive 52. // MSG_RESET.

53. rc = (*pDSM_Entry)(&AppId,

54. SourceId, 55. DG_CONTROL,

56. DAT_PENDINGXFERS, 57. AbortType,

58. (TW_MEMREF)&twPendingXfers); 59. } 60. }

61. //To abort all pending transfers: 62. LABEL_ABORT_ALL: 63. {

64. rc = (*pDSM_Entry) (&AppID,

65. &SourceID, 66. DG_CONTROL,

67. DAT_PENDINGXFERS, 68. MSG_RESET,

69. (TW_MEMREF)&twPendingXfers); 70. if (rc == TWRC_SUCCESS)

71. //Source is now in state 5 72. }

73. }//------>好像又多了

第5步到第1步:断开TWAIN Session 5->4

操作码:DG_CONTROL / DAT_USERINTERFACE / MSG_DISABLEDS pOrigin:指向应用的TW_IDENTITY结构 pDest:指向源的TW_IDENTITY结构

pData:指向TW_USERINTERFACE类型的结构 TW_USERINTERFACE定义如下:

C代码

1. typedef struct { 2. TW_BOOL ShowUI; 3. TW_BOOL ModalUI; 4. TW_HANDLE hParent;

5. } TW_USERINTERFACE, FAR *pTW_USERINTERFACE;

不用内容 注意几点:

? 如果显示了源的用户接口:该操作由源响应MSG_CLOSEDSREQ返回给应用。这个请求

放在TW_EVENT的TWMessage里面。通过应用的DG_CONTROL / DAT_EVENT /MSG_PROCESSEVENT操作发送事件给应用。

? 如果应用没让源的用户接口显示:当所有的传输结束之后,调用这个命令,应用也

可以调用这个命令返回到第4步,如果想修改一个或多个能力,当他准备接受更多数据的时候。

4->3

操作码:DG_CONTROL / DAT_IDENTITY / MSG_CLOSEDS

? pOrigin:指向应用TW_IDENTITY结构 ? pDest:NULL(表明方向是SM) ? pData:指向TW_IDENTITY结构

当操作结束,源关闭。(如果要关SM,要将所有的S关闭) 3->2

操作码:DG_CONTROL / DAT_PARENT / MSG_CLOSEDSM

? pOrigin:指向应用TW_IDENTITY结构

? pDest:NULL(SM第一~indicates destination is Source Manager) ? pData:通常这个是指向一个TW_PARENT结构的,但这个不是。不是DAT的那个类型。

o Win下: pData指向作为the Source’s“parent”的the window handle

(hWnd)。

The variable is of type TW_INT32. For 16 bit Microsoft Windows, the handle is stored in the low word of the 32 bit integer and the upper word is set to zero. If running under the WIN32 environment, this is a 32 bit window handle. 2->1 SM结束,卸磨杀驴DLL。Win下,用FreeLibrary( hDSMLib),hDSMLib是使用LoadLibrary()时候传回来的句柄。

最后,回顾一下:

Application Receives State Application Action Select Source...

1->2 Load Source Manager

2->3 DG_CONTROL / DAT_PARENT / MSG_OPENDSM

Acquire...

MSG_XFERREADY

MSG_CLOSEDSREQ

DG_CONTROL / DAT_IDENTITY / MSG_USERSELECT

3 -> 2 DG_CONTROL / DAT_PARENT / MSG_CLOSEDSM 2 -> 1 Unload Source Manager 1 -> 2 Load Source Manager

2 -> 3 DG_CONTROL / DAT_PARENT / MSG_OPENDSM 3 -> 4 DG_CONTROL / DAT_IDENTITY / MSG_OPENDS

Capability Negotiation

4 -> 5 DG_CONTROL / DAT_USERINTERFACE / MSG_ENABLEDS 6 For each pending transfer: DG_IMAGE / DAT_IMAGEINFO / MSG_GET DG_IMAGE / DAT_IMAGELAYOUT / MSG_GET

DG_CONTROL / DAT_CAPABILITY / MSG_GETCURRENT

6 -> 7 DG_IMAGE / DAT_IMAGExxxxXFER / MSG_GET 7 -> 6 DG_CONTROL / DAT_PENDINGXFERS / MSG_ENDXFER

6 -> 5

Automatic transition to State 5 if TW_PENDINGXFERS.Count

equals 0. 5 -> 4 DG_CONTROL / DAT_USERINTERFACE / MSG_DISABLEDS 4 -> 3 DG_CONTROL / DAT_IDENTITY / MSG_CLOSEDS 3 -> 2 DG_CONTROL / DAT_PARENT / MSG_CLOSEDSM 2 -> 1 Unload the Source Manager

Acquire...

MSG_XFERREADY

MSG_CLOSEDSREQ

DG_CONTROL / DAT_IDENTITY / MSG_USERSELECT

3 -> 2 DG_CONTROL / DAT_PARENT / MSG_CLOSEDSM 2 -> 1 Unload Source Manager 1 -> 2 Load Source Manager

2 -> 3 DG_CONTROL / DAT_PARENT / MSG_OPENDSM 3 -> 4 DG_CONTROL / DAT_IDENTITY / MSG_OPENDS

Capability Negotiation

4 -> 5 DG_CONTROL / DAT_USERINTERFACE / MSG_ENABLEDS 6 For each pending transfer: DG_IMAGE / DAT_IMAGEINFO / MSG_GET DG_IMAGE / DAT_IMAGELAYOUT / MSG_GET

DG_CONTROL / DAT_CAPABILITY / MSG_GETCURRENT

6 -> 7 DG_IMAGE / DAT_IMAGExxxxXFER / MSG_GET 7 -> 6 DG_CONTROL / DAT_PENDINGXFERS / MSG_ENDXFER

6 -> 5

Automatic transition to State 5 if TW_PENDINGXFERS.Count

equals 0. 5 -> 4 DG_CONTROL / DAT_USERINTERFACE / MSG_DISABLEDS 4 -> 3 DG_CONTROL / DAT_IDENTITY / MSG_CLOSEDS 3 -> 2 DG_CONTROL / DAT_PARENT / MSG_CLOSEDSM 2 -> 1 Unload the Source Manager

本文来源:https://www.bwwdw.com/article/15sf.html

Top