CnTwain.pas 53 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633
  1. {******************************************************************************}
  2. { CnPack For Delphi/C++Builder }
  3. { 中国人自己的开放源码第三方开发包 }
  4. { (C)Copyright 2001-2018 CnPack 开发组 }
  5. { ------------------------------------ }
  6. { }
  7. { 本开发包是开源的自由软件,您可以遵照 CnPack 的发布协议来修 }
  8. { 改和重新发布这一程序。 }
  9. { }
  10. { 发布这一开发包的目的是希望它有用,但没有任何担保。甚至没有 }
  11. { 适合特定目的而隐含的担保。更详细的情况请参阅 CnPack 发布协议。 }
  12. { }
  13. { 您应该已经和开发包一起收到一份 CnPack 发布协议的副本。如果 }
  14. { 还没有,可访问我们的网站: }
  15. { }
  16. { 网站地址:http://www.cnpack.org }
  17. { 电子邮件:master@cnpack.org }
  18. { }
  19. {******************************************************************************}
  20. unit CnTwain;
  21. {* |<PRE>
  22. ================================================================================
  23. * 软件名称:外接设备组件包
  24. * 单元名称:实现扫描仪图象采集单元
  25. * 单元作者:rarnu(rarnu@cnpack.org)
  26. * 备 注:爱普生扫描仪可用,使用EPSON V200 API,本单元仅是略做封装
  27. * 开发平台:Windows2003 Server + Delphi2007 up2
  28. * 兼容测试:Windows2000/XP/2003/Vista + Delphi 7/2006/2007/2009
  29. * 本 地 化:该单元中的字符串均符合本地化处理方式
  30. * 单元标识:$Id$
  31. * 修改记录:2008.08.14 V1.0
  32. * 创建单元
  33. ================================================================================
  34. |</PRE>}
  35. interface
  36. {$I CnPack.inc}
  37. uses
  38. Windows, Messages, SysUtils, Classes, Controls, Forms, Graphics;
  39. const
  40. APP_PROTOCOLMAJOR = 4;
  41. APP_PROTOCOLMINOR = 0;
  42. VALID_HANDLE = 32;
  43. const
  44. TWON_PROTOCOLMAJOR = 1;
  45. TWON_PROTOCOLMINOR = 7;
  46. TWON_ARRAY = 3;
  47. TWON_ENUMERATION = 4;
  48. TWON_ONEVALUE = 5;
  49. TWON_RANGE = 6;
  50. TWON_ICONID = 962;
  51. TWON_DSMID = 461;
  52. TWON_DSMCODEID = 63;
  53. TWON_DONTCARE8 = $FF;
  54. TWON_DONTCARE16 = $FFFF;
  55. TWON_DONTCARE32 = $FFFFFFFF;
  56. TWCY_USA = 1;
  57. TWCY_CANADA = 2;
  58. TWCY_MEXICO = 3;
  59. TWCY_BRITAIN = 6;
  60. TWCY_FRANCE = 33;
  61. TWCY_JAPAN = 81;
  62. TWCY_KOREA = 82;
  63. TWCY_CHINA = 86;
  64. TWCY_HONGKONG = 852;
  65. TWCY_TAIWAN = 886;
  66. TWLG_DAN = 0; //Danish
  67. TWLG_DUT = 1; //Dutch
  68. TWLG_ENG = 2; //International English
  69. TWLG_FCF = 3; //French Canadian
  70. TWLG_FIN = 4; //Finnish
  71. TWLG_FRN = 5; //French
  72. TWLG_GER = 6; //German
  73. TWLG_ICE = 7; //Icelandic
  74. TWLG_ITN = 8; //Italian
  75. TWLG_NOR = 9; //Norwegian
  76. TWLG_POR = 10; //Portuguese
  77. TWLG_SPA = 11; //Spanish
  78. TWLG_SWE = 12; //Swedish
  79. TWLG_USA = 13; //U.S. English
  80. TWLG_USERLOCALE = $FFFF;
  81. TWLG_CHINESE = 37;
  82. TWLG_CHINESE_PRC = 39; // People's Republic of China
  83. TWLG_CHINESE_SIMPLIFIED = 41;
  84. TWLG_CHINESE_TAIWAN = 42;
  85. TWLG_CHINESE_TRADITIONAL = 43;
  86. TWTY_INT8 = $0000; // Means Item is a TW_INT8
  87. TWTY_INT16 = $0001; // Means Item is a TW_INT16
  88. TWTY_INT32 = $0002; // Means Item is a TW_INT32
  89. TWTY_UINT8 = $0003; // Means Item is a TW_UINT8
  90. TWTY_UINT16 = $0004; // Means Item is a TW_UINT16
  91. TWTY_UINT32 = $0005; // Means Item is a TW_UINT32
  92. TWTY_BOOL = $0006; // Means Item is a TW_BOOL
  93. TWTY_FIX32 = $0007; // Means Item is a TW_FIX32
  94. TWTY_FRAME = $0008; // Means Item is a TW_FRAME
  95. TWTY_STR32 = $0009; // Means Item is a TW_STR32
  96. TWTY_STR64 = $000a; // Means Item is a TW_STR64
  97. TWTY_STR128 = $000b; // Means Item is a TW_STR128
  98. TWTY_STR255 = $000c; // Means Item is a TW_STR255
  99. DG_CONTROL = $00000001; // data pertaining to control
  100. DG_IMAGE = $00000002; // data pertaining to raster images
  101. DG_IMAGE_OR_CONTROL = $00000003; //is " DG_CONTROL|DG_IMAGE " in C++
  102. DAT_NULL = $0000; // No data or structure.
  103. DAT_CUSTOMBASE = $8000; // Base of custom DATs.
  104. // Data Argument Types for the DG_CONTROL Data Group.
  105. DAT_CAPABILITY = $0001; // TW_CAPABILITY
  106. DAT_EVENT = $0002; // TW_EVENT
  107. DAT_IDENTITY = $0003; // TW_IDENTITY
  108. DAT_PARENT = $0004; // TW_HANDLE, app win handle in Windows
  109. DAT_PENDINGXFERS = $0005; // TW_PENDINGXFERS
  110. DAT_SETUPMEMXFER = $0006; // TW_SETUPMEMXFER
  111. DAT_SETUPFILEXFER = $0007; // TW_SETUPFILEXFER
  112. DAT_STATUS = $0008; // TW_STATUS
  113. DAT_USERINTERFACE = $0009; // TW_USERINTERFACE
  114. DAT_XFERGROUP = $000a; // TW_UINT32
  115. DAT_TWUNKIDENTITY = $000b; // TW_TWUNKIDENTITY
  116. // Data Argument Types for the DG_IMAGE Data Group.
  117. DAT_IMAGEINFO = $0101; // TW_IMAGEINFO
  118. DAT_IMAGELAYOUT = $0102; //TW_IMAGELAYOUT
  119. DAT_IMAGEMEMXFER = $0103; //TW_IMAGEMEMXFER
  120. DAT_IMAGENATIVEXFER = $0104; //TW_UINT32 loword is hDIB, PICHandle
  121. DAT_IMAGEFILEXFER = $0105; //Null data
  122. DAT_CIECOLOR = $0106; //TW_CIECOLOR
  123. DAT_GRAYRESPONSE = $0107; //TW_GRAYRESPONSE
  124. DAT_RGBRESPONSE = $0108; //TW_RGBRESPONSE
  125. DAT_JPEGCOMPRESSION = $0109; //TW_JPEGCOMPRESSION
  126. DAT_PALETTE8 = $010A; //TW_PALETTE8
  127. // All message constants are unique.
  128. MSG_NULL = $0000; // Used in TW_EVENT structure
  129. MSG_CUSTOMBASE = $8000; // Base of custom messages
  130. // Generic messages may be used with any of several DATs.
  131. MSG_GET = $0001; // Get one or more values
  132. MSG_GETCURRENT = $0002; // Get current value
  133. MSG_GETDEFAULT = $0003; // Get default (e.g. power up) value
  134. MSG_GETFIRST = $0004; // Get first of a series of items, e.g. DSs
  135. MSG_GETNEXT = $0005; // Iterate through a series of items.
  136. MSG_SET = $0006; // Set one or more values
  137. MSG_RESET = $0007; // Set current value to default value
  138. // Messages used with DAT_NULL
  139. MSG_XFERREADY = $0101; // The data source has data ready
  140. MSG_CLOSEDSREQ = $0102; // Request for App. to close DS
  141. MSG_CLOSEDSOK = $0103; // Tell the Application. to save the state.
  142. // Messages used with a pointer to a DAT_STATUS structure
  143. MSG_CHECKSTATUS = $0201; // Get status information
  144. // Messages used with a pointer to DAT_PARENT data
  145. MSG_OPENDSM = $0301; // Open the DSM
  146. MSG_CLOSEDSM = $0302; // Close the DSM
  147. // Messages used with a pointer to a DAT_IDENTITY structure
  148. MSG_OPENDS = $0401; // Open a data source
  149. MSG_CLOSEDS = $0402; // Close a data source
  150. MSG_USERSELECT = $0403; // Put up a dialog of all DS
  151. // Messages used with a pointer to a DAT_USERINTERFACE structure
  152. MSG_DISABLEDS = $0501; // Disable data transfer in the DS
  153. MSG_ENABLEDS = $0502; // Enable data transfer in the DS
  154. // Messages used with a pointer to a DAT_EVENT structure
  155. MSG_PROCESSEVENT = $0601;
  156. // Messages used with a pointer to a DAT_PENDINGXFERS structure
  157. MSG_ENDXFER = $0701;
  158. // Capabilities
  159. CAP_CUSTOMBASE = $8000; //Base of custom capabilities
  160. // all data sources are REQUIRED to support these caps
  161. CAP_XFERCOUNT = $0001;
  162. // image data sources are REQUIRED to support these caps
  163. ICAP_COMPRESSION = $0100;
  164. ICAP_PIXELTYPE = $0101;
  165. ICAP_UNITS = $0102; //default is TWUN_INCHES
  166. ICAP_XFERMECH = $0103;
  167. // all data sources MAY support these caps
  168. CAP_AUTHOR = $1000;
  169. CAP_CAPTION = $1001;
  170. CAP_FEEDERENABLED = $1002;
  171. CAP_FEEDERLOADED = $1003;
  172. CAP_TIMEDATE = $1004;
  173. CAP_SUPPORTEDCAPS = $1005;
  174. CAP_EXTENDEDCAPS = $1006;
  175. CAP_AUTOFEED = $1007;
  176. CAP_CLEARPAGE = $1008;
  177. CAP_FEEDPAGE = $1009;
  178. CAP_REWINDPAGE = $100a;
  179. CAP_INDICATORS = $100b; //Added 1.1
  180. CAP_SUPPORTEDCAPSEXT = $100c; // Added 1.6
  181. CAP_PAPERDETECTABLE = $100d; // Added 1.6
  182. CAP_UICONTROLLABLE = $100e; // Added 1.6
  183. // image data sources MAY support these caps
  184. ICAP_AUTOBRIGHT = $1100;
  185. ICAP_BRIGHTNESS = $1101;
  186. ICAP_CONTRAST = $1103;
  187. ICAP_CUSTHALFTONE = $1104;
  188. ICAP_EXPOSURETIME = $1105;
  189. ICAP_FILTER = $1106;
  190. ICAP_FLASHUSED = $1107;
  191. ICAP_GAMMA = $1108;
  192. ICAP_HALFTONES = $1109;
  193. ICAP_HIGHLIGHT = $110a;
  194. ICAP_IMAGEFILEFORMAT = $110c;
  195. ICAP_LAMPSTATE = $110d;
  196. ICAP_LIGHTSOURCE = $110e;
  197. ICAP_ORIENTATION = $1110;
  198. ICAP_PHYSICALWIDTH = $1111;
  199. ICAP_PHYSICALHEIGHT = $1112;
  200. ICAP_SHADOW = $1113;
  201. ICAP_FRAMES = $1114;
  202. ICAP_XNATIVERESOLUTION = $1116;
  203. ICAP_YNATIVERESOLUTION = $1117;
  204. ICAP_XRESOLUTION = $1118;
  205. ICAP_YRESOLUTION = $1119;
  206. ICAP_MAXFRAMES = $111a;
  207. ICAP_TILES = $111b;
  208. ICAP_BITORDER = $111c;
  209. ICAP_CCITTKFACTOR = $111d;
  210. ICAP_LIGHTPATH = $111e;
  211. ICAP_PIXELFLAVOR = $111f;
  212. ICAP_PLANARCHUNKY = $1120;
  213. ICAP_ROTATION = $1121;
  214. ICAP_SUPPORTEDSIZES = $1122;
  215. ICAP_THRESHOLD = $1123;
  216. ICAP_XSCALING = $1124;
  217. ICAP_YSCALING = $1125;
  218. ICAP_BITORDERCODES = $1126;
  219. ICAP_PIXELFLAVORCODES = $1127;
  220. ICAP_JPEGPIXELTYPE = $1128;
  221. ICAP_TIMEFILL = $112a;
  222. ICAP_BITDEPTH = $112b;
  223. ICAP_BITDEPTHREDUCTION = $112c; //Added 1.5
  224. //Return Codes and Condition Codes section
  225. // Return Codes: DSM_Entry and DS_Entry may return any one of these values.
  226. TWRC_CUSTOMBASE = $8000;
  227. TWRC_SUCCESS = 0;
  228. TWRC_FAILURE = 1; //App may get TW_STATUS for info on failure
  229. TWRC_CHECKSTATUS = 2; //"tried hard"; get status
  230. TWRC_CANCEL = 3;
  231. TWRC_DSEVENT = 4;
  232. TWRC_NOTDSEVENT = 5;
  233. TWRC_XFERDONE = 6;
  234. TWRC_ENDOFLIST = 7; //After MSG_GETNEXT if nothing left
  235. //Condition Codes: App gets these by doing DG_CONTROL DAT_STATUS MSG_GET.
  236. TWCC_CUSTOMBASE = $8000;
  237. TWCC_SUCCESS = 0; //It worked!
  238. TWCC_BUMMER = 1; //Failure due to unknown causes
  239. TWCC_LOWMEMORY = 2; //Not enough memory to perform operation
  240. TWCC_NODS = 3; //No Data Source
  241. TWCC_MAXCONNECTIONS = 4; //DS is connected to max possible apps
  242. TWCC_OPERATIONERROR = 5; //DS or DSM reported error, app shouldn't
  243. TWCC_BADCAP = 6; //Unknown capability
  244. TWCC_BADPROTOCOL = 9; //Unrecognized MSG DG DAT combination
  245. TWCC_BADVALUE = 10; //Data parameter out of range
  246. TWCC_SEQERROR = 11; //DG DAT MSG out of expected sequence
  247. TWCC_BADDEST = 12; //Unknown destination App/Src in DSM_Entry
  248. // ICAP_UNITS values (UN_ means UNits)
  249. TWUN_INCHES = 0;
  250. TWUN_CENTIMETERS = 1;
  251. TWUN_PICAS = 2;
  252. TWUN_POINTS = 3;
  253. TWUN_TWIPS = 4;
  254. TWUN_PIXELS = 5;
  255. // ICAP_PIXELTYPE values (PT_ means Pixel Type)
  256. TWPT_BW = 0;
  257. TWPT_GRAY = 1;
  258. TWPT_RGB = 2;
  259. TWPT_PALETTE = 3;
  260. TWPT_CMY = 4;
  261. TWPT_CMYK = 5;
  262. TWPT_YUV = 6;
  263. TWPT_YUVK = 7;
  264. TWPT_CIEXYZ = 8;
  265. // Flags used in TW_MEMORY structure.
  266. TWMF_APPOWNS = $01;
  267. TWMF_DSMOWNS = $02;
  268. TWMF_DSOWNS = $04;
  269. TWMF_POINTER = $08;
  270. TWMF_HANDLE = $10;
  271. // ICAP_PIXELFLAVOR values (PF_ means Pixel Flavor)
  272. TWPF_CHOCOLATE = 0; // zero pixel represents darkest shade
  273. TWPF_VANILLA = 1; // zero pixel represents lightest shade
  274. // ICAP_IMAGEFILEFORMAT values (FF_means File Format)
  275. TWFF_TIFF = 0; // Tagged Image File Format
  276. TWFF_PICT = 1; // Macintosh PICT
  277. TWFF_BMP = 2; // Windows Bitmap
  278. TWFF_XBM = 3; // X-Windows Bitmap
  279. TWFF_JFIF = 4; // JPEG File Interchange Format
  280. TWFF_FPX = 5; // Flash Pix
  281. TWFF_TIFFMULTI = 6; // Multi-page tiff file
  282. TWFF_PNG = 7;
  283. TWFF_SPIFF = 8;
  284. TWFF_EXIF = 9;
  285. TWSX_NATIVE = 0;
  286. TWSX_FILE = 1;
  287. TWSX_MEMORY = 2;
  288. type
  289. TW_HANDLE = Word;
  290. TW_MEMREF = pointer;
  291. // TW_HUGE = Longint;
  292. TW_STR32 = array[0..33] of Char;
  293. // TW_STR64 = Array [0..65] of Char;
  294. // TW_STR128 = Array [0..129] of Char;
  295. // TW_STR255 = Array [0..255] of Char;
  296. // TW_INT8 = ShortInt;
  297. TW_INT16 = Smallint;
  298. TW_INT32 = Longint;
  299. TW_UINT8 = Byte;
  300. TW_UINT16 = Word; // Unsinged integer !!!
  301. TW_UINT32 = Longword;
  302. TW_BOOL = Word; // Unsinged Short Boolean !!!
  303. pTW_UINT16 = ^TW_UINT16;
  304. TW_FIX32 = packed record // Fixed point structure type.
  305. Whole: TW_INT16; // maintains the sign
  306. Frac: TW_UINT16;
  307. end;
  308. pTW_FIX32 = ^TW_FIX32;
  309. TW_VERSION = packed record
  310. MajorNum: TW_UINT16; // Major revision number of the software.
  311. MinorNum: TW_UINT16; // Incremental revision number of the software.
  312. Language: TW_UINT16; // e.g. TWLG_SWISSFRENCH
  313. Country: TW_UINT16; // e.g. TWCY_SWITZERLAND
  314. Info: TW_STR32; // e.g. "1.0b3 Beta release"
  315. end;
  316. TW_IDENTITY = packed record
  317. Id: TW_UINT32; // Unique number. In Windows, app hWnd
  318. Version: TW_VERSION; // Identifies the piece of code
  319. ProtocolMajor: TW_UINT16; // App and DS must set to TWON_PROTOCOLMAJOR
  320. ProtocolMinor: TW_UINT16; // App and DS must set to TWON_PROTOCOLMINOR
  321. SupportedGroups: TW_UINT32; // Bit field OR combination of DG_ constants
  322. Manufacturer: TW_STR32; // Manufacturer name, e.g. "Hewlett-Packard"
  323. ProductFamily: TW_STR32; // Product family name, e.g. "ScanJet"
  324. ProductName: TW_STR32; // Product name, e.g. "ScanJet Plus"
  325. end;
  326. pTW_IDENTITY = ^TW_IDENTITY;
  327. TW_IMAGEINFO = packed record // DAT_IMAGEINFO. App gets detailed image info from DS with this.
  328. XResolution: TW_FIX32; // Resolution in the horizontal
  329. YResolution: TW_FIX32; // Resolution in the vertical
  330. ImageWidth: TW_INT32; // Columns in the image, -1 if unknown by DS
  331. ImageLength: TW_INT32; // Rows in the image, -1 if unknown by DS
  332. SamplesPerPixel: TW_INT16; // Number of samples per pixel, 3 for RGB
  333. BitsPerSample: array[0..7] of TW_INT16; // Number of bits for each sample
  334. BitsPerPixel: TW_INT16; // Number of bits for each padded pixel
  335. Planar: TW_BOOL; // True if Planar, False if chunky
  336. PixelType: TW_INT16; // How to interp data; photo interp (TWPT_)
  337. Compression: TW_UINT16; // How the data is compressed (TWCP_xxxx)
  338. end;
  339. pTW_IMAGEINFO = ^TW_IMAGEINFO;
  340. TW_ONEVALUE = packed record
  341. ItemType: TW_UINT16;
  342. Item: TW_UINT32;
  343. end;
  344. pTW_ONEVALUE = ^TW_ONEVALUE;
  345. TW_CAPABILITY = packed record //DAT_CAPABILITY. Used by app to get/set capability from/in a data source.
  346. Cap, ConType: TW_UINT16;
  347. hContainer: THandle;
  348. end;
  349. pTW_CAPABILITY = ^TW_CAPABILITY;
  350. TW_SETUPMEMXFER = packed record
  351. MinBufSize: TW_UINT32;
  352. MaxBufSize: TW_UINT32;
  353. Preferred: TW_UINT32;
  354. end;
  355. pTW_SETUPMEMXFER = ^TW_SETUPMEMXFER;
  356. TW_USERINTERFACE = packed record
  357. ShowUI: TW_BOOL; // TRUE if DS should bring up its UI
  358. ModalUI: TW_BOOL; // For Mac only - true if the DS's UI is modal
  359. hParent: TW_HANDLE; // For windows only - App window handle
  360. end;
  361. pTW_USERINTERFACE = ^TW_USERINTERFACE;
  362. TW_EVENT = packed record
  363. pEvent: TW_MEMREF; // Windows pMSG or Mac pEvent.
  364. TWMessage: TW_UINT16; // TW msg from data source, e.g. MSG_XFERREADY
  365. end;
  366. pTW_EVENT = ^TW_EVENT;
  367. TW_PENDINGXFERS = packed record
  368. Count: TW_UINT16; // Number of additional "images" pending.
  369. Reserved: TW_UINT32;
  370. end;
  371. pTW_PENDINGXFERS = ^TW_PENDINGXFERS;
  372. TW_ELEMENT8 = packed record
  373. Index: TW_UINT8; // Value used to index into the color table.
  374. Channel1: TW_UINT8; // First tri-stimulus value (e.g Red)
  375. Channel2: TW_UINT8; // Second tri-stimulus value (e.g Green)
  376. Channel3: TW_UINT8; // Third tri-stimulus value (e.g Blue)
  377. end;
  378. pTW_ELEMENT8 = ^TW_ELEMENT8;
  379. TW_PALETTE8 = packed record
  380. NumColors: TW_UINT16; // Number of colors in the color table.
  381. PaletteType: TW_UINT16; // TWPA_xxxx, specifies type of palette.
  382. Colors: array[0..255] of TW_ELEMENT8; // TWPA_xxxx, specifies type of palette.
  383. end;
  384. pTW_PALETTE8 = ^TW_PALETTE8;
  385. TW_MEMORY = packed record
  386. Flags: TW_UINT32; // Any combination of the TWMF_ constants.
  387. Length: TW_UINT32; // Number of bytes stored in buffer TheMem.
  388. TheMem: TW_MEMREF; // Pointer or handle to the allocated memory buffer.
  389. end;
  390. pTW_MEMORY = ^TW_MEMORY;
  391. TW_IMAGEMEMXFER = packed record
  392. Compression: TW_UINT16; // How the data is compressed
  393. BytesPerRow: TW_UINT32; // Number of bytes in a row of data
  394. Columns: TW_UINT32; // How many columns
  395. Rows: TW_UINT32; // How many rows
  396. XOffset: TW_UINT32; // How far from the side of the image
  397. YOffset: TW_UINT32; // How far from the top of the image
  398. BytesWritten: TW_UINT32; // How many bytes written in Memory
  399. Memory: TW_MEMORY; // Mem struct used to pass actual image data
  400. end;
  401. pTW_IMAGEMEMXFER = ^TW_IMAGEMEMXFER;
  402. TW_SETUPFILEXFER = packed record
  403. FileName: array[0..255] of Char;
  404. Format: TW_UINT16; // Any TWFF_ constant
  405. VRefNum: TW_INT16; // Used for Mac only
  406. end;
  407. pTW_SETUPFILEXFER = ^TW_SETUPFILEXFER;
  408. TW_ENUMERATION = packed record
  409. ItemType: TW_UINT16;
  410. NumItems: TW_UINT32; // How many items in ItemList
  411. CurrentIndex: TW_UINT32; // Current value is in ItemList[CurrentIndex]
  412. DefaultIndex: TW_UINT32; // Powerup value is in ItemList[DefaultIndex]
  413. ItemList: array[0..0] of TW_UINT8; // Array of ItemType values starts here
  414. end;
  415. pTW_ENUMERATION = ^TW_ENUMERATION;
  416. DSM_Entry = function(pOrigin: pTW_IDENTITY; pDest: pTW_IDENTITY; DG: TW_UINT32; DAT: TW_UINT16; MSG: TW_UINT16; pData: TW_MEMREF): TW_UINT16; stdcall;
  417. TOnTwMessage = procedure(Sender: TObject; Msg: string) of object;
  418. TOnCapture = procedure(Sender: TObject; bmp: TBitmap) of object;
  419. TOnFileNameNeeded = procedure(Sender: TObject; var FileName: string) of object;
  420. TtransferType = (doNativeTransfer, doFileTransfer, doMemTransfer);
  421. TCnTwain = class(TComponent)
  422. private
  423. FAppID: TW_IDENTITY;
  424. FdsID: TW_IDENTITY;
  425. twUI: TW_USERINTERFACE;
  426. FHandle: HWND;
  427. FIsDSMOpen: Boolean;
  428. FIsDSOpen: Boolean;
  429. FIsDSEnabled: Boolean;
  430. FTransferType: TTransferType;
  431. hDSMDLL: THandle;
  432. lpDSM_Entry: DSM_Entry;
  433. OldWndProc: TFarProc;
  434. NewWndProc: Pointer;
  435. FHooked: Boolean;
  436. FAutoFeed: Boolean;
  437. FOnTwMessage: TOnTwMessage;
  438. FOnCapture: TOnCapture;
  439. FOnFileNameNeeded: TOnFileNameNeeded;
  440. procedure HookWin;
  441. procedure UnHookWin;
  442. protected
  443. function SelectDS: TW_UINT16;
  444. procedure WndProc(var Message: TMessage);
  445. function ProcessTWMessage(var aMsg: TMessage; TwhWnd: THandle): Boolean;
  446. function OpenDSM: TW_UINT16; // DSM
  447. function CloseDSM: TW_UINT16;
  448. function OpenDS: TW_UINT16; // DS
  449. function CloseDS: TW_UINT16;
  450. function XferMechDS: TW_UINT16;
  451. function AutoFeedDS: TW_UINT16;
  452. function EnableDS(Show: Boolean): TW_UINT16; // UI
  453. function DisableDS: TW_UINT16;
  454. procedure TransferImage;
  455. procedure NativeTransfer;
  456. procedure FileTransfer;
  457. procedure MemoryTransfer;
  458. procedure DoXferDone(hDib: THandle);
  459. procedure DoTwMessage(Msg: string; TerminateDS: Boolean = True);
  460. public
  461. constructor Create(AOwner: TComponent); override;
  462. destructor Destroy; override;
  463. {* 连接并打开扫描仪 }
  464. function Acquire(Show: Boolean): TW_UINT16;
  465. {* 获取 Device 信息}
  466. function GetDSInfo(var DsID: TW_IDENTITY): TW_UINT16;
  467. {* 获取组件信息 }
  468. function GetComponentInfo(var DsID: TW_IDENTITY): TW_UINT16;
  469. {* 选择源,当计算机连接多个扫描仪时有效 }
  470. function SelectSource: TW_UINT16;
  471. {* 断开并关闭扫描仪 }
  472. procedure Terminate;
  473. {* 判断 DSM 服务是否开启 }
  474. property IsDSMOpen: Boolean read FIsDSMOpen;
  475. {* 判断 Device 是否开启 }
  476. property IsDSOpen: Boolean read FIsDSOpen;
  477. {* 判断 Device 是否可用 }
  478. property IsDSEnabled: Boolean read FIsDSEnabled;
  479. published
  480. {* 是否自动返回 }
  481. property AutoFeed: Boolean read FAutoFeed write FAutoFeed;
  482. {* 数据传送类型 }
  483. property TransferType: TtransferType read FTransferType write FTransferType;
  484. {* 捕获图像时触发事件 }
  485. property OnCaptrue: TOnCapture read FOnCapture write FOnCapture;
  486. {* 捕获错误信息时触发事件 }
  487. property OnErrorMessage: TOnTwMessage read FOnTwMessage write FOnTwMessage;
  488. {* 请求文件名时触发事件 }
  489. property OnFileNameNeeded: TOnFileNameNeeded read FOnFileNameNeeded write FOnFileNameNeeded;
  490. end;
  491. implementation
  492. function FIX32ToFloat(fix32: TW_FIX32): Double;
  493. begin
  494. Result := fix32.Whole + (fix32.Frac / 65536.0);
  495. end;
  496. function DibNumColors(pv: Pointer): Word;
  497. var
  498. Bits: integer;
  499. begin
  500. if pBITMAPINFOHEADER(pv)^.biSize <> sizeof(BITMAPCOREHEADER) then
  501. begin
  502. if pBITMAPINFOHEADER(pv)^.biClrUsed <> 0 then
  503. begin
  504. Result := pBITMAPINFOHEADER(pv)^.biClrUsed;
  505. Exit;
  506. end;
  507. Bits := pBITMAPINFOHEADER(pv)^.biBitCount;
  508. end
  509. else
  510. Bits := pBITMAPCOREHEADER(pv)^.bcBitCount;
  511. case Bits of
  512. 1:
  513. Result := 2;
  514. 4:
  515. Result := 16;
  516. 8:
  517. Result := 256;
  518. else
  519. Result := 0;
  520. end;
  521. end;
  522. function CreateBIPalette(lpbi: pBITMAPINFOHEADER): HPALETTE;
  523. var
  524. pRgb: pRGBQUAD;
  525. nNumColors: Word;
  526. hPal: HGLOBAL;
  527. pPal: pLOGPALETTE;
  528. i: integer;
  529. Red, Green, Blue: Byte;
  530. begin
  531. Result := 0;
  532. if lpbi = nil then
  533. Exit;
  534. if lpbi^.biSize <> sizeof(BITMAPINFOHEADER) then
  535. Exit;
  536. pRgb := pRGBQUAD(Longint(lpbi) + Word(lpbi^.biSize));
  537. nNumColors := DibNumColors(lpbi);
  538. if nNumColors <> 0 then
  539. begin
  540. hPal := GlobalAlloc(GPTR, sizeof(LOGPALETTE) + nNumColors * sizeof(PALETTEENTRY));
  541. pPal := GlobalLock(hPal);
  542. if pPal = nil then
  543. Exit;
  544. pPal^.palNumEntries := nNumColors;
  545. pPal^.palVersion := $0300;
  546. for i := 0 to nNumColors - 1 do
  547. begin
  548. pPal^.palPalEntry[i].peRed := pRGBQUAD(Longint(pRgb) + i)^.rgbRed;
  549. pPal^.palPalEntry[i].peGreen := pRGBQUAD(Longint(pRgb) + i)^.rgbGreen;
  550. pPal^.palPalEntry[i].peBlue := pRGBQUAD(Longint(pRgb) + i)^.rgbBlue;
  551. pPal^.palPalEntry[i].peFlags := 0;
  552. end;
  553. Result := CreatePalette(pPal^);
  554. GlobalUnlock(hPal);
  555. GlobalFree(hPal);
  556. end
  557. else if lpbi^.biBitCount = 24 then
  558. begin
  559. nNumColors := 256;
  560. hPal := GlobalAlloc(GPTR, sizeof(LOGPALETTE) + nNumColors * sizeof(PALETTEENTRY));
  561. pPal := GlobalLock(hPal);
  562. if pPal = nil then
  563. Exit;
  564. pPal^.palNumEntries := nNumColors;
  565. pPal^.palVersion := $0300;
  566. Red := 0;
  567. Green := 0;
  568. Blue := 0;
  569. for i := 0 to pPal^.palNumEntries - 1 do
  570. begin
  571. pPal^.palPalEntry[i].peRed := Red;
  572. pPal^.palPalEntry[i].peGreen := Green;
  573. pPal^.palPalEntry[i].peBlue := Blue;
  574. pPal^.palPalEntry[i].peFlags := 0;
  575. Inc(Red, 32);
  576. if Red = 0 then
  577. begin
  578. Inc(Green, 32);
  579. if Green = 0 then
  580. Inc(Blue, 64);
  581. end;
  582. end;
  583. Result := CreatePalette(pPal^);
  584. GlobalUnlock(hPal);
  585. GlobalFree(hPal);
  586. end;
  587. end;
  588. procedure FlipBitMap(hWindow, hBM: THandle; PixType: TW_INT16);
  589. var
  590. pDib: pByte;
  591. pbmi: pBITMAPINFO;
  592. bmpWidth, bmpHeight, Linelength: Longint;
  593. indexH, items, i: integer;
  594. SizeImage, ClrUsed, offset: DWord;
  595. BitCount: Word;
  596. temp: THandle;
  597. tempptr, tempptrsave, pbuffer: pByte;
  598. pixels: TW_UINT16;
  599. SaveRed, SaveBlue: Byte;
  600. begin
  601. pDib := GlobalLock(hBM);
  602. pbmi := pBITMAPINFO(pDib);
  603. bmpWidth := pbmi^.bmiHeader.biWidth;
  604. bmpHeight := pbmi^.bmiHeader.biHeight;
  605. SizeImage := pbmi^.bmiHeader.biSizeImage;
  606. BitCount := pbmi^.bmiHeader.biBitCount;
  607. ClrUsed := pbmi^.bmiHeader.biClrUsed;
  608. temp := GlobalAlloc(GHND, SizeImage);
  609. if temp <> 0 then
  610. begin
  611. tempptr := GlobalLock(temp);
  612. tempptrsave := tempptr;
  613. // calculate offset to start of the bitmap data
  614. offset := Sizeof(BITMAPINFOHEADER);
  615. Inc(offset, ClrUsed * sizeof(RGBQUAD));
  616. Linelength := (((bmpWidth * BitCount + 31) div 32) * 4);
  617. //Goto Last line in bitmap
  618. Inc(offset, Linelength * (bmpHeight - 1));
  619. Inc(pDib, offset); // pDib = pDib + offset - Linelength;
  620. Dec(pDib, Linelength);
  621. for indexH := 1 to bmpHeight - 1 do
  622. begin
  623. Move(pDib^, tempptr^, Linelength);
  624. Dec(pDib, Linelength);
  625. Inc(tempptr, Linelength);
  626. end;
  627. // Copy temp over hBM
  628. pbuffer := pByte(pbmi);
  629. Inc(pbuffer, Sizeof(BITMAPINFOHEADER));
  630. Inc(pbuffer, ClrUsed * Sizeof(RGBQUAD));
  631. Move(tempptrsave^, pbuffer^, SizeImage); // memcpy(pbuffer, tempptrsave, SizeImage);
  632. if PixType = TWPT_RGB then
  633. begin
  634. pbuffer := pByte(pbmi);
  635. Inc(pbuffer, sizeof(BITMAPINFOHEADER));
  636. Inc(pbuffer, ClrUsed * sizeof(RGBQUAD));
  637. pixels := pbmi^.bmiHeader.biWidth;
  638. for items := 0 to bmpHeight - 1 do
  639. begin
  640. tempptr := pbuffer;
  641. for i := 0 to pixels - 1 do
  642. begin
  643. //Switch Red byte and Blue byte
  644. SaveRed := Byte(tempptr^);
  645. SaveBlue := pByte(Longword(tempptr) + 2)^;
  646. tempptr^ := SaveBlue;
  647. pByte(Longword(tempptr) + 2)^ := SaveRed;
  648. Inc(tempptr, 3);
  649. end;
  650. Inc(pbuffer, Linelength);
  651. end;
  652. end;
  653. GlobalUnlock(hBM);
  654. GlobalUnlock(temp);
  655. GlobalFree(temp);
  656. end
  657. else
  658. begin
  659. GlobalUnlock(hBM);
  660. // DoTwMessage('Could not allocate enough memory to flip image', False);
  661. end;
  662. end;
  663. constructor TCnTwain.Create(AOwner: TComponent);
  664. begin
  665. inherited Create(AOwner);
  666. FHooked := False;
  667. with AOwner as TWinControl do
  668. FHandle := Handle;
  669. // Init ApplicationIdentity.
  670. FAppID.Id := 0; // Source Manager will assign real value
  671. with FAppID.Version do
  672. begin
  673. MajorNum := APP_PROTOCOLMAJOR;
  674. MinorNum := APP_PROTOCOLMINOR;
  675. Language := TWLG_CHINESE_SIMPLIFIED; // TWLG_ENG;
  676. Country := TWCY_CHINA;
  677. strcopy(Info, 'RaTwain 扫描仪控件');
  678. end;
  679. FAppID.ProtocolMajor := TWON_PROTOCOLMAJOR;
  680. FAppID.ProtocolMinor := TWON_PROTOCOLMINOR;
  681. FAppID.SupportedGroups := DG_IMAGE_OR_CONTROL;
  682. strcopy(FAppID.Manufacturer, '上海维普软件工作室');
  683. strcopy(FAppID.ProductFamily, 'Delphi7专用扫描仪控件');
  684. strcopy(FAppID.ProductName, '扫描仪控件');
  685. FillChar(FDsID, Sizeof(TW_IDENTITY), 0);
  686. FTransferType := doNativeTransfer;
  687. hDSMDLL := 0;
  688. lpDSM_Entry := nil;
  689. FHooked := False;
  690. FAutoFeed := False;
  691. FIsDSMOpen := False;
  692. FIsDSOpen := False;
  693. FIsDSEnabled := False;
  694. end;
  695. destructor TCnTwain.Destroy;
  696. begin
  697. Terminate;
  698. inherited Destroy;
  699. end;
  700. procedure TCnTwain.HookWin;
  701. begin
  702. OldWndProc := TFarProc(GetWindowLong(FHandle, GWL_WNDPROC));
  703. NewWndProc := MakeObjectInstance(WndProc);
  704. SetWindowLong(FHandle, GWL_WNDPROC, LongInt(NewWndProc));
  705. FHooked := True;
  706. end;
  707. procedure TCnTwain.UnHookWin;
  708. begin
  709. if not fHooked then
  710. exit;
  711. SetWindowLong(FHandle, GWL_WNDPROC, LongInt(OldWndProc));
  712. if AsSigned(NewWndProc) then
  713. FreeObjectInstance(NewWndProc);
  714. NewWndProc := nil;
  715. FHooked := False;
  716. end;
  717. procedure TCnTwain.WndProc(var Message: TMessage);
  718. begin
  719. if not IsDSOpen or not ProcessTWMessage(Message, FHandle) then
  720. begin
  721. // if Message.Msg = PM_XFERDONE then ;
  722. Message.Result := CallWindowProc(OldWndProc, FHandle, Message.Msg, Message.wParam, Message.lParam);
  723. end;
  724. end;
  725. function TCnTwain.ProcessTWMessage(var aMsg: TMessage; TwhWnd: THandle): Boolean;
  726. var
  727. twRC: TW_UINT16;
  728. twEv: TW_EVENT;
  729. theMsg: TMsg;
  730. begin // Here Something delicacy that MSG of C++ and TMessage of Delphi are not Same.
  731. twRC := TWRC_NOTDSEVENT;
  732. if IsDSOpen then
  733. begin
  734. FillChar(twEv, Sizeof(TW_EVENT), #0);
  735. FillChar(theMsg, Sizeof(TMsg), #0);
  736. theMsg.hwnd := TwhWnd;
  737. theMsg.message := aMsg.Msg;
  738. theMsg.wParam := aMsg.WParam;
  739. theMsg.lParam := aMsg.LParam;
  740. twEv.pEvent := @theMsg;
  741. twRC := lpDSM_Entry(@FappID, @FdsID, DG_CONTROL, DAT_EVENT, MSG_PROCESSEVENT, @twEv);
  742. aMsg.Msg := theMsg.message;
  743. aMsg.WParam := theMsg.wParam;
  744. aMsg.LParam := theMsg.lParam;
  745. aMsg.Result := twRC;
  746. case twEv.TWMessage of
  747. MSG_XFERREADY:
  748. TransferImage;
  749. MSG_CLOSEDSREQ, MSG_CLOSEDSOK:
  750. Terminate;
  751. end;
  752. end;
  753. Result := twRC = TWRC_DSEVENT;
  754. end;
  755. procedure TCnTwain.TransferImage;
  756. begin
  757. case FTransferType of
  758. doNativeTransfer:
  759. NativeTransfer;
  760. doFileTransfer:
  761. FileTransfer;
  762. doMemTransfer:
  763. MemoryTransfer;
  764. end;
  765. //
  766. end;
  767. procedure TCnTwain.NativeTransfer;
  768. var
  769. twPendingXfer: TW_PENDINGXFERS;
  770. twRC, twRC2: TW_UINT16;
  771. hBitMap: TW_UINT32;
  772. hbm_acq: THandle;
  773. begin
  774. hBitMap := 0;
  775. FillChar(twPendingXfer, sizeof(TW_PENDINGXFERS), #0);
  776. repeat
  777. twRC := lpDSM_Entry(@FappID, @FdsID, DG_IMAGE, DAT_IMAGENATIVEXFER, MSG_GET, @hBitMap);
  778. case twRC of
  779. TWRC_XFERDONE:
  780. begin
  781. hbm_acq := hBitMap;
  782. twRC2 := lpDSM_Entry(@FappID, @FdsID, DG_CONTROL, DAT_PENDINGXFERS, MSG_ENDXFER, @twPendingXfer);
  783. if twRC2 <> TWRC_SUCCESS then
  784. DoTwMessage('DG_CONTROL/DAT_PENDINGXFERS/MSG_ENDXFER', False);
  785. if twPendingXfer.Count = 0 then
  786. if (hbm_acq <> 0) and (GlobalLock(hbm_acq) <> nil) then
  787. begin
  788. Terminate;
  789. GlobalUnlock(hbm_acq);
  790. end;
  791. if hbm_acq > VALID_HANDLE then
  792. begin
  793. DoXferDone(hbm_acq);
  794. GlobalFree(hbm_acq);
  795. end
  796. else
  797. DoXferDone(0);
  798. end;
  799. TWRC_CANCEL:
  800. begin
  801. // DoTwMessage('User Cancel. (DG_IMAGE/DAT_IMAGENATIVEXFER/MSG_GET)', False);
  802. twRC2 := lpDSM_Entry(@FappID, @FdsID, DG_CONTROL, DAT_PENDINGXFERS, MSG_ENDXFER, @twPendingXfer);
  803. if twRC2 <> TWRC_SUCCESS then
  804. DoTwMessage('DG_CONTROL/DAT_PENDINGXFERS/MSG_ENDXFER', False);
  805. if twPendingXfer.Count = 0 then
  806. Terminate;
  807. DoXferDone(0);
  808. end;
  809. else
  810. twRC2 := lpDSM_Entry(@FappID, @FdsID, DG_CONTROL, DAT_PENDINGXFERS, MSG_ENDXFER, @twPendingXfer);
  811. if twRC2 <> TWRC_SUCCESS then
  812. DoTwMessage('DG_CONTROL/DAT_PENDINGXFERS/MSG_ENDXFER', False);
  813. if twPendingXfer.Count = 0 then
  814. Terminate;
  815. DoXferDone(0);
  816. end;
  817. until twPendingXfer.count = 0;
  818. end;
  819. procedure TCnTwain.FileTransfer;
  820. var
  821. twPendingXfer: TW_PENDINGXFERS;
  822. SetupMsgGet, setup: TW_SETUPFILEXFER;
  823. ofs: OFSTRUCT;
  824. hF: THandle;
  825. twRC, twRC2: TW_UINT16;
  826. hbm_acq: THandle;
  827. header: BITMAPFILEHEADER;
  828. dwSize: DWord;
  829. ptr: PChar;
  830. count: TW_UINT32;
  831. num: TW_UINT16;
  832. FFileName: string;
  833. begin
  834. FillChar(twPendingXfer, sizeof(TW_PENDINGXFERS), #0);
  835. FillChar(SetupMsgGet, sizeof(TW_SETUPFILEXFER), #0);
  836. FillChar(setup, sizeof(TW_SETUPFILEXFER), #0);
  837. FillChar(ofs, sizeof(OFSTRUCT), #0);
  838. repeat
  839. FFileName := '';
  840. if Assigned(FOnFileNameNeeded) then
  841. FOnFileNameNeeded(Self, FFileName);
  842. if FFileName <> '' then
  843. StrPCopy(setup.FileName, FFileName)
  844. else
  845. begin
  846. lpDSM_Entry(@FappID, @FdsID, DG_CONTROL, DAT_SETUPFILEXFER, MSG_GET, @SetupMsgGet);
  847. StrCopy(setup.FileName, SetupMsgGet.FileName);
  848. end;
  849. setup.Format := TWFF_BMP;
  850. setup.VRefNum := 0;
  851. hF := OpenFile(PAnsiChar({$IFDEF UNICODE}AnsiString{$ELSE}string{$ENDIF}(setup.Filename)), ofs, OF_CREATE);
  852. if hF = HFILE_ERROR then
  853. begin
  854. DoTwMessage('Unable to create file for file transfer', False);
  855. twRC := TWRC_FAILURE;
  856. end
  857. else
  858. begin
  859. _lclose(hF);
  860. twRC := lpDSM_Entry(@FappID, @FdsID, DG_CONTROL, DAT_SETUPFILEXFER, MSG_SET, @setup);
  861. if twRC <> TWRC_SUCCESS then
  862. DoTwMessage('DG_CONTROL/DAT_SETUPFILEXFER/MSG_SET', False)
  863. else
  864. twRC := lpDSM_Entry(@FappID, @FdsID, DG_IMAGE, DAT_IMAGEFILEXFER, MSG_GET, nil);
  865. case twRC of
  866. TWRC_XFERDONE:
  867. begin
  868. FillChar(ofs, sizeof(OFSTRUCT), #0);
  869. FillChar(header, sizeof(BITMAPFILEHEADER), #0);
  870. hF := OpenFile(PAnsiChar({$IFDEF UNICODE}AnsiString{$ELSE}string{$ENDIF}(setup.FileName)), ofs, OF_READ);
  871. hbm_acq := 0;
  872. if hF <> Longword(-1) then
  873. begin
  874. num := $8000;
  875. dwSize := GetFileSize(hF, nil);
  876. _lread(hF, @header, sizeof(BITMAPFILEHEADER));
  877. Dec(dwSize, sizeof(BITMAPFILEHEADER));
  878. if header.bfSize = 0 then
  879. header.bfSize := dwSize;
  880. hbm_acq := GlobalAlloc(GHND, header.bfSize);
  881. if hbm_acq <> 0 then
  882. begin
  883. ptr := GlobalLock(hbm_acq);
  884. //for count:=(header.bfSize-sizeof(BITMAPFILEHEADER)) downto count; count-=num, ptr+=num)
  885. count := header.bfSize - sizeof(BITMAPFILEHEADER);
  886. while count > 0 do
  887. begin
  888. if count < num then
  889. num := count;
  890. _lread(hF, ptr, num);
  891. Dec(count, num);
  892. Inc(ptr, num);
  893. end;
  894. GlobalUnlock(hbm_acq);
  895. GlobalFree(hbm_acq);
  896. end;
  897. _lclose(hF);
  898. end;
  899. twRC2 := lpDSM_Entry(@FappID, @FdsID, DG_CONTROL, DAT_PENDINGXFERS, MSG_ENDXFER, @twPendingXfer);
  900. if twRC2 <> TWRC_SUCCESS then
  901. DoTwMessage('DG_CONTROL / DAT_PENDINGXFERS / MSG_ENDXFER', False);
  902. if twPendingXfer.Count = 0 then
  903. Terminate;
  904. DoXferDone(hbm_acq);
  905. end;
  906. TWRC_CANCEL:
  907. begin
  908. // DoTwMessage('User Cancel. (DG_IMAGE/DAT_IMAGENATIVEXFER/MSG_GET)', False);
  909. twRC2 := lpDSM_Entry(@FappID, @FdsID, DG_CONTROL, DAT_PENDINGXFERS, MSG_ENDXFER, @twPendingXfer);
  910. if twRC2 <> TWRC_SUCCESS then
  911. DoTwMessage('DG_CONTROL/DAT_PENDINGXFERS/MSG_ENDXFER', False);
  912. if twPendingXfer.Count = 0 then
  913. Terminate;
  914. DoXferDone(0);
  915. end;
  916. else
  917. twRC2 := lpDSM_Entry(@FappID, @FdsID, DG_CONTROL, DAT_PENDINGXFERS, MSG_ENDXFER, @twPendingXfer);
  918. if twRC2 <> TWRC_SUCCESS then
  919. DoTwMessage('DG_CONTROL/DAT_PENDINGXFERS/MSG_ENDXFER', False);
  920. if twPendingXfer.Count = 0 then
  921. Terminate;
  922. DoXferDone(0);
  923. end;
  924. end;
  925. until((twPendingXfer.Count = 0) or (twRC = TWRC_FAILURE));
  926. end;
  927. procedure TCnTwain.MemoryTransfer;
  928. var
  929. twPendingXfer: TW_PENDINGXFERS;
  930. info: TW_IMAGEINFO;
  931. twRC, twRC2: TW_UINT16;
  932. size: TW_UINT32;
  933. setup: TW_SETUPMEMXFER;
  934. blocks, index: integer;
  935. hbm_acq: THandle;
  936. pdib: pBITMAPINFO;
  937. cap: TW_CAPABILITY;
  938. pOneV: pTW_ONEVALUE;
  939. Units, PixelFlavor: TW_UINT16;
  940. XRes, YRes: Double;
  941. pal: TW_PALETTE8;
  942. ptr: PByte;
  943. xfer: TW_IMAGEMEMXFER;
  944. begin
  945. FillChar(twPendingXfer, sizeof(TW_PENDINGXFERS), #0);
  946. FillChar(info, sizeof(TW_IMAGEINFO), #0);
  947. FillChar(setup, sizeof(TW_SETUPMEMXFER), #0);
  948. FillChar(pal, sizeof(TW_PALETTE8), #0);
  949. FillChar(xfer, sizeof(TW_IMAGEMEMXFER), #0);
  950. repeat
  951. twRC := lpDSM_Entry(@FappID, @FdsID, DG_IMAGE, DAT_IMAGEINFO, MSG_GET, @info);
  952. if twRC <> TWRC_SUCCESS then
  953. DoTwMessage('DG_IMAGE/DAT_IMAGEINFO/MSG_GET', False)
  954. else
  955. begin
  956. size := (((info.ImageWidth * info.BitsPerPixel + 31) div 8) * info.ImageLength);
  957. lpDSM_Entry(@FappID, @FdsID, DG_CONTROL, DAT_SETUPMEMXFER, MSG_GET, @setup);
  958. blocks := size div setup.Preferred;
  959. size := (TW_UINT32(blocks) + 1) * setup.Preferred;
  960. hbm_acq := GlobalAlloc(GHND, size + sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD));
  961. if hbm_acq = 0 then
  962. DoTwMessage('GlobalAlloc Failed in DoMemTransfer', False)
  963. else
  964. begin
  965. pdib := GlobalLock(hbm_acq);
  966. // fill in the image information
  967. pdib^.bmiHeader.biSize := sizeof(BITMAPINFOHEADER);
  968. pdib^.bmiHeader.biWidth := info.ImageWidth;
  969. pdib^.bmiHeader.biHeight := info.ImageLength;
  970. // Only 1 is supported
  971. pdib^.bmiHeader.biPlanes := 1;
  972. pdib^.bmiHeader.biBitCount := info.BitsPerPixel;
  973. // This application does not support compression
  974. pdib^.bmiHeader.biCompression := BI_RGB;
  975. pdib^.bmiHeader.biSizeImage := size;
  976. // Get Units and calculate PelsPerMeter
  977. cap.Cap := ICAP_UNITS;
  978. cap.ConType := TW_UINT16(TWON_DONTCARE16);
  979. cap.hContainer := 0;
  980. twRC := lpDSM_Entry(@FappID, @FdsID, DG_CONTROL, DAT_CAPABILITY, MSG_GETCURRENT, @cap);
  981. if twRC <> TWRC_SUCCESS then
  982. begin
  983. // raise ETwainError.Create('DG_CONTROL/DAT_CAPABILITY/MSG_GETCURRENT');
  984. pdib^.bmiHeader.biXPelsPerMeter := 0;
  985. pdib^.bmiHeader.biYPelsPerMeter := 0;
  986. end
  987. else
  988. begin
  989. pOneV := GlobalLock(cap.hContainer);
  990. Units := pOneV^.Item;
  991. GlobalUnlock(cap.hContainer);
  992. GlobalFree(cap.hContainer);
  993. XRes := FIX32ToFloat(info.XResolution);
  994. YRes := FIX32ToFloat(info.YResolution);
  995. case Units of
  996. TWUN_INCHES:
  997. begin
  998. pdib^.bmiHeader.biXPelsPerMeter := Trunc((XRes * 2.54) * 100);
  999. pdib^.bmiHeader.biYPelsPerMeter := Trunc((YRes * 2.54) * 100);
  1000. end;
  1001. TWUN_CENTIMETERS:
  1002. begin
  1003. pdib^.bmiHeader.biXPelsPerMeter := Trunc(XRes * 100);
  1004. pdib^.bmiHeader.biYPelsPerMeter := Trunc(YRes * 100);
  1005. end;
  1006. else
  1007. begin
  1008. pdib^.bmiHeader.biXPelsPerMeter := 0;
  1009. pdib^.bmiHeader.biYPelsPerMeter := 0;
  1010. end;
  1011. end;
  1012. case info.PixelType of
  1013. TWPT_BW:
  1014. begin
  1015. pdib^.bmiHeader.biClrUsed := 2;
  1016. pdib^.bmiHeader.biClrImportant := 0;
  1017. cap.Cap := ICAP_PIXELFLAVOR;
  1018. cap.ConType := TW_UINT16(TWON_DONTCARE16);
  1019. cap.hContainer := 0;
  1020. twRC := lpDSM_Entry(@FappID, @FdsID, DG_CONTROL, DAT_CAPABILITY, MSG_GETCURRENT, @cap);
  1021. if twRC <> TWRC_SUCCESS then
  1022. PixelFlavor := TWPF_CHOCOLATE
  1023. else
  1024. begin
  1025. if cap.ConType <> TWON_ONEVALUE then
  1026. PixelFlavor := TWPF_CHOCOLATE
  1027. else
  1028. begin
  1029. pOneV := GlobalLock(cap.hContainer);
  1030. PixelFlavor := TW_UINT16(pOneV^.Item);
  1031. GlobalUnlock(cap.hContainer);
  1032. end;
  1033. GlobalFree(cap.hContainer);
  1034. end;
  1035. if PixelFlavor = 0 then
  1036. begin
  1037. pdib^.bmiColors[0].rgbRed := 0;
  1038. pdib^.bmiColors[0].rgbGreen := 0;
  1039. pdib^.bmiColors[0].rgbBlue := 0;
  1040. pdib^.bmiColors[0].rgbReserved := 0;
  1041. index := 1;
  1042. pdib^.bmiColors[index].rgbRed := $00FF;
  1043. pdib^.bmiColors[index].rgbGreen := $00FF;
  1044. pdib^.bmiColors[index].rgbBlue := $00FF;
  1045. pdib^.bmiColors[index].rgbReserved := 0;
  1046. end
  1047. else
  1048. begin
  1049. pdib^.bmiColors[0].rgbRed := $00FF;
  1050. pdib^.bmiColors[0].rgbGreen := $00FF;
  1051. pdib^.bmiColors[0].rgbBlue := $00FF;
  1052. pdib^.bmiColors[0].rgbReserved := 0;
  1053. index := 1;
  1054. pdib^.bmiColors[index].rgbRed := 0;
  1055. pdib^.bmiColors[index].rgbGreen := 0;
  1056. pdib^.bmiColors[index].rgbBlue := 0;
  1057. pdib^.bmiColors[index].rgbReserved := 0;
  1058. end;
  1059. end;
  1060. TWPT_GRAY:
  1061. begin
  1062. pdib^.bmiHeader.biClrUsed := 256;
  1063. for index := 0 to 255 do
  1064. begin
  1065. pdib^.bmiColors[index].rgbRed := BYTE(index);
  1066. pdib^.bmiColors[index].rgbGreen := BYTE(index);
  1067. pdib^.bmiColors[index].rgbBlue := BYTE(index);
  1068. pdib^.bmiColors[index].rgbReserved := 0;
  1069. end;
  1070. end;
  1071. TWPT_RGB:
  1072. pdib^.bmiHeader.biClrUsed := 0;
  1073. else
  1074. twRC := lpDSM_Entry(@FappID, @FdsID, DG_IMAGE, DAT_PALETTE8, MSG_GET, @pal);
  1075. if twRC <> TWRC_SUCCESS then
  1076. begin
  1077. // raise ETwainError.Create('DG_IMAGE/DAT_PALETTE8/MSG_GET -- defaulting to 256 gray image palette');
  1078. pdib^.bmiHeader.biClrImportant := 0;
  1079. pdib^.bmiHeader.biClrUsed := 256;
  1080. for index := 0 to pal.NumColors - 1 do
  1081. begin
  1082. pdib^.bmiColors[index].rgbRed := BYTE(index);
  1083. pdib^.bmiColors[index].rgbGreen := BYTE(index);
  1084. pdib^.bmiColors[index].rgbBlue := BYTE(index);
  1085. pdib^.bmiColors[index].rgbReserved := 0;
  1086. end;
  1087. end
  1088. else
  1089. begin
  1090. pdib^.bmiHeader.biClrImportant := 0;
  1091. pdib^.bmiHeader.biClrUsed := pal.NumColors;
  1092. for index := 0 to pal.NumColors - 1 do
  1093. begin
  1094. pdib^.bmiColors[index].rgbRed := pal.Colors[index].Channel1;
  1095. pdib^.bmiColors[index].rgbGreen := pal.Colors[index].Channel2;
  1096. pdib^.bmiColors[index].rgbBlue := pal.Colors[index].Channel3;
  1097. pdib^.bmiColors[index].rgbReserved := 0;
  1098. end;
  1099. end;
  1100. end;
  1101. ptr := PByte(pdib);
  1102. Inc(ptr, sizeof(BITMAPINFOHEADER));
  1103. Inc(ptr, pdib^.bmiHeader.biClrUsed * sizeof(RGBQUAD));
  1104. twRC := lpDSM_Entry(@FappID, @FdsID, DG_CONTROL, DAT_SETUPMEMXFER, MSG_GET, @setup);
  1105. if twRC <> TWRC_SUCCESS then
  1106. DoTwMessage('DG_CONTROL/DAT_SETUPMEMXFER/MSG_GET', False)
  1107. else
  1108. begin
  1109. // we will use a pointer to shared memory
  1110. xfer.Memory.Flags := TWMF_APPOWNS or TWMF_POINTER;
  1111. xfer.Memory.Length := setup.Preferred;
  1112. xfer.Memory.TheMem := ptr;
  1113. // transfer the data -- loop until done or canceled
  1114. repeat
  1115. twRC := lpDSM_Entry(@FappID, @FdsID, DG_IMAGE, DAT_IMAGEMEMXFER, MSG_GET, @xfer);
  1116. case twRC of
  1117. TWRC_SUCCESS:
  1118. begin
  1119. Inc(ptr, xfer.BytesWritten);
  1120. xfer.Memory.TheMem := ptr;
  1121. end;
  1122. TWRC_XFERDONE:
  1123. begin
  1124. GlobalUnlock(hbm_acq);
  1125. FlipBitMap(FHandle, hbm_acq, info.PixelType);
  1126. twRC2 := lpDSM_Entry(@FappID, @FdsID, DG_CONTROL, DAT_PENDINGXFERS, MSG_ENDXFER, @twPendingXfer);
  1127. if twRC2 <> TWRC_SUCCESS then
  1128. DoTwMessage('DG_CONTROL / DAT_PENDINGXFERS / MSG_ENDXFER', False);
  1129. if twPendingXfer.Count = 0 then
  1130. Terminate;
  1131. DoXferDone(hbm_acq);
  1132. GlobalFree(hbm_acq);
  1133. end;
  1134. TWRC_CANCEL:
  1135. begin
  1136. // DoTwMessage('User Cancel. (DG_IMAGE/DAT_IMAGENATIVEXFER/MSG_GET)', False);
  1137. twRC2 := lpDSM_Entry(@FappID, @FdsID, DG_CONTROL, DAT_PENDINGXFERS, MSG_ENDXFER, @twPendingXfer);
  1138. if twRC2 <> TWRC_SUCCESS then
  1139. DoTwMessage('DG_CONTROL / DAT_PENDINGXFERS / MSG_ENDXFER', False);
  1140. GlobalUnlock(hbm_acq);
  1141. GlobalFree(hbm_acq);
  1142. if twPendingXfer.Count = 0 then
  1143. Terminate;
  1144. DoXferDone(0);
  1145. end;
  1146. else
  1147. twRC2 := lpDSM_Entry(@FappID, @FdsID, DG_CONTROL, DAT_PENDINGXFERS, MSG_ENDXFER, @twPendingXfer);
  1148. if twRC2 <> TWRC_SUCCESS then
  1149. DoTwMessage('DG_CONTROL / DAT_PENDINGXFERS / MSG_ENDXFER', False);
  1150. GlobalUnlock(hbm_acq);
  1151. GlobalFree(hbm_acq);
  1152. if twPendingXfer.Count = 0 then
  1153. Terminate;
  1154. DoXferDone(0);
  1155. end;
  1156. until(twRC <> TWRC_SUCCESS);
  1157. end; // if twRC <> TWRC_SUCCESS then DoTwMessage('DG_CONTROL/DAT_SETUPMEMXFER/MSG_GET', False) else begin
  1158. end;
  1159. end; // hbm_acq = 0
  1160. end; // twRC <> TWRC_SUCCESS
  1161. until twPendingXfer.count = 0;
  1162. end;
  1163. procedure TCnTwain.DoXferDone(hDib: THandle);
  1164. var
  1165. lpDib, lpBi: PBITMAPINFOHEADER;
  1166. lpBits: Pointer;
  1167. dwColorTableSize: TW_UINT32;
  1168. hBitMap: TW_UINT32;
  1169. hDibPal: THandle;
  1170. DC: HDC;
  1171. bmp: TBitmap;
  1172. begin
  1173. if not Assigned(FOnCapture) then
  1174. Exit;
  1175. if hDib = 0 then
  1176. begin
  1177. FOnCapture(Self, nil);
  1178. Exit;
  1179. end;
  1180. lpDib := GlobalLock(hDib);
  1181. if lpDib = nil then
  1182. begin
  1183. DoTwMessage('Could Not Lock Bitmap Memory.', False);
  1184. Exit;
  1185. end;
  1186. lpBi := lpDib;
  1187. dwColorTableSize := DibNumColors(lpDib) * sizeof(RGBQUAD);
  1188. lpBits := lpDib;
  1189. Inc(pByte(lpBits), lpBi^.biSize + dwColorTableSize);
  1190. DC := GetDC(FHandle);
  1191. hDibPal := CreateBIPalette(lpBi);
  1192. if hDibPal <> 0 then
  1193. begin
  1194. SelectPalette(DC, hDibPal, False);
  1195. RealizePalette(DC);
  1196. end;
  1197. if lpDib^.biBitCount = 1 then
  1198. begin
  1199. hBitMap := CreateBitmap(lpDib^.biWidth, lpDib^.biHeight, 1, 1, lpBits);
  1200. if hBitMap <> 0 then
  1201. SetDIBits(DC, hBitMap, 0, lpDib^.biHeight, lpBits, pBITMAPINFO(lpDib)^, DIB_RGB_COLORS);
  1202. end
  1203. else
  1204. hBitMap := CreateDIBitmap(DC, lpDib^, CBM_INIT, lpBits, pBITMAPINFO(lpDib)^, DIB_RGB_COLORS);
  1205. GlobalUnlock(hDib);
  1206. ReleaseDC(FHandle, DC);
  1207. bmp := TBitmap.Create;
  1208. bmp.Handle := hBitMap;
  1209. FOnCapture(Self, bmp);
  1210. bmp.Free;
  1211. end;
  1212. procedure TCnTwain.DoTwMessage(Msg: string; TerminateDS: Boolean = True);
  1213. begin
  1214. if TerminateDS then
  1215. Terminate;
  1216. if Assigned(FOnTwMessage) then
  1217. FOnTwMessage(Self, Msg);
  1218. end;
  1219. function TCnTwain.OpenDSM: TW_UINT16;
  1220. begin
  1221. Result := TWRC_FAILURE;
  1222. if IsDSMOpen then
  1223. Exit;
  1224. hDSMDLL := LoadLibrary('TWAIN_32.DLL');
  1225. if hDSMDLL <> 0 then
  1226. @lpDSM_Entry := GetProcAddress(hDSMDLL, 'DSM_Entry');
  1227. if (hDSMDLL = 0) or (@lpDSM_Entry = nil) then
  1228. DoTwMessage('Error in Open, LoadLibrary, or GetProcAddress.');
  1229. Result := lpDSM_Entry(@FAppID, nil, DG_CONTROL, DAT_PARENT, MSG_OPENDSM, @FHandle);
  1230. if Result = TWRC_SUCCESS then
  1231. FIsDSMOpen := True
  1232. else
  1233. DoTwMessage('Error Open DSM. (DG_CONTROL/DAT_PARENT/MSG_OPENDSM)');
  1234. end;
  1235. function TCnTwain.CloseDSM: TW_UINT16;
  1236. begin
  1237. Result := TWRC_FAILURE;
  1238. if IsDSMOpen then
  1239. begin
  1240. Result := lpDSM_Entry(@FAppID, nil, DG_CONTROL, DAT_PARENT, MSG_CLOSEDSM, @FHandle);
  1241. if hDSMDLL <> 0 then
  1242. begin
  1243. FreeLibrary(hDSMDLL);
  1244. hDSMDLL := 0;
  1245. end;
  1246. if Result <> TWRC_SUCCESS then
  1247. DoTwMessage('Error Close DSM. (DG_CONTROL/DAT_PARENT/MSG_CLOSEDSM)');
  1248. FdsID.Id := 0;
  1249. end;
  1250. FIsDSMOpen := False;
  1251. end;
  1252. function TCnTwain.OpenDS: TW_UINT16;
  1253. begin
  1254. Result := TWRC_FAILURE;
  1255. if IsDSMOpen then
  1256. if not IsDSOpen then
  1257. begin
  1258. Result := lpDSM_Entry(@FAppID, nil, DG_CONTROL, DAT_IDENTITY, MSG_OPENDS, @FdsID);
  1259. if Result = TWRC_SUCCESS then
  1260. begin
  1261. FIsDSOpen := True;
  1262. HookWin;
  1263. end
  1264. else
  1265. DoTwMessage('Error Open DS. (DG_CONTROL/DAT_IDENTITY/MSG_OPENDS)');
  1266. end
  1267. else
  1268. DoTwMessage('Can not Open DS while It is Openning')
  1269. else
  1270. DoTwMessage('Can not Open DS while DSM not Openning');
  1271. end;
  1272. function TCnTwain.CloseDS: TW_UINT16;
  1273. begin
  1274. Result := TWRC_FAILURE;
  1275. if IsDSOpen then
  1276. if not IsDSEnabled then
  1277. begin
  1278. Result := lpDSM_Entry(@FAppID, nil, DG_CONTROL, DAT_IDENTITY, MSG_CLOSEDS, @FdsID);
  1279. if Result = TWRC_SUCCESS then
  1280. begin
  1281. FIsDSOpen := False;
  1282. UnHookWin;
  1283. end
  1284. else
  1285. DoTwMessage('Error Close DS. (DG_CONTROL/DAT_IDENTITY/MSG_CLOSEDS)');
  1286. FillChar(FdsID, Sizeof(TW_IDENTITY), #0);
  1287. end
  1288. else
  1289. DoTwMessage('Can not Close DS while DS is Enabled');
  1290. FIsDSOpen := False;
  1291. end;
  1292. function TCnTwain.XferMechDS: TW_UINT16;
  1293. var
  1294. cap: TW_CAPABILITY;
  1295. pval: pTW_ONEVALUE;
  1296. begin
  1297. Result := TWRC_FAILURE;
  1298. cap.Cap := ICAP_XFERMECH;
  1299. cap.ConType := TWON_ONEVALUE;
  1300. cap.hContainer := GlobalAlloc(GHND, Sizeof(TW_ONEVALUE));
  1301. if cap.hContainer = 0 then
  1302. begin
  1303. DoTwMessage('Memory Allocation Failed. (MSG_SET/ICAP_XFERMECH)');
  1304. Exit;
  1305. end;
  1306. pval := GlobalLock(cap.hContainer);
  1307. pval^.ItemType := TWTY_UINT16;
  1308. case FTransferType of
  1309. doNativeTransfer:
  1310. pval^.Item := TWSX_NATIVE;
  1311. doFileTransfer:
  1312. pval^.Item := TWSX_FILE;
  1313. doMemTransfer:
  1314. pval^.Item := TWSX_MEMORY;
  1315. end;
  1316. GlobalUnlock(cap.hContainer);
  1317. Result := lpDSM_Entry(@FAppID, @FdsID, DG_CONTROL, DAT_CAPABILITY, MSG_SET, @cap);
  1318. GlobalFree(cap.hContainer);
  1319. if Result <> TWRC_SUCCESS then
  1320. DoTwMessage('Error XferMech DS. (DG_CONTROL/DAT_CAPABILITY/MSG_SET)');
  1321. end;
  1322. function TCnTwain.AutoFeedDS: TW_UINT16;
  1323. var
  1324. cap: TW_CAPABILITY;
  1325. pval: pTW_ONEVALUE;
  1326. begin
  1327. Result := TWRC_SUCCESS;
  1328. if not FAutoFeed then
  1329. Exit;
  1330. // Get Feeder Enabled
  1331. FillChar(cap, Sizeof(TW_CAPABILITY), 0);
  1332. cap.Cap := CAP_FEEDERENABLED;
  1333. cap.ConType := TWON_ONEVALUE;
  1334. Result := lpDSM_Entry(@FAppID, @FdsID, DG_CONTROL, DAT_CAPABILITY, MSG_GET, @cap);
  1335. if Result <> TWRC_SUCCESS then
  1336. begin
  1337. GlobalFree(cap.hContainer);
  1338. DoTwMessage('Error get AutoFeed. (DG_CONTROL/DAT_CAPABILITY/MSG_GET)');
  1339. Exit;
  1340. end;
  1341. pval := GlobalLock(cap.hContainer);
  1342. if pval^.Item <> 0 then
  1343. begin // Feeder Enabled
  1344. GlobalUnlock(cap.hContainer);
  1345. GlobalFree(cap.hContainer);
  1346. end
  1347. else
  1348. begin
  1349. // Set Feeder Enabled
  1350. pval^.ItemType := TWTY_BOOL;
  1351. pval^.Item := 1; // TRUE
  1352. Result := lpDSM_Entry(@FAppID, @FdsID, DG_CONTROL, DAT_CAPABILITY, MSG_SET, @cap);
  1353. GlobalFree(cap.hContainer);
  1354. if Result = TWRC_SUCCESS then
  1355. begin
  1356. // Verify Feeder Enabled
  1357. Result := lpDSM_Entry(@FAppID, @FdsID, DG_CONTROL, DAT_CAPABILITY, MSG_GET, @cap);
  1358. if Result = TWRC_SUCCESS then
  1359. begin
  1360. pval := GlobalLock(cap.hContainer);
  1361. if pval^.Item = 0 then
  1362. Result := TWRC_FAILURE; // not set
  1363. GlobalUnlock(cap.hContainer);
  1364. GlobalFree(cap.hContainer);
  1365. end
  1366. else
  1367. DoTwMessage('Error Get AutoFeed. (DG_CONTROL, DAT_CAPABILITY, MSG_GET)');
  1368. end
  1369. else
  1370. DoTwMessage('Error Get AutoFeed. (DG_CONTROL, DAT_CAPABILITY, MSG_SET)');
  1371. end;
  1372. if Result = TWRC_SUCCESS then
  1373. begin
  1374. // Get AutoFeed
  1375. cap.Cap := CAP_AUTOFEED;
  1376. cap.ConType := TWON_ONEVALUE;
  1377. Result := lpDSM_Entry(@FAppID, @FdsID, DG_CONTROL, DAT_CAPABILITY, MSG_GET, @cap);
  1378. pval := GlobalLock(cap.hContainer);
  1379. if pval^.Item <> 0 then
  1380. begin // already auto feed
  1381. GlobalUnlock(cap.hContainer);
  1382. GlobalFree(cap.hContainer);
  1383. end
  1384. else
  1385. begin
  1386. // Set AutoFeed
  1387. pval^.ItemType := TWTY_BOOL;
  1388. pval^.Item := 1; // TRUE;
  1389. GlobalUnlock(cap.hContainer);
  1390. Result := lpDSM_Entry(@FAppID, @FdsID, DG_CONTROL, DAT_CAPABILITY, MSG_SET, @cap);
  1391. GlobalFree(cap.hContainer);
  1392. if Result = TWRC_SUCCESS then
  1393. begin
  1394. // Verify AutoFeed
  1395. Result := lpDSM_Entry(@FAppID, @FdsID, DG_CONTROL, DAT_CAPABILITY, MSG_GET, @cap);
  1396. if Result = TWRC_SUCCESS then
  1397. begin
  1398. pval := GlobalLock(cap.hContainer);
  1399. if pval^.Item <> 0 then
  1400. Result := TWRC_FAILURE; // not been set
  1401. GlobalUnlock(cap.hContainer);
  1402. GlobalFree(cap.hContainer);
  1403. end;
  1404. end
  1405. else
  1406. DoTwMessage('Error set AutoFeed. (DG_CONTROL, DAT_CAPABILITY, MSG_SET)');
  1407. end;
  1408. end;
  1409. // AutoFeedBOOL := Result = TWRC_SUCCESS;
  1410. end;
  1411. function TCnTwain.EnableDS(Show: Boolean): TW_UINT16;
  1412. begin
  1413. Result := TWRC_FAILURE;
  1414. if IsDSOpen then
  1415. if not IsDSEnabled then
  1416. begin
  1417. twUI.hParent := FHandle;
  1418. twUI.ModalUI := 0; // Mac Only..
  1419. if Show then
  1420. twUI.ShowUI := 1
  1421. else
  1422. twUI.ShowUI := 0;
  1423. Result := lpDSM_Entry(@FAppID, @FdsID, DG_CONTROL, DAT_USERINTERFACE, MSG_ENABLEDS, @twUI);
  1424. if Result = TWRC_SUCCESS then
  1425. FIsDSEnabled := True
  1426. else
  1427. DoTwMessage('Error Enable DS. (DG_CONTROL/DAT_USERINTERFACE/MSG_ENABLEDS)');
  1428. end
  1429. else
  1430. DoTwMessage('Can not Enable DS while it already Enabled')
  1431. else
  1432. DoTwMessage('Can not Enable DS while DS is not Openning');
  1433. end;
  1434. function TCnTwain.DisableDS: TW_UINT16;
  1435. begin
  1436. Result := TWRC_FAILURE;
  1437. if IsDSEnabled then
  1438. begin
  1439. twUI.hParent := FHandle;
  1440. twUI.ShowUI := TW_BOOL(TWON_DONTCARE8);
  1441. Result := lpDSM_Entry(@FAppID, @FdsID, DG_CONTROL, DAT_USERINTERFACE, MSG_DISABLEDS, @twUI);
  1442. if Result = TWRC_SUCCESS then
  1443. FIsDSEnabled := False
  1444. else
  1445. DoTwMessage('Error Disable DS. (DG_CONTROL/DAT_USERINTERFACE/MSG_DISABLEDS)');
  1446. end;
  1447. FIsDSEnabled := False;
  1448. end;
  1449. function TCnTwain.SelectDS: TW_UINT16;
  1450. var
  1451. NewDsID: TW_IDENTITY;
  1452. begin
  1453. Result := TWRC_FAILURE;
  1454. NewDsID.Id := 0;
  1455. NewDsID.ProductName[0] := #0;
  1456. if not IsDSOpen then
  1457. begin
  1458. Result := lpDSM_Entry(@FAppID, nil, DG_CONTROL, DAT_IDENTITY, MSG_USERSELECT, @NewDsID);
  1459. if Result = TWRC_SUCCESS then
  1460. FdsID := NewDsID;
  1461. end
  1462. else
  1463. DoTwMessage('Can not Select New DS while DS is Openning');
  1464. end;
  1465. function TCnTwain.Acquire(Show: Boolean): TW_UINT16;
  1466. begin
  1467. Result := TWRC_FAILURE;
  1468. if not IsDSMOpen then
  1469. Result := OpenDSM;
  1470. if Result <> TWRC_SUCCESS then
  1471. Exit;
  1472. if not IsDSOpen then
  1473. Result := OpenDS;
  1474. if Result <> TWRC_SUCCESS then
  1475. Exit;
  1476. Result := XferMechDS;
  1477. if Result <> TWRC_SUCCESS then
  1478. Exit;
  1479. Result := AutoFeedDS;
  1480. if Result <> TWRC_SUCCESS then
  1481. Exit;
  1482. if not IsDSEnabled then
  1483. Result := EnableDS(Show);
  1484. end;
  1485. function TCnTwain.GetDSInfo(var DsID: TW_IDENTITY): TW_UINT16;
  1486. begin
  1487. Result := TWRC_FAILURE;
  1488. if not FIsDSMOpen then
  1489. begin
  1490. if OpenDSM <> TWRC_SUCCESS then
  1491. Exit;
  1492. if OpenDS <> TWRC_SUCCESS then
  1493. Exit;
  1494. DsID := FDsID;
  1495. Result := TWRC_SUCCESS;
  1496. CloseDS;
  1497. CloseDSM;
  1498. end
  1499. else // DSM Openned.
  1500. if FIsDSOpen then
  1501. begin
  1502. DsID := FDsID;
  1503. Result := TWRC_SUCCESS;
  1504. end
  1505. else
  1506. begin
  1507. if OpenDS <> TWRC_SUCCESS then
  1508. Exit;
  1509. DsID := FDsID;
  1510. CloseDS;
  1511. end;
  1512. end;
  1513. function TCnTwain.GetComponentInfo(var DsID: TW_IDENTITY): TW_UINT16;
  1514. begin
  1515. Result := TWRC_SUCCESS;
  1516. DsID := FAppId;
  1517. end;
  1518. function TCnTwain.SelectSource: TW_UINT16;
  1519. begin
  1520. Result := TWRC_FAILURE;
  1521. if not IsDSMOpen then
  1522. OpenDSM;
  1523. if IsDSOpen then
  1524. begin //Can't Do Select While DS is Openning!
  1525. DoTwMessage('Can''t Do Select While DS is Openning.', False);
  1526. Exit;
  1527. end;
  1528. Result := SelectDS;
  1529. if IsDSMOpen then
  1530. CloseDSM;
  1531. end;
  1532. procedure TCnTwain.Terminate;
  1533. begin
  1534. DisableDS;
  1535. CloseDS;
  1536. CloseDSM;
  1537. end;
  1538. end.