TWAIN学习笔记

更新时间:2023-09-24 16:41:01 阅读量: IT计算机 文档下载

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

2008-10-06

TWAIN学习笔记(壹)

?

TWAIN,定义了一套标准的软件协议(software protocol)和应用程序编程接口 (application programming interface(API))。使用它实现软件应用程序和图象获取设备(扫描仪)之间的通讯。我们见到的情况是:从FILE菜单下选取ACQUIRE就弹出了扫描软件。

四层:

Application,Protocol,Acquisition,Device

用户层,用户的应用程序,界面之类的东西

? 协议层,把用户的请求转换成TWAIN明白的内容 ? 请求层,向下请求内容,可以是硬件也可以是数据库 ? 硬件层,数据的来源

?

TWAIN之间通讯通过两个入口,DSM_Entry,DS_Entry

Application:

所有的应用不能直连到数据层,只能通过SourceManager,通过DSM_Entry()方法。

DSM_Entry()方法有下面的参数:

标识符构造,identifier structure ? 目标(SourceManager或者Source) ? 三个描述

o 数据组(Data Group : DG_) o Data Argument Type(DAT_) o Message(MSG_)

? 用于传数据的指针域

?

Win下,C代码类似于: C代码

1. TW_UINT16 FAR PASCAL DSM_Entry(

2. pTW_IDENTITY pOrigin, // source of message

3. pTW_IDENTITY pDest, // destination of message 4. TW_UINT32 DG, // data group ID: DG_xxxx

5. TW_UINT16 DAT, // data argument type: DAT_xxxx

6. TW_UINT16 MSG, // message ID: MSG_xxxx 7. TW_MEMREF pData // pointer to data 8. );

Source Manager:

SM提供应用层和数据层之间的通讯,支持用户选取数据源,应用层读取数据源。如果用DSM_Entry()的时候,调用的是SM,那直接就操作它本身。如果调用的是S,那再调用DS_Entry()。 Win下面,C代码类似于: C代码

1. TW_UINT16 FAR PASCAL DS_Entry(

2. pTW_IDENTITY pOrigin, // source of message

3. TW_UINT32 DG, // data group ID: DG_xxxx 4. TW_UINT16 DAT, // data argument type: DAT_xxxx

5. TW_UINT16 MSG, // message ID: MSG_xxxx 6. TW_MEMREF pData // pointer to data 7. ) Source:

返回值前缀TWRC_,如果出问题,设置一个前缀为TWCC_的状态码,但是不会自动返回。

SM和S在Win下都是DLL形式实现。

从Source返回给Application,需要4步:

通知应用层,已经准备好了有东西要返回了。MSG_XFERREADY用于Source通知App

? 禁用Source的用户接口,MSG_CLOSEDSREQ

? 通知应用层,按下了OK按钮,应用更改,用于Source被DG_CONTROL /DAT_USERINTERFACE / MSG_ENABLEDSUIONLY.打开的情况,MSG_CLOSEDSOK ? 设备发生动作,只有在应用层给数据层这个优先权,单独传回来。MSG_DEVICEEVENT

?

DSM_Entry()和DS_Entry()用于通讯,一个操作和一个应用或者SM关联。通常,但不绝对,用传进来的最后一个参数(pData)来描述。

从app到SM,设为NULL,从app到S(通过SM),设为目标id,从SM到S,设为DS_Entry。

传进来的三个参数DG,DAT,MSG表示的意思如下: DG_XXXX:

DG_CONTROL 用于TWAIN操作动作,例如打开SM ? DG_IMAGE 用于操作图形图像操作 ? DG_AUDIO 用于操作声频数据

?

DAT_XXX:

传进来的参数,可以引用一个结构体或者变量,例如DAT_IDENTITY,还有类似于TW_XXX的声明。 MSG_XXX:

用于确定动作,都是类似于MSG_GET,MSG_SET的有前缀MSG_开始的。 三个例子:

打开SM模块:DG_CONTROL/DAT_PARENT/MSG_OPENDSM 打开对话框,让用户可以选择Source:

DG_CONTROL/DAT_IDENTITY/MSG_USERSELECT

导一个图像到文件上:DG_IMAGE/DAT_IMAGEFILEXFER/MSG_GET

协议层被分为7个阶段:

[1,2,3]在且只在SM阶段,[4,5,6,7]在且只在S阶段。 举例说:

1.Pre-Session ----> 2.SM Loaded ----> 3.SM Opened ----> 4.Source Open ---->

SM not loaded App:Get Entry point User:Select Source Capability Negotiation

5.Source Enable ----> 6.Transfer Ready ----> 7.Transferring

Source:Show User App:Inquire Image Source: Transfer Data

Interface or Audio Information

看英文资料精疲力竭??还阳中??

TWAIN学习笔记(贰)

TWAIN

能力分成三组:

?

CAP_XXX:适用于一般的数据源 ? ICAP_XXX:适用于图形图像源 ? ACAP_XXX:适用于声音数据源

能力容器分成四类:

?

TW_ONEVALUE:单值 ? TW_ARRAY:多值 ? TW_RANGE:范围值

? TW_ENUMERATION:枚举值

<上面数据类型很烦,自己看说明去吧>

有三种方法将Source传递到应用程序。native, disk file, buffered memory。音频文件只支持native和disk file。

Native:所有的Source都必须支持的模式,但是有限制性(例如限制于DIB或者PICT格式,受可用内存的限制),Win下,DIB格式(Device-Independent Bitmap),Source给文件分配一个内存块,将指针返回给应用,应用负责转换数据之后释放这块内存。

Disk File:推荐Source支持这种模式,应用程序创建一个Source支持格式的文件,易于读写,尤其是可以避免遇到内存问题。稍微比之后讨论的Buffered模式慢,但比他好操作,并且之后应用程序要操作清理这个文件。

Buffered Memory:所有的Source必须支持该模式。

MD,被关闭了,没保存。

通过一个或多个缓存来实现传输,应用层来分配内存的使用和释放。数据以一无格式位图(unformatted bitmap)传输,应用需要在传输过程中

(TW_IMAGEINFO&TW_IMAGEMEMXFER)用信息标识各个缓存和正确识别位图。于Native和Disk File的一个动作结束传输相比,这种模式可能要多次循环。

应用层实现: TWAIN的实现层次:

最小实现:使用TWAIN默认的,只在Native本机模式,请求单独一个图片。

? 基本实现: ? 最大实现:

?

安装SM(Source Manager)软件:

TWAIN Working Group(TWG)给Win提供四个包:

TWAIN_32.DLL:32位程序用 ? TWAIN.DLL:16位程序用

? TWUNKER_32.EXE:让16位应用程序链接32位的数据源

? TWUNKER_16.EXE:让32位应用程序链接16位源,注意,16位源不能再NT上面正确运行

?

SM四个文件Win文件夹下,比如C:\\Winnt,C:\\Windows.

微软提供了一个VER.DLL包,用于安装SM。VER.DLL,VER.LIB,VER.H包括在安装包Toolkit里面。VER.DLL是可以自由使用和发布的。 TWAIN要开始,要做三个准备:

添加应用的用户接口用来选择数据源和请求菜单选择:必须有选择源(Select Source...和Acquire...)

? 将TWAIN.H引用到程序中:包括所有必须的定义

? 更改应用的事件循环: 可以开很多个源,但是每次只能持有一个。

o 传递事件给Source

o 通知应用,源准备好了或者关闭接口 o 硬件事件发生的时候通知应用。

?

三个目标的实现如下:

——————靠—————— 下面全都是具体实现,不想弄了。 ——————靠—————— 算了,复制粘贴一下。谁帮个忙。

第一个目标,传递事件(从应用到源):

只要源激活了,为了确保源能接受和执行事件,应用必须将所有事件,在源激活期间,统统传过去。

如: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 Source to */ 4. /* the application */

5. } TW_EVENT, FAR *pTW_EVENT;

pEvent在Win下,指向message structure。源从SM接收到信息,决定是否属于它,

如果是:源执行事件,然后设置返回码为TWRC_DSEVENT,以示它是Source事件,并且设置TW_Event结构的TWMessage到MSG_NULL, ? 如果不是:设置返回码为TWRC_NOTDSEVENT,设置TWMessage到MSG_NULL,应用从DSM_Entry接收到信息,然后在循环里面装作没事情一样执行。

?

第二和第三个目标,(从源到事件)

当源准备好了, 通知应用,通过TW_EVENT.TWMessage,有下面四个选项: MSG_XFERREADY:标示数据已经准备好了 ? MSG_CLOSEDSREQ:关闭Source的用户接口

? MSG_CLOSEDSOK:同上,不过只用在DG_CONTROL / DAT_USERINTERFACE / MSG_ENABLEDSUIONLY

? MSG_DEVICEEVENT:报告设备事件发生

?

Win下,修改循环的例子代码: C代码

1. TW_EVENT twEvent; 2. TW_INT16 rc;

3. while (GetMessage ( (LPMSG) &msg, NULL, 0, 0) ) { 4. rc = TWRC_NOTDSEVENT; 5. if Source is enabled {

6. twEvent.pEvent = (TW_MEMREF)&msg; 7. twEvent.TWMessage = MSG_NULL; 8. rc = (*pDSM_Entry) (pAppId,

9. pSourceId, 10. DG_CONTROL, 11. DAT_EVENT,

12. MSG_PROCESSEVENT, 13. (TW_MEMREF)&twEvent);

14. // check for message from Source 15. switch (twEvent.TWMessage) {

16. case MSG_XFERREADY:

17. SetupAndTransferImage(NULL); 18. break;

19. case MSG_CLOSEDSREQ:

20. DisableAndCloseSource(NULL); 21. break;

22. case MSG_CLOSEDSOK:

23. DisableAndCloseSource(NULL); 24. GetCustomDsData(); 25. break; 26. case MSG_NULL:

27. // no message returned from the source

28. break; 29. } 30. }

31. // Source didn’t process it, so we will 32. if (rc == TWRC_NOTDSEVENT) {

33. TranslateMessage( (LPMSG) &msg); 34. DispatchMessage( (LPMSG) &msg); 35. } 36.}

DSM_Entry()方法: Win下代码如下: C代码

1. TW_UINT16 FAR PASCAL DSM_Entry(

2. pTW_IDENTITY pOrigin, // source of message

3. pTW_IDENTITY pDest, // destination of message 4. TW_UINT32 DG, // data group ID: DG_xxxx 5. TW_UINT16 DAT, // data argument type: DAT_xxxx

6. TW_UINT16 MSG, // message ID: MSG_xxxx 7. TW_MEMREF pData // pointer to data 8. );

pOrigin:TW_IDENTITY,从应用和源链接上之后不能改变。 ? pDest:如果操作最后目标是SM,设置为NULL,否则指向源

? DG_XXX:DG_CONTROL,DG_IMAGE,DG_AUDIO目前是被定义掉了的,可以自定义数据组。

?

DAT_XXX:描述pData对象的唯一标示(结构或者变量) ? MSG_XXX:动作的描述

? pData:操作用到的TW_XXX结构或者变量,类型有DAT_XXX描述。

?

There are nine operation triplets that can be sent from the application to be consumed by the Source Manager.

有九个手术双胞胎,可发出的申请将消费源管理器。

从应用到SM,(我们公司的人事很有味道

),DG统统属于DG_CONTROL,DAT

有三个:DAT_IDENTITY,DAT_PARENT,DAT_STATUS。下面的列表是DAT下面的MSG组合:

DG_CONTROL/DAT_IDENTITY MSG_CLOSEDS: MSG_GETDEFAULT : MSG_GETFIRST : MSG_GETNEXT : MSG_OPENDS : MSG_USERSELECT : DG_CONTROL / DAT_PARENT MSG_CLOSEDSM : MSG_OPENDSM :

DG_CONTROL / DAT_STATUS MSG_GET :

从应用到源:

参数通过DSM_Entry调用,第一个集是DG_CONTROL,定义了DG能在所有的TWAIN设备上运用的。第二个集,定义为DG_IMAGE。 DG_CONTROL / DAT_CAPABILITY MSG_GET MSG_GETCURRENT MSG_GETDEFAULT MSG_RESET :

(能力值,扫描仪这类东西能干啥) 获取能力值,包括当前的和默认的 获取能力值当前值 获取源的默认首选能力值

将当前源能力值转成TWAIN定义的默认值

准备关闭源

获取默认源的标识信息 获取第一个活动源的标识信息 获取下一个活动源的标识信息 装载且初始化源 弹出“选择源”的对话框

准备关闭SM 初始化SM

返回SM当前状态码

MSG_SET :

DG_CONTROL / DAT_DEVICEEVENT MSG_GET :

DG_CONTROL / DAT_EVENT MSG_PROCESSEVENT :

DG_CONTROL / DAT_FILESYSTEM MSG_AUTOMATICCAPTUREDIRECTORY : 设定能力值

DG_CONTROL / DAT_NULL / MSG_DEVICEEVENT

从应用传递事件到源

选择目录自动接收图像

MSG_CHANGEDIRECTORY : MSG_COPY :

MSG_CREATEDIRECTORY : MSG_DELETE : MSG_FORMATMEDIA : MSG_GETCLOSE MSG_GETFIRSTFILE MSG_GETINFO MSG_RENAME DG_CONTROL/DAT_PASSTHRU/MSG_PASSTHRU MSG_PASSTHRU

DG_CONTROL / DAT_PENDINGXFERS MSG_ENDXFER MSG_GET MSG_RESET MSG_STOPFEEDER

DG_CONTROL / DAT_SETUPFILEXFER MSG_GET MSG_GETDEFAULT MSG_RESET MSG_SET

DG_CONTROL / DAT_SETUPFILEXFER2 MSG_GET MSG_GETDEFAULT MSG_RESET MSG_SET

DG_CONTROL / DAT_SETUPMEMXFER MSG_GET

更改当前domain,host,dir,设备 拷贝文件

建立一个目录文件夹 删除一个目录文件夹 格式化存储设备(?那么牛) 关闭MSG_GETFILEFIRST打开的上下文 获取目录里第一个文件 获取当前文件上下文的信息 重命名一文件

用特殊命令。(无聊厂家提供的特殊功能)

应用接收或者请求结束数据传输 返回源准备提供的传输 重置 强行停止ADF

返回文件的信息,文件将被源写入请求的数据

返回默认的文件传输信息 重置当前文件信息 为下一个文件传输设置信息

跟上面一样 跟上面一样 跟上面一样 跟上面一样

返回源的最优,最小和最大的缓冲值

DG_CONTROL / DAT_STATUS MSG_GET

DG_CONTROL / DAT_USERINTERFACE MSG_DISABLEDS MSG_ENABLEDS

DG_CONTROL / DAT_XFERGROUP MSG_GET

从源返回当前状态码

关闭源的用户接口 激活源的用户接口

给下面传输返回DG,目前支持DG_IMAGE或自定DG

上回说到从应用到源的三胞胎的第一组设置,现在说第二组DG_IMAGE DG_IMAGE / DAT_CIECOLOR MSG_GET

DG_IMAGE / DAT_GRAYRESPONSE MSG_RESET MSG_SET

DG_IMAGE / DAT_IMAGEFILEXFER MSG_GET

DG_IMAGE / DAT_IMAGEINFO MSG_GET

DG_IMAGE / DAT_IMAGELAYOUT MSG_GET MSG_GETDEFAULT MSG_RESET MSG_SET

DG_IMAGE / DAT_IMAGEMEMXFER MSG_GET MSG_GET MSG_GET MSG_GETDEFAULT MSG_RESET MSG_SET

DG_IMAGE / DAT_PALETTE8 MSG_GET MSG_GETDEFAULT MSG_RESET MSG_SET

给当前的传输返回CIE XYZ信息

灰度默认值 设置灰度值

用Disk File模式初始化图形图像请求

返回准备传输的图形图像的信息

给“原始”图像描述物理布局/位置 获取图的默认布局信息

将下个图传输布局信息设成默认值 设置下个图传输的布局信息

以缓存模式初始化图请求 以本地模式初始化图请求 获取当前传输的JPEG压缩参数 获取默认的JPEG压缩参数 使用源的默认JPEG压缩值 使用指定的JPEG压缩值

获取当前传输信息 获取源默认的调色板信息 使用源默认的调色板 使用指定的调色板

DG_IMAGE / DAT_IMAGENATIVEXFER DG_IMAGE / DAT_JPEGCOMPRESSION

DG_IMAGE / DAT_RGBRESPONSE MSG_RESET MSG_SET

DG_AUDIO / DAT_AUDIOFILEXFER MSG_GET :

DG_AUDIO / DAT_AUDIOINFO MSG_GET : MSG_GET

使用默认的RGB值 设定RGB值

文件(File)模式传音频数据

获取当前传输的信息(av的上半集) 本地模式(Native)传输音频(audio)数据

DG_AUDIO / DAT_AUDIONATIVEXFER

以上说的是三胞胎(triplet,这个变态的翻译好记点,别学我), DG_XXX,DAT_XXX,MSG_XXX由上面的决定,剩下的几个补充如下:

pOrigin:源,应用程序的TW_IDENTITY结构的副本

? pDest:如果操作对象是SM,值一定是NULL,如果是源,该参数引用源的TW_IDENTITY结构的一副本,返回给应用

? pData:由之前的DAT_XXX来定义是什么类型。通常,对应的用TW_XXX来命名数据结构。如:DAT_IDENTITY对应的就是TW_XXX。TWAIN.H里面定义了全部的结构。应用负责所有的分配和释放以及检查。

?

{最短的一章,下面那个一个整体,实在对不起啊兄弟,委屈你太监了。}

DIB(自百度百科)

C代码

1. DIB,全称Device Independent Bitmap,设备无关位图文件,这是一种文件格式,其目的是为了保证用某个应用程序创建的位图图形可以被其它应用程序装载或显示一样。 2.

3. DIB(Device-indepentent bitmap)的与设备无关性主要体现在以下两个方面:

4. DIB的颜色模式与设备无关。例如,一个256色的DIB即可以在真彩色显示模式下使用,也可以在16色模式下使用。

5. 256色以下(包括256色)的DIB拥有自己的颜色表,像素的颜色独立于系统调色板。

6. 由于DIB不依赖于具体设备,因此可以用来永久性地保存图象。DIB一般是以*.BMP文件的形式保存在磁盘中的,有时也会保存在*.DIB文件中。运行在不同输出设备下的应用程序可以通过DIB来交换图象。 7. DIB还可以用一种RLE算法来压缩图像数据,但一般来说DIB是不压缩的。 8. DIB的结构

9. 与Borland C++下的框架类库OWL不同,MFC未提供现成的类来封装DIB。尽管Microsoft列出了一些理由,但没有DIB类确实给MFC用户带来很多不便。用户要想使用DIB,首先应该了解DIB的结构。

10. 在内存中,一个完整的DIB由两部分组成:一个BITMAPINFO结构和一个存储像素阵列的数组。BITMAPINFO描述了位图的大小,颜色模式和调色板等各种属性,其定义为

11. typedef struct tagBITMAPINFO {

12. BITMAPINFOHEADER bmiHeader; 13. RGBQUAD bmiColors[1]; //颜色表 14. } BITMAPINFO;

15. RGBQUAD结构用来描述颜色,其定义为 16. typedef struct tagRGBQUAD {

17. BYTE rgbBlue; //蓝色的强度 18. BYTE rgbGreen; //绿色的强度 19. BYTE rgbRed; //红色的强度

20. BYTE rgbReserved; //保留字节,为0 21. } RGBQUAD;

22. 注意,RGBQUAD结构中的颜色顺序是BGR,而不是平常的RGB。 23. BITMAPINFOHEADER结构包含了DIB的各种信息,其定义为 24. typedef struct tagBITMAPINFOHEADER{

25. DWORD biSize; //该结构的大小

26. LONG biWidth; //位图的宽度(以像素为单位) 27. LONG biHeight; //位图的高度(以像素为单位) 28. WORD biPlanes; //必须为1

29. WORD biBitCount //每个像素的位数(1、4、8、16、24或32)

30. DWORD biCompression; //压缩方式,一般为0或BI_RGB (未压缩)

31. DWORD biSizeImage; //以字节为单位的图象大小(仅用于压缩位图)

32. LONG biXPelsPerMeter; //以目标设备每米的像素数来说明位图的水平分辨率

33. LONG biYPelsPerMeter; //以目标设备每米的像素数来说明位图的垂直分辨率

34. DWORD biClrUsed; /*颜色表的颜色数,若为0则位图使用由biBitCount指定的最大颜色数*/

35. DWORD biClrImportant; //重要颜色的数目,若该值为0则所有颜色都重要

36. } BITMAPINFOHEADER;

37. 与DDB不同,DIB的字节数组是从图象的最下面一行开始的逐行向上存储的,也即等于把图象倒过来然后在逐行扫描。另外,字节数组中每个扫描行的字节数必需是4的倍数,如果不足要用0补齐 38. DIB可以存储在*.BMP或*.DIB文件中。DIB文件是以BITMAPFILEHEADER结构开头的,该结构的定义为 39. typedef struct tagBITMAPFILEHEADER {

40. WORD bfType; //文件类型,必须为\41. DWORD bfSize; //文件的大小 42. WORD bfReserved1; //为0 43. WORD bfReserved2; //为0

44. DWORD bfOffBits; //存储的像素阵列相对于文件头的偏移量

45. } BITMAPFILEHEADER;

46. 紧随该结构的是一个BITMAPINFOHEADER结构,然后是RGBQUAD结构组成的颜色表(如果有的话),文件最后存储的是DIB的像素阵列。 47.DIB的颜色信息储存在自己的颜色表中,程序一般要根据颜色表为DIB创建逻辑调色板。在输出一幅DIB之前,程序应该将其逻辑调色板选入到相关的设备上下文中并实现到系统调色板中,然后再调用相关的GDI函数(如::SetDIBitsToDevice或::StretchDIBits)输出DIB。在输出过程中,GDI函数会把DIB转换成DDB,这项工作主要包括以下两步: 48. 将DIB的颜色格式转换成与输出设备相同的颜色格式。例如,在真彩色的显示模式下要显示一个256色的DIB,则应该将其转换成24位的颜色格式。

49. 将DIB像素的逻辑颜色索引转换成系统调色板索引。 50.编写DIB类

51. 由于MFC未提供DIB类,用户在使用DIB时将面临繁重的Windows API编程任务。幸运的是,Visual C++提供了一个较高层次的API,简化了DIB的使用。这些API函数实际上是由MFC的DibLook例程提供的,它们位于DibLook目录下的dibapi.cpp、myfile.cpp和dibapi.h文件中,主要包括:

52. ReadDIBFile //把DIB文件读入内存 53. SaveDIB //把DIB保存到文件中

54. CreateDIBPalette //从DIB中创建一个逻辑调色板 55. PaintDIB //显示DIB

56. DIBWidth //返回DIB的宽度 57. DIBHeight //返回DIB的高度 58.DIB区块 59.DIB区块

60.DIB能拥有几种色彩组织中的一种,DDB必须是单色的或是与真实输出设备相同的格式。DIB是一个档案或记忆体块;DDB是GDI点阵图物件并由点阵图代号表示。DIB能被显示或转换为DDB并转换回DIB,但是这里包含了装置无关位元和设备相关位元之间的转换程序。

61.现在您将遇到一个函式,它打破了这些规则。该函式在32位元Windows版本中发表,称为CreateDIBSection,语法为: 62.hBitmap = CreateDIBSection (

63. hdc, // device context handle

64. pInfo, // pointer to DIB information

65. fClrUse, // color use flag

66. ppBits, // pointer to pointer variable

67. hSection, // file-mapping object handle

68. dwOffset) ; // offset to bits in file-mapping object

69.CreateDIBSection是Windows API中最重要的函式之一(至少在使用点阵图时),然而您会发现它很深奥并难以理解。

70.让我们从它的名称开始,我们知道DIB是什么,但「DIB section」到底是什么呢?当您第一次检查CreateDIBSection时,可能会寻找该函式与DIB区块工作的方式。这是正确的,CreateDIBSection所做的就是建立了DIB的一部分(点阵图图素位元的记忆体块)。 71.现在我们看一下传回值,它是GDI点阵图物件的代号,这个传回值可能是该函式呼叫最会拐人的部分。传回值似乎暗示著CreateDIBSection在功能上与CreateDIBitmap相同。事实上,它只是相似但完全不同。实际上,从CreateDIBSection传回的点阵图代号与我们在本章和上一章遇到的所有点阵图建立函式传回的点阵图代号在本质上不同。

72.一旦理解了CreateDIBSection的真实特性,您可能觉得奇怪为什么不把传回值定义得有所区别。您也可能得出结论:CreateDIBSection应该称之为CreateDIBitmap,并且如同我前面所指出的CreateDIBitmap应该称之为CreateDDBitmap。

73.首先让我们检查一下如何简化CreateDIBSection,并正确地使用它。首先,把最後两个参数hSection和dwOffset,分别设定为NULL和0,我将在本章最後讨论这些参数的用法。第二,仅在fColorUse参数设定为DIB_ PAL_COLORS时,才使用hdc参数,如果fColorUse为DIB_RGB_COLORS(或0),hdc将被忽略(这与CreateDIBitmap不同,hdc参数用於取得与DDB相容的设备的色彩格式)。

74.因此,CreateDIBSection最简单的形式仅需要第二和第四个参数。第二个参数是指向BITMAPINFO结构的指标,我们以前曾使用过。我希望指向第四个参数的指标定义的指标不会使您困惑,它实际上很简单。 75.假设要建立每图素24位元的384×256位元DIB,24位元格式不需要色彩对照表,因此它是最简单的,所以我们可以为BITMAPINFO参数使用BITMAPINFOHEADER结构。

76.您需要定义三个变数:BITMAPINFOHEADER结构、BYTE指标和点阵图代号:

77.BITMAPINFOHEADER bmih ;

78.BYTE * pBits ; 79.HBITMAP hBitmap ; 80.现在初始化BITMAPINFOHEADER结构的栏位

81.bmih->biSize = sizeof (BITMAPINFOHEADER) ; 82.bmih->biWidth = 384 ; 83.bmih->biHeight = 256 ; 84.bmih->biPlanes = 1 ; 85.bmih->biBitCount = 24 ;

86.bmih->biCompression = BI_RGB ; 87.bmih->biSizeImage = 0 ; 88.bmih->biXPelsPerMeter = 0 ; 89.bmih->biYPelsPerMeter = 0 ; 90.bmih->biClrUsed = 0 ; 91.bmih->biClrImportant = 0 ; 92.在基本准备後,我们呼叫该函式:

93.hBitmap = CreateDIBSection (NULL, (BITMAPINFO *) &bmih, 0, &pBits, NULL, 0) ;

94.注意,我们为第二个参数赋予BITMAPINFOHEADER结构的位址。这是常见的,但一个BYIE指标pBits的位址,就不常见了。这样,第四个参数是函式需要的指向指标的指标。

95.这是函式呼叫所做的:CreateDIBSection检查BITMAPINFOHEADER结构并配置足够的记忆体块来载入DIB图素位元。(在这个例子里,记忆体块的大小为384×256×3位元组。)它在您提供的pBits参数中储存了指向此记忆体块的指标。函式传回点阵图代号,正如我说的,它与

CreateDIBitmap和其他点阵图建立函式传回的代号不一样。

96.然而,我们还没有做完,点阵图图素是未初始化的。如果正在读取DIB档案,可以简单地把pBits参数传递给ReadFile函式并读取它们。或者可以使用一些程式码「人工」设定。

DIB(自百度百科)END

应用控制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,MAKEINTRESOURCE (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 found 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

Select Source...

Acquire...

MSG_XFERREADY

MSG_CLOSEDSREQ

1->2 Load Source Manager

2->3 DG_CONTROL / DAT_PARENT / MSG_OPENDSM

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 6

Capability Negotiation For each pending transfer: DG_IMAGE / DAT_IMAGEINFO / MSG_GET DG_IMAGE / DAT_IMAGELAYOUT / MSG_GET

DG_CONTROL / DAT_CAPABILITY / MSG_GETCURRENT

4 -> 5 DG_CONTROL / DAT_USERINTERFACE / MSG_ENABLEDS

6 -> 7 DG_IMAGE / DAT_IMAGExxxxXFER / MSG_GET 7 -> 6 DG_CONTROL / DAT_PENDINGXFERS / MSG_ENDXFER Automatic transition to State 5 if 6 -> 5 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

TWAIN学习笔记(柒) | DIB(自百度百科)

? ? ? ? ? 评论

15:16

浏览 (1769) 评论 (0)

分类: 基础知识 相关推荐

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_ARRAY */

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(TW_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_ONEVALUE));

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

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

Top