| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633 |
- {******************************************************************************}
- { CnPack For Delphi/C++Builder }
- { 中国人自己的开放源码第三方开发包 }
- { (C)Copyright 2001-2018 CnPack 开发组 }
- { ------------------------------------ }
- { }
- { 本开发包是开源的自由软件,您可以遵照 CnPack 的发布协议来修 }
- { 改和重新发布这一程序。 }
- { }
- { 发布这一开发包的目的是希望它有用,但没有任何担保。甚至没有 }
- { 适合特定目的而隐含的担保。更详细的情况请参阅 CnPack 发布协议。 }
- { }
- { 您应该已经和开发包一起收到一份 CnPack 发布协议的副本。如果 }
- { 还没有,可访问我们的网站: }
- { }
- { 网站地址:http://www.cnpack.org }
- { 电子邮件:master@cnpack.org }
- { }
- {******************************************************************************}
- unit CnTwain;
- {* |<PRE>
- ================================================================================
- * 软件名称:外接设备组件包
- * 单元名称:实现扫描仪图象采集单元
- * 单元作者:rarnu(rarnu@cnpack.org)
- * 备 注:爱普生扫描仪可用,使用EPSON V200 API,本单元仅是略做封装
- * 开发平台:Windows2003 Server + Delphi2007 up2
- * 兼容测试:Windows2000/XP/2003/Vista + Delphi 7/2006/2007/2009
- * 本 地 化:该单元中的字符串均符合本地化处理方式
- * 单元标识:$Id$
- * 修改记录:2008.08.14 V1.0
- * 创建单元
- ================================================================================
- |</PRE>}
- interface
- {$I CnPack.inc}
- uses
- Windows, Messages, SysUtils, Classes, Controls, Forms, Graphics;
- const
- APP_PROTOCOLMAJOR = 4;
- APP_PROTOCOLMINOR = 0;
- VALID_HANDLE = 32;
- const
- TWON_PROTOCOLMAJOR = 1;
- TWON_PROTOCOLMINOR = 7;
- TWON_ARRAY = 3;
- TWON_ENUMERATION = 4;
- TWON_ONEVALUE = 5;
- TWON_RANGE = 6;
- TWON_ICONID = 962;
- TWON_DSMID = 461;
- TWON_DSMCODEID = 63;
- TWON_DONTCARE8 = $FF;
- TWON_DONTCARE16 = $FFFF;
- TWON_DONTCARE32 = $FFFFFFFF;
- TWCY_USA = 1;
- TWCY_CANADA = 2;
- TWCY_MEXICO = 3;
- TWCY_BRITAIN = 6;
- TWCY_FRANCE = 33;
- TWCY_JAPAN = 81;
- TWCY_KOREA = 82;
- TWCY_CHINA = 86;
- TWCY_HONGKONG = 852;
- TWCY_TAIWAN = 886;
- TWLG_DAN = 0; //Danish
- TWLG_DUT = 1; //Dutch
- TWLG_ENG = 2; //International English
- TWLG_FCF = 3; //French Canadian
- TWLG_FIN = 4; //Finnish
- TWLG_FRN = 5; //French
- TWLG_GER = 6; //German
- TWLG_ICE = 7; //Icelandic
- TWLG_ITN = 8; //Italian
- TWLG_NOR = 9; //Norwegian
- TWLG_POR = 10; //Portuguese
- TWLG_SPA = 11; //Spanish
- TWLG_SWE = 12; //Swedish
- TWLG_USA = 13; //U.S. English
- TWLG_USERLOCALE = $FFFF;
- TWLG_CHINESE = 37;
- TWLG_CHINESE_PRC = 39; // People's Republic of China
- TWLG_CHINESE_SIMPLIFIED = 41;
- TWLG_CHINESE_TAIWAN = 42;
- TWLG_CHINESE_TRADITIONAL = 43;
- TWTY_INT8 = $0000; // Means Item is a TW_INT8
- TWTY_INT16 = $0001; // Means Item is a TW_INT16
- TWTY_INT32 = $0002; // Means Item is a TW_INT32
- TWTY_UINT8 = $0003; // Means Item is a TW_UINT8
- TWTY_UINT16 = $0004; // Means Item is a TW_UINT16
- TWTY_UINT32 = $0005; // Means Item is a TW_UINT32
- TWTY_BOOL = $0006; // Means Item is a TW_BOOL
- TWTY_FIX32 = $0007; // Means Item is a TW_FIX32
- TWTY_FRAME = $0008; // Means Item is a TW_FRAME
- TWTY_STR32 = $0009; // Means Item is a TW_STR32
- TWTY_STR64 = $000a; // Means Item is a TW_STR64
- TWTY_STR128 = $000b; // Means Item is a TW_STR128
- TWTY_STR255 = $000c; // Means Item is a TW_STR255
- DG_CONTROL = $00000001; // data pertaining to control
- DG_IMAGE = $00000002; // data pertaining to raster images
- DG_IMAGE_OR_CONTROL = $00000003; //is " DG_CONTROL|DG_IMAGE " in C++
- DAT_NULL = $0000; // No data or structure.
- DAT_CUSTOMBASE = $8000; // Base of custom DATs.
- // Data Argument Types for the DG_CONTROL Data Group.
- DAT_CAPABILITY = $0001; // TW_CAPABILITY
- DAT_EVENT = $0002; // TW_EVENT
- DAT_IDENTITY = $0003; // TW_IDENTITY
- DAT_PARENT = $0004; // TW_HANDLE, app win handle in Windows
- DAT_PENDINGXFERS = $0005; // TW_PENDINGXFERS
- DAT_SETUPMEMXFER = $0006; // TW_SETUPMEMXFER
- DAT_SETUPFILEXFER = $0007; // TW_SETUPFILEXFER
- DAT_STATUS = $0008; // TW_STATUS
- DAT_USERINTERFACE = $0009; // TW_USERINTERFACE
- DAT_XFERGROUP = $000a; // TW_UINT32
- DAT_TWUNKIDENTITY = $000b; // TW_TWUNKIDENTITY
- // Data Argument Types for the DG_IMAGE Data Group.
- DAT_IMAGEINFO = $0101; // TW_IMAGEINFO
- DAT_IMAGELAYOUT = $0102; //TW_IMAGELAYOUT
- DAT_IMAGEMEMXFER = $0103; //TW_IMAGEMEMXFER
- DAT_IMAGENATIVEXFER = $0104; //TW_UINT32 loword is hDIB, PICHandle
- DAT_IMAGEFILEXFER = $0105; //Null data
- DAT_CIECOLOR = $0106; //TW_CIECOLOR
- DAT_GRAYRESPONSE = $0107; //TW_GRAYRESPONSE
- DAT_RGBRESPONSE = $0108; //TW_RGBRESPONSE
- DAT_JPEGCOMPRESSION = $0109; //TW_JPEGCOMPRESSION
- DAT_PALETTE8 = $010A; //TW_PALETTE8
- // All message constants are unique.
- MSG_NULL = $0000; // Used in TW_EVENT structure
- MSG_CUSTOMBASE = $8000; // Base of custom messages
- // Generic messages may be used with any of several DATs.
- MSG_GET = $0001; // Get one or more values
- MSG_GETCURRENT = $0002; // Get current value
- MSG_GETDEFAULT = $0003; // Get default (e.g. power up) value
- MSG_GETFIRST = $0004; // Get first of a series of items, e.g. DSs
- MSG_GETNEXT = $0005; // Iterate through a series of items.
- MSG_SET = $0006; // Set one or more values
- MSG_RESET = $0007; // Set current value to default value
- // Messages used with DAT_NULL
- MSG_XFERREADY = $0101; // The data source has data ready
- MSG_CLOSEDSREQ = $0102; // Request for App. to close DS
- MSG_CLOSEDSOK = $0103; // Tell the Application. to save the state.
- // Messages used with a pointer to a DAT_STATUS structure
- MSG_CHECKSTATUS = $0201; // Get status information
- // Messages used with a pointer to DAT_PARENT data
- MSG_OPENDSM = $0301; // Open the DSM
- MSG_CLOSEDSM = $0302; // Close the DSM
- // Messages used with a pointer to a DAT_IDENTITY structure
- MSG_OPENDS = $0401; // Open a data source
- MSG_CLOSEDS = $0402; // Close a data source
- MSG_USERSELECT = $0403; // Put up a dialog of all DS
- // Messages used with a pointer to a DAT_USERINTERFACE structure
- MSG_DISABLEDS = $0501; // Disable data transfer in the DS
- MSG_ENABLEDS = $0502; // Enable data transfer in the DS
- // Messages used with a pointer to a DAT_EVENT structure
- MSG_PROCESSEVENT = $0601;
- // Messages used with a pointer to a DAT_PENDINGXFERS structure
- MSG_ENDXFER = $0701;
- // Capabilities
- CAP_CUSTOMBASE = $8000; //Base of custom capabilities
- // all data sources are REQUIRED to support these caps
- CAP_XFERCOUNT = $0001;
- // image data sources are REQUIRED to support these caps
- ICAP_COMPRESSION = $0100;
- ICAP_PIXELTYPE = $0101;
- ICAP_UNITS = $0102; //default is TWUN_INCHES
- ICAP_XFERMECH = $0103;
- // all data sources MAY support these caps
- CAP_AUTHOR = $1000;
- CAP_CAPTION = $1001;
- CAP_FEEDERENABLED = $1002;
- CAP_FEEDERLOADED = $1003;
- CAP_TIMEDATE = $1004;
- CAP_SUPPORTEDCAPS = $1005;
- CAP_EXTENDEDCAPS = $1006;
- CAP_AUTOFEED = $1007;
- CAP_CLEARPAGE = $1008;
- CAP_FEEDPAGE = $1009;
- CAP_REWINDPAGE = $100a;
- CAP_INDICATORS = $100b; //Added 1.1
- CAP_SUPPORTEDCAPSEXT = $100c; // Added 1.6
- CAP_PAPERDETECTABLE = $100d; // Added 1.6
- CAP_UICONTROLLABLE = $100e; // Added 1.6
- // image data sources MAY support these caps
- ICAP_AUTOBRIGHT = $1100;
- ICAP_BRIGHTNESS = $1101;
- ICAP_CONTRAST = $1103;
- ICAP_CUSTHALFTONE = $1104;
- ICAP_EXPOSURETIME = $1105;
- ICAP_FILTER = $1106;
- ICAP_FLASHUSED = $1107;
- ICAP_GAMMA = $1108;
- ICAP_HALFTONES = $1109;
- ICAP_HIGHLIGHT = $110a;
- ICAP_IMAGEFILEFORMAT = $110c;
- ICAP_LAMPSTATE = $110d;
- ICAP_LIGHTSOURCE = $110e;
- ICAP_ORIENTATION = $1110;
- ICAP_PHYSICALWIDTH = $1111;
- ICAP_PHYSICALHEIGHT = $1112;
- ICAP_SHADOW = $1113;
- ICAP_FRAMES = $1114;
- ICAP_XNATIVERESOLUTION = $1116;
- ICAP_YNATIVERESOLUTION = $1117;
- ICAP_XRESOLUTION = $1118;
- ICAP_YRESOLUTION = $1119;
- ICAP_MAXFRAMES = $111a;
- ICAP_TILES = $111b;
- ICAP_BITORDER = $111c;
- ICAP_CCITTKFACTOR = $111d;
- ICAP_LIGHTPATH = $111e;
- ICAP_PIXELFLAVOR = $111f;
- ICAP_PLANARCHUNKY = $1120;
- ICAP_ROTATION = $1121;
- ICAP_SUPPORTEDSIZES = $1122;
- ICAP_THRESHOLD = $1123;
- ICAP_XSCALING = $1124;
- ICAP_YSCALING = $1125;
- ICAP_BITORDERCODES = $1126;
- ICAP_PIXELFLAVORCODES = $1127;
- ICAP_JPEGPIXELTYPE = $1128;
- ICAP_TIMEFILL = $112a;
- ICAP_BITDEPTH = $112b;
- ICAP_BITDEPTHREDUCTION = $112c; //Added 1.5
- //Return Codes and Condition Codes section
- // Return Codes: DSM_Entry and DS_Entry may return any one of these values.
- TWRC_CUSTOMBASE = $8000;
- TWRC_SUCCESS = 0;
- TWRC_FAILURE = 1; //App may get TW_STATUS for info on failure
- TWRC_CHECKSTATUS = 2; //"tried hard"; get status
- TWRC_CANCEL = 3;
- TWRC_DSEVENT = 4;
- TWRC_NOTDSEVENT = 5;
- TWRC_XFERDONE = 6;
- TWRC_ENDOFLIST = 7; //After MSG_GETNEXT if nothing left
- //Condition Codes: App gets these by doing DG_CONTROL DAT_STATUS MSG_GET.
- TWCC_CUSTOMBASE = $8000;
- TWCC_SUCCESS = 0; //It worked!
- TWCC_BUMMER = 1; //Failure due to unknown causes
- TWCC_LOWMEMORY = 2; //Not enough memory to perform operation
- TWCC_NODS = 3; //No Data Source
- TWCC_MAXCONNECTIONS = 4; //DS is connected to max possible apps
- TWCC_OPERATIONERROR = 5; //DS or DSM reported error, app shouldn't
- TWCC_BADCAP = 6; //Unknown capability
- TWCC_BADPROTOCOL = 9; //Unrecognized MSG DG DAT combination
- TWCC_BADVALUE = 10; //Data parameter out of range
- TWCC_SEQERROR = 11; //DG DAT MSG out of expected sequence
- TWCC_BADDEST = 12; //Unknown destination App/Src in DSM_Entry
- // ICAP_UNITS values (UN_ means UNits)
- TWUN_INCHES = 0;
- TWUN_CENTIMETERS = 1;
- TWUN_PICAS = 2;
- TWUN_POINTS = 3;
- TWUN_TWIPS = 4;
- TWUN_PIXELS = 5;
- // ICAP_PIXELTYPE values (PT_ means Pixel Type)
- TWPT_BW = 0;
- TWPT_GRAY = 1;
- TWPT_RGB = 2;
- TWPT_PALETTE = 3;
- TWPT_CMY = 4;
- TWPT_CMYK = 5;
- TWPT_YUV = 6;
- TWPT_YUVK = 7;
- TWPT_CIEXYZ = 8;
- // Flags used in TW_MEMORY structure.
- TWMF_APPOWNS = $01;
- TWMF_DSMOWNS = $02;
- TWMF_DSOWNS = $04;
- TWMF_POINTER = $08;
- TWMF_HANDLE = $10;
- // ICAP_PIXELFLAVOR values (PF_ means Pixel Flavor)
- TWPF_CHOCOLATE = 0; // zero pixel represents darkest shade
- TWPF_VANILLA = 1; // zero pixel represents lightest shade
- // ICAP_IMAGEFILEFORMAT values (FF_means File Format)
- TWFF_TIFF = 0; // Tagged Image File Format
- TWFF_PICT = 1; // Macintosh PICT
- TWFF_BMP = 2; // Windows Bitmap
- TWFF_XBM = 3; // X-Windows Bitmap
- TWFF_JFIF = 4; // JPEG File Interchange Format
- TWFF_FPX = 5; // Flash Pix
- TWFF_TIFFMULTI = 6; // Multi-page tiff file
- TWFF_PNG = 7;
- TWFF_SPIFF = 8;
- TWFF_EXIF = 9;
- TWSX_NATIVE = 0;
- TWSX_FILE = 1;
- TWSX_MEMORY = 2;
- type
- TW_HANDLE = Word;
- TW_MEMREF = pointer;
- // TW_HUGE = Longint;
- TW_STR32 = array[0..33] of Char;
- // TW_STR64 = Array [0..65] of Char;
- // TW_STR128 = Array [0..129] of Char;
- // TW_STR255 = Array [0..255] of Char;
- // TW_INT8 = ShortInt;
- TW_INT16 = Smallint;
- TW_INT32 = Longint;
- TW_UINT8 = Byte;
- TW_UINT16 = Word; // Unsinged integer !!!
- TW_UINT32 = Longword;
- TW_BOOL = Word; // Unsinged Short Boolean !!!
- pTW_UINT16 = ^TW_UINT16;
- TW_FIX32 = packed record // Fixed point structure type.
- Whole: TW_INT16; // maintains the sign
- Frac: TW_UINT16;
- end;
- pTW_FIX32 = ^TW_FIX32;
- TW_VERSION = packed record
- MajorNum: TW_UINT16; // Major revision number of the software.
- MinorNum: TW_UINT16; // Incremental revision number of the software.
- Language: TW_UINT16; // e.g. TWLG_SWISSFRENCH
- Country: TW_UINT16; // e.g. TWCY_SWITZERLAND
- Info: TW_STR32; // e.g. "1.0b3 Beta release"
- end;
- TW_IDENTITY = packed record
- Id: TW_UINT32; // Unique number. In Windows, app hWnd
- Version: TW_VERSION; // Identifies the piece of code
- ProtocolMajor: TW_UINT16; // App and DS must set to TWON_PROTOCOLMAJOR
- ProtocolMinor: TW_UINT16; // App and DS must set to TWON_PROTOCOLMINOR
- SupportedGroups: TW_UINT32; // Bit field OR combination of DG_ constants
- Manufacturer: TW_STR32; // Manufacturer name, e.g. "Hewlett-Packard"
- ProductFamily: TW_STR32; // Product family name, e.g. "ScanJet"
- ProductName: TW_STR32; // Product name, e.g. "ScanJet Plus"
- end;
- pTW_IDENTITY = ^TW_IDENTITY;
- TW_IMAGEINFO = packed record // DAT_IMAGEINFO. App gets detailed image info from DS with this.
- XResolution: TW_FIX32; // Resolution in the horizontal
- YResolution: TW_FIX32; // Resolution in the vertical
- ImageWidth: TW_INT32; // Columns in the image, -1 if unknown by DS
- ImageLength: TW_INT32; // Rows in the image, -1 if unknown by DS
- SamplesPerPixel: TW_INT16; // Number of samples per pixel, 3 for RGB
- BitsPerSample: array[0..7] of TW_INT16; // Number of bits for each sample
- BitsPerPixel: TW_INT16; // Number of bits for each padded pixel
- Planar: TW_BOOL; // True if Planar, False if chunky
- PixelType: TW_INT16; // How to interp data; photo interp (TWPT_)
- Compression: TW_UINT16; // How the data is compressed (TWCP_xxxx)
- end;
- pTW_IMAGEINFO = ^TW_IMAGEINFO;
- TW_ONEVALUE = packed record
- ItemType: TW_UINT16;
- Item: TW_UINT32;
- end;
- pTW_ONEVALUE = ^TW_ONEVALUE;
- TW_CAPABILITY = packed record //DAT_CAPABILITY. Used by app to get/set capability from/in a data source.
- Cap, ConType: TW_UINT16;
- hContainer: THandle;
- end;
- pTW_CAPABILITY = ^TW_CAPABILITY;
- TW_SETUPMEMXFER = packed record
- MinBufSize: TW_UINT32;
- MaxBufSize: TW_UINT32;
- Preferred: TW_UINT32;
- end;
- pTW_SETUPMEMXFER = ^TW_SETUPMEMXFER;
- TW_USERINTERFACE = packed record
- ShowUI: TW_BOOL; // TRUE if DS should bring up its UI
- ModalUI: TW_BOOL; // For Mac only - true if the DS's UI is modal
- hParent: TW_HANDLE; // For windows only - App window handle
- end;
- pTW_USERINTERFACE = ^TW_USERINTERFACE;
- TW_EVENT = packed record
- pEvent: TW_MEMREF; // Windows pMSG or Mac pEvent.
- TWMessage: TW_UINT16; // TW msg from data source, e.g. MSG_XFERREADY
- end;
- pTW_EVENT = ^TW_EVENT;
- TW_PENDINGXFERS = packed record
- Count: TW_UINT16; // Number of additional "images" pending.
- Reserved: TW_UINT32;
- end;
- pTW_PENDINGXFERS = ^TW_PENDINGXFERS;
- TW_ELEMENT8 = packed record
- Index: TW_UINT8; // Value used to index into the color table.
- Channel1: TW_UINT8; // First tri-stimulus value (e.g Red)
- Channel2: TW_UINT8; // Second tri-stimulus value (e.g Green)
- Channel3: TW_UINT8; // Third tri-stimulus value (e.g Blue)
- end;
- pTW_ELEMENT8 = ^TW_ELEMENT8;
- TW_PALETTE8 = packed record
- NumColors: TW_UINT16; // Number of colors in the color table.
- PaletteType: TW_UINT16; // TWPA_xxxx, specifies type of palette.
- Colors: array[0..255] of TW_ELEMENT8; // TWPA_xxxx, specifies type of palette.
- end;
- pTW_PALETTE8 = ^TW_PALETTE8;
- TW_MEMORY = packed record
- Flags: TW_UINT32; // Any combination of the TWMF_ constants.
- Length: TW_UINT32; // Number of bytes stored in buffer TheMem.
- TheMem: TW_MEMREF; // Pointer or handle to the allocated memory buffer.
- end;
- pTW_MEMORY = ^TW_MEMORY;
- TW_IMAGEMEMXFER = packed record
- Compression: TW_UINT16; // How the data is compressed
- BytesPerRow: TW_UINT32; // Number of bytes in a row of data
- Columns: TW_UINT32; // How many columns
- Rows: TW_UINT32; // How many rows
- XOffset: TW_UINT32; // How far from the side of the image
- YOffset: TW_UINT32; // How far from the top of the image
- BytesWritten: TW_UINT32; // How many bytes written in Memory
- Memory: TW_MEMORY; // Mem struct used to pass actual image data
- end;
- pTW_IMAGEMEMXFER = ^TW_IMAGEMEMXFER;
- TW_SETUPFILEXFER = packed record
- FileName: array[0..255] of Char;
- Format: TW_UINT16; // Any TWFF_ constant
- VRefNum: TW_INT16; // Used for Mac only
- end;
- pTW_SETUPFILEXFER = ^TW_SETUPFILEXFER;
- TW_ENUMERATION = packed record
- ItemType: TW_UINT16;
- NumItems: TW_UINT32; // How many items in ItemList
- CurrentIndex: TW_UINT32; // Current value is in ItemList[CurrentIndex]
- DefaultIndex: TW_UINT32; // Powerup value is in ItemList[DefaultIndex]
- ItemList: array[0..0] of TW_UINT8; // Array of ItemType values starts here
- end;
- pTW_ENUMERATION = ^TW_ENUMERATION;
- DSM_Entry = function(pOrigin: pTW_IDENTITY; pDest: pTW_IDENTITY; DG: TW_UINT32; DAT: TW_UINT16; MSG: TW_UINT16; pData: TW_MEMREF): TW_UINT16; stdcall;
- TOnTwMessage = procedure(Sender: TObject; Msg: string) of object;
- TOnCapture = procedure(Sender: TObject; bmp: TBitmap) of object;
- TOnFileNameNeeded = procedure(Sender: TObject; var FileName: string) of object;
- TtransferType = (doNativeTransfer, doFileTransfer, doMemTransfer);
- TCnTwain = class(TComponent)
- private
- FAppID: TW_IDENTITY;
- FdsID: TW_IDENTITY;
- twUI: TW_USERINTERFACE;
- FHandle: HWND;
- FIsDSMOpen: Boolean;
- FIsDSOpen: Boolean;
- FIsDSEnabled: Boolean;
- FTransferType: TTransferType;
- hDSMDLL: THandle;
- lpDSM_Entry: DSM_Entry;
- OldWndProc: TFarProc;
- NewWndProc: Pointer;
- FHooked: Boolean;
- FAutoFeed: Boolean;
- FOnTwMessage: TOnTwMessage;
- FOnCapture: TOnCapture;
- FOnFileNameNeeded: TOnFileNameNeeded;
- procedure HookWin;
- procedure UnHookWin;
- protected
- function SelectDS: TW_UINT16;
- procedure WndProc(var Message: TMessage);
- function ProcessTWMessage(var aMsg: TMessage; TwhWnd: THandle): Boolean;
- function OpenDSM: TW_UINT16; // DSM
- function CloseDSM: TW_UINT16;
- function OpenDS: TW_UINT16; // DS
- function CloseDS: TW_UINT16;
- function XferMechDS: TW_UINT16;
- function AutoFeedDS: TW_UINT16;
- function EnableDS(Show: Boolean): TW_UINT16; // UI
- function DisableDS: TW_UINT16;
- procedure TransferImage;
- procedure NativeTransfer;
- procedure FileTransfer;
- procedure MemoryTransfer;
- procedure DoXferDone(hDib: THandle);
- procedure DoTwMessage(Msg: string; TerminateDS: Boolean = True);
- public
- constructor Create(AOwner: TComponent); override;
- destructor Destroy; override;
- {* 连接并打开扫描仪 }
- function Acquire(Show: Boolean): TW_UINT16;
- {* 获取 Device 信息}
- function GetDSInfo(var DsID: TW_IDENTITY): TW_UINT16;
- {* 获取组件信息 }
- function GetComponentInfo(var DsID: TW_IDENTITY): TW_UINT16;
- {* 选择源,当计算机连接多个扫描仪时有效 }
- function SelectSource: TW_UINT16;
- {* 断开并关闭扫描仪 }
- procedure Terminate;
- {* 判断 DSM 服务是否开启 }
- property IsDSMOpen: Boolean read FIsDSMOpen;
- {* 判断 Device 是否开启 }
- property IsDSOpen: Boolean read FIsDSOpen;
- {* 判断 Device 是否可用 }
- property IsDSEnabled: Boolean read FIsDSEnabled;
- published
- {* 是否自动返回 }
- property AutoFeed: Boolean read FAutoFeed write FAutoFeed;
- {* 数据传送类型 }
- property TransferType: TtransferType read FTransferType write FTransferType;
- {* 捕获图像时触发事件 }
- property OnCaptrue: TOnCapture read FOnCapture write FOnCapture;
- {* 捕获错误信息时触发事件 }
- property OnErrorMessage: TOnTwMessage read FOnTwMessage write FOnTwMessage;
- {* 请求文件名时触发事件 }
- property OnFileNameNeeded: TOnFileNameNeeded read FOnFileNameNeeded write FOnFileNameNeeded;
- end;
- implementation
- function FIX32ToFloat(fix32: TW_FIX32): Double;
- begin
- Result := fix32.Whole + (fix32.Frac / 65536.0);
- end;
- function DibNumColors(pv: Pointer): Word;
- var
- Bits: integer;
- begin
- if pBITMAPINFOHEADER(pv)^.biSize <> sizeof(BITMAPCOREHEADER) then
- begin
- if pBITMAPINFOHEADER(pv)^.biClrUsed <> 0 then
- begin
- Result := pBITMAPINFOHEADER(pv)^.biClrUsed;
- Exit;
- end;
- Bits := pBITMAPINFOHEADER(pv)^.biBitCount;
- end
- else
- Bits := pBITMAPCOREHEADER(pv)^.bcBitCount;
- case Bits of
- 1:
- Result := 2;
- 4:
- Result := 16;
- 8:
- Result := 256;
- else
- Result := 0;
- end;
- end;
- function CreateBIPalette(lpbi: pBITMAPINFOHEADER): HPALETTE;
- var
- pRgb: pRGBQUAD;
- nNumColors: Word;
- hPal: HGLOBAL;
- pPal: pLOGPALETTE;
- i: integer;
- Red, Green, Blue: Byte;
- begin
- Result := 0;
- if lpbi = nil then
- Exit;
- if lpbi^.biSize <> sizeof(BITMAPINFOHEADER) then
- Exit;
- pRgb := pRGBQUAD(Longint(lpbi) + Word(lpbi^.biSize));
- nNumColors := DibNumColors(lpbi);
- if nNumColors <> 0 then
- begin
- hPal := GlobalAlloc(GPTR, sizeof(LOGPALETTE) + nNumColors * sizeof(PALETTEENTRY));
- pPal := GlobalLock(hPal);
- if pPal = nil then
- Exit;
- pPal^.palNumEntries := nNumColors;
- pPal^.palVersion := $0300;
- for i := 0 to nNumColors - 1 do
- begin
- pPal^.palPalEntry[i].peRed := pRGBQUAD(Longint(pRgb) + i)^.rgbRed;
- pPal^.palPalEntry[i].peGreen := pRGBQUAD(Longint(pRgb) + i)^.rgbGreen;
- pPal^.palPalEntry[i].peBlue := pRGBQUAD(Longint(pRgb) + i)^.rgbBlue;
- pPal^.palPalEntry[i].peFlags := 0;
- end;
- Result := CreatePalette(pPal^);
- GlobalUnlock(hPal);
- GlobalFree(hPal);
- end
- else if lpbi^.biBitCount = 24 then
- begin
- nNumColors := 256;
- hPal := GlobalAlloc(GPTR, sizeof(LOGPALETTE) + nNumColors * sizeof(PALETTEENTRY));
- pPal := GlobalLock(hPal);
- if pPal = nil then
- Exit;
- pPal^.palNumEntries := nNumColors;
- pPal^.palVersion := $0300;
- Red := 0;
- Green := 0;
- Blue := 0;
- for i := 0 to pPal^.palNumEntries - 1 do
- begin
- pPal^.palPalEntry[i].peRed := Red;
- pPal^.palPalEntry[i].peGreen := Green;
- pPal^.palPalEntry[i].peBlue := Blue;
- pPal^.palPalEntry[i].peFlags := 0;
- Inc(Red, 32);
- if Red = 0 then
- begin
- Inc(Green, 32);
- if Green = 0 then
- Inc(Blue, 64);
- end;
- end;
- Result := CreatePalette(pPal^);
- GlobalUnlock(hPal);
- GlobalFree(hPal);
- end;
- end;
- procedure FlipBitMap(hWindow, hBM: THandle; PixType: TW_INT16);
- var
- pDib: pByte;
- pbmi: pBITMAPINFO;
- bmpWidth, bmpHeight, Linelength: Longint;
- indexH, items, i: integer;
- SizeImage, ClrUsed, offset: DWord;
- BitCount: Word;
- temp: THandle;
- tempptr, tempptrsave, pbuffer: pByte;
- pixels: TW_UINT16;
- SaveRed, SaveBlue: Byte;
- begin
- pDib := GlobalLock(hBM);
- pbmi := pBITMAPINFO(pDib);
- bmpWidth := pbmi^.bmiHeader.biWidth;
- bmpHeight := pbmi^.bmiHeader.biHeight;
- SizeImage := pbmi^.bmiHeader.biSizeImage;
- BitCount := pbmi^.bmiHeader.biBitCount;
- ClrUsed := pbmi^.bmiHeader.biClrUsed;
- temp := GlobalAlloc(GHND, SizeImage);
- if temp <> 0 then
- begin
- tempptr := GlobalLock(temp);
- tempptrsave := tempptr;
- // calculate offset to start of the bitmap data
- offset := Sizeof(BITMAPINFOHEADER);
- Inc(offset, ClrUsed * sizeof(RGBQUAD));
- Linelength := (((bmpWidth * BitCount + 31) div 32) * 4);
- //Goto Last line in bitmap
- Inc(offset, Linelength * (bmpHeight - 1));
- Inc(pDib, offset); // pDib = pDib + offset - Linelength;
- Dec(pDib, Linelength);
- for indexH := 1 to bmpHeight - 1 do
- begin
- Move(pDib^, tempptr^, Linelength);
- Dec(pDib, Linelength);
- Inc(tempptr, Linelength);
- end;
- // Copy temp over hBM
- pbuffer := pByte(pbmi);
- Inc(pbuffer, Sizeof(BITMAPINFOHEADER));
- Inc(pbuffer, ClrUsed * Sizeof(RGBQUAD));
- Move(tempptrsave^, pbuffer^, SizeImage); // memcpy(pbuffer, tempptrsave, SizeImage);
- if PixType = TWPT_RGB then
- begin
- pbuffer := pByte(pbmi);
- Inc(pbuffer, sizeof(BITMAPINFOHEADER));
- Inc(pbuffer, ClrUsed * sizeof(RGBQUAD));
- pixels := pbmi^.bmiHeader.biWidth;
- for items := 0 to bmpHeight - 1 do
- begin
- tempptr := pbuffer;
- for i := 0 to pixels - 1 do
- begin
- //Switch Red byte and Blue byte
- SaveRed := Byte(tempptr^);
- SaveBlue := pByte(Longword(tempptr) + 2)^;
- tempptr^ := SaveBlue;
- pByte(Longword(tempptr) + 2)^ := SaveRed;
- Inc(tempptr, 3);
- end;
- Inc(pbuffer, Linelength);
- end;
- end;
- GlobalUnlock(hBM);
- GlobalUnlock(temp);
- GlobalFree(temp);
- end
- else
- begin
- GlobalUnlock(hBM);
- // DoTwMessage('Could not allocate enough memory to flip image', False);
- end;
- end;
- constructor TCnTwain.Create(AOwner: TComponent);
- begin
- inherited Create(AOwner);
- FHooked := False;
- with AOwner as TWinControl do
- FHandle := Handle;
- // Init ApplicationIdentity.
- FAppID.Id := 0; // Source Manager will assign real value
- with FAppID.Version do
- begin
- MajorNum := APP_PROTOCOLMAJOR;
- MinorNum := APP_PROTOCOLMINOR;
- Language := TWLG_CHINESE_SIMPLIFIED; // TWLG_ENG;
- Country := TWCY_CHINA;
- strcopy(Info, 'RaTwain 扫描仪控件');
- end;
- FAppID.ProtocolMajor := TWON_PROTOCOLMAJOR;
- FAppID.ProtocolMinor := TWON_PROTOCOLMINOR;
- FAppID.SupportedGroups := DG_IMAGE_OR_CONTROL;
- strcopy(FAppID.Manufacturer, '上海维普软件工作室');
- strcopy(FAppID.ProductFamily, 'Delphi7专用扫描仪控件');
- strcopy(FAppID.ProductName, '扫描仪控件');
- FillChar(FDsID, Sizeof(TW_IDENTITY), 0);
- FTransferType := doNativeTransfer;
- hDSMDLL := 0;
- lpDSM_Entry := nil;
- FHooked := False;
- FAutoFeed := False;
- FIsDSMOpen := False;
- FIsDSOpen := False;
- FIsDSEnabled := False;
- end;
- destructor TCnTwain.Destroy;
- begin
- Terminate;
- inherited Destroy;
- end;
- procedure TCnTwain.HookWin;
- begin
- OldWndProc := TFarProc(GetWindowLong(FHandle, GWL_WNDPROC));
- NewWndProc := MakeObjectInstance(WndProc);
- SetWindowLong(FHandle, GWL_WNDPROC, LongInt(NewWndProc));
- FHooked := True;
- end;
- procedure TCnTwain.UnHookWin;
- begin
- if not fHooked then
- exit;
- SetWindowLong(FHandle, GWL_WNDPROC, LongInt(OldWndProc));
- if AsSigned(NewWndProc) then
- FreeObjectInstance(NewWndProc);
- NewWndProc := nil;
- FHooked := False;
- end;
- procedure TCnTwain.WndProc(var Message: TMessage);
- begin
- if not IsDSOpen or not ProcessTWMessage(Message, FHandle) then
- begin
- // if Message.Msg = PM_XFERDONE then ;
- Message.Result := CallWindowProc(OldWndProc, FHandle, Message.Msg, Message.wParam, Message.lParam);
- end;
- end;
- function TCnTwain.ProcessTWMessage(var aMsg: TMessage; TwhWnd: THandle): Boolean;
- var
- twRC: TW_UINT16;
- twEv: TW_EVENT;
- theMsg: TMsg;
- begin // Here Something delicacy that MSG of C++ and TMessage of Delphi are not Same.
- twRC := TWRC_NOTDSEVENT;
- if IsDSOpen then
- begin
- FillChar(twEv, Sizeof(TW_EVENT), #0);
- FillChar(theMsg, Sizeof(TMsg), #0);
- theMsg.hwnd := TwhWnd;
- theMsg.message := aMsg.Msg;
- theMsg.wParam := aMsg.WParam;
- theMsg.lParam := aMsg.LParam;
- twEv.pEvent := @theMsg;
- twRC := lpDSM_Entry(@FappID, @FdsID, DG_CONTROL, DAT_EVENT, MSG_PROCESSEVENT, @twEv);
- aMsg.Msg := theMsg.message;
- aMsg.WParam := theMsg.wParam;
- aMsg.LParam := theMsg.lParam;
- aMsg.Result := twRC;
- case twEv.TWMessage of
- MSG_XFERREADY:
- TransferImage;
- MSG_CLOSEDSREQ, MSG_CLOSEDSOK:
- Terminate;
- end;
- end;
- Result := twRC = TWRC_DSEVENT;
- end;
- procedure TCnTwain.TransferImage;
- begin
- case FTransferType of
- doNativeTransfer:
- NativeTransfer;
- doFileTransfer:
- FileTransfer;
- doMemTransfer:
- MemoryTransfer;
- end;
- //
- end;
- procedure TCnTwain.NativeTransfer;
- var
- twPendingXfer: TW_PENDINGXFERS;
- twRC, twRC2: TW_UINT16;
- hBitMap: TW_UINT32;
- hbm_acq: THandle;
- begin
- hBitMap := 0;
- FillChar(twPendingXfer, sizeof(TW_PENDINGXFERS), #0);
- repeat
- twRC := lpDSM_Entry(@FappID, @FdsID, DG_IMAGE, DAT_IMAGENATIVEXFER, MSG_GET, @hBitMap);
- case twRC of
- TWRC_XFERDONE:
- begin
- hbm_acq := hBitMap;
- twRC2 := lpDSM_Entry(@FappID, @FdsID, DG_CONTROL, DAT_PENDINGXFERS, MSG_ENDXFER, @twPendingXfer);
- if twRC2 <> TWRC_SUCCESS then
- DoTwMessage('DG_CONTROL/DAT_PENDINGXFERS/MSG_ENDXFER', False);
- if twPendingXfer.Count = 0 then
- if (hbm_acq <> 0) and (GlobalLock(hbm_acq) <> nil) then
- begin
- Terminate;
- GlobalUnlock(hbm_acq);
- end;
- if hbm_acq > VALID_HANDLE then
- begin
- DoXferDone(hbm_acq);
- GlobalFree(hbm_acq);
- end
- else
- DoXferDone(0);
- end;
- TWRC_CANCEL:
- begin
- // DoTwMessage('User Cancel. (DG_IMAGE/DAT_IMAGENATIVEXFER/MSG_GET)', False);
- twRC2 := lpDSM_Entry(@FappID, @FdsID, DG_CONTROL, DAT_PENDINGXFERS, MSG_ENDXFER, @twPendingXfer);
- if twRC2 <> TWRC_SUCCESS then
- DoTwMessage('DG_CONTROL/DAT_PENDINGXFERS/MSG_ENDXFER', False);
- if twPendingXfer.Count = 0 then
- Terminate;
- DoXferDone(0);
- end;
- else
- twRC2 := lpDSM_Entry(@FappID, @FdsID, DG_CONTROL, DAT_PENDINGXFERS, MSG_ENDXFER, @twPendingXfer);
- if twRC2 <> TWRC_SUCCESS then
- DoTwMessage('DG_CONTROL/DAT_PENDINGXFERS/MSG_ENDXFER', False);
- if twPendingXfer.Count = 0 then
- Terminate;
- DoXferDone(0);
- end;
- until twPendingXfer.count = 0;
- end;
- procedure TCnTwain.FileTransfer;
- var
- twPendingXfer: TW_PENDINGXFERS;
- SetupMsgGet, setup: TW_SETUPFILEXFER;
- ofs: OFSTRUCT;
- hF: THandle;
- twRC, twRC2: TW_UINT16;
- hbm_acq: THandle;
- header: BITMAPFILEHEADER;
- dwSize: DWord;
- ptr: PChar;
- count: TW_UINT32;
- num: TW_UINT16;
- FFileName: string;
- begin
- FillChar(twPendingXfer, sizeof(TW_PENDINGXFERS), #0);
- FillChar(SetupMsgGet, sizeof(TW_SETUPFILEXFER), #0);
- FillChar(setup, sizeof(TW_SETUPFILEXFER), #0);
- FillChar(ofs, sizeof(OFSTRUCT), #0);
- repeat
- FFileName := '';
- if Assigned(FOnFileNameNeeded) then
- FOnFileNameNeeded(Self, FFileName);
- if FFileName <> '' then
- StrPCopy(setup.FileName, FFileName)
- else
- begin
- lpDSM_Entry(@FappID, @FdsID, DG_CONTROL, DAT_SETUPFILEXFER, MSG_GET, @SetupMsgGet);
- StrCopy(setup.FileName, SetupMsgGet.FileName);
- end;
- setup.Format := TWFF_BMP;
- setup.VRefNum := 0;
- hF := OpenFile(PAnsiChar({$IFDEF UNICODE}AnsiString{$ELSE}string{$ENDIF}(setup.Filename)), ofs, OF_CREATE);
- if hF = HFILE_ERROR then
- begin
- DoTwMessage('Unable to create file for file transfer', False);
- twRC := TWRC_FAILURE;
- end
- else
- begin
- _lclose(hF);
- twRC := lpDSM_Entry(@FappID, @FdsID, DG_CONTROL, DAT_SETUPFILEXFER, MSG_SET, @setup);
- if twRC <> TWRC_SUCCESS then
- DoTwMessage('DG_CONTROL/DAT_SETUPFILEXFER/MSG_SET', False)
- else
- twRC := lpDSM_Entry(@FappID, @FdsID, DG_IMAGE, DAT_IMAGEFILEXFER, MSG_GET, nil);
- case twRC of
- TWRC_XFERDONE:
- begin
- FillChar(ofs, sizeof(OFSTRUCT), #0);
- FillChar(header, sizeof(BITMAPFILEHEADER), #0);
- hF := OpenFile(PAnsiChar({$IFDEF UNICODE}AnsiString{$ELSE}string{$ENDIF}(setup.FileName)), ofs, OF_READ);
- hbm_acq := 0;
- if hF <> Longword(-1) then
- begin
- num := $8000;
- dwSize := GetFileSize(hF, nil);
- _lread(hF, @header, sizeof(BITMAPFILEHEADER));
- Dec(dwSize, sizeof(BITMAPFILEHEADER));
- if header.bfSize = 0 then
- header.bfSize := dwSize;
- hbm_acq := GlobalAlloc(GHND, header.bfSize);
- if hbm_acq <> 0 then
- begin
- ptr := GlobalLock(hbm_acq);
- //for count:=(header.bfSize-sizeof(BITMAPFILEHEADER)) downto count; count-=num, ptr+=num)
- count := header.bfSize - sizeof(BITMAPFILEHEADER);
- while count > 0 do
- begin
- if count < num then
- num := count;
- _lread(hF, ptr, num);
- Dec(count, num);
- Inc(ptr, num);
- end;
- GlobalUnlock(hbm_acq);
- GlobalFree(hbm_acq);
- end;
- _lclose(hF);
- end;
- twRC2 := lpDSM_Entry(@FappID, @FdsID, DG_CONTROL, DAT_PENDINGXFERS, MSG_ENDXFER, @twPendingXfer);
- if twRC2 <> TWRC_SUCCESS then
- DoTwMessage('DG_CONTROL / DAT_PENDINGXFERS / MSG_ENDXFER', False);
- if twPendingXfer.Count = 0 then
- Terminate;
- DoXferDone(hbm_acq);
- end;
- TWRC_CANCEL:
- begin
- // DoTwMessage('User Cancel. (DG_IMAGE/DAT_IMAGENATIVEXFER/MSG_GET)', False);
- twRC2 := lpDSM_Entry(@FappID, @FdsID, DG_CONTROL, DAT_PENDINGXFERS, MSG_ENDXFER, @twPendingXfer);
- if twRC2 <> TWRC_SUCCESS then
- DoTwMessage('DG_CONTROL/DAT_PENDINGXFERS/MSG_ENDXFER', False);
- if twPendingXfer.Count = 0 then
- Terminate;
- DoXferDone(0);
- end;
- else
- twRC2 := lpDSM_Entry(@FappID, @FdsID, DG_CONTROL, DAT_PENDINGXFERS, MSG_ENDXFER, @twPendingXfer);
- if twRC2 <> TWRC_SUCCESS then
- DoTwMessage('DG_CONTROL/DAT_PENDINGXFERS/MSG_ENDXFER', False);
- if twPendingXfer.Count = 0 then
- Terminate;
- DoXferDone(0);
- end;
- end;
- until((twPendingXfer.Count = 0) or (twRC = TWRC_FAILURE));
- end;
- procedure TCnTwain.MemoryTransfer;
- var
- twPendingXfer: TW_PENDINGXFERS;
- info: TW_IMAGEINFO;
- twRC, twRC2: TW_UINT16;
- size: TW_UINT32;
- setup: TW_SETUPMEMXFER;
- blocks, index: integer;
- hbm_acq: THandle;
- pdib: pBITMAPINFO;
- cap: TW_CAPABILITY;
- pOneV: pTW_ONEVALUE;
- Units, PixelFlavor: TW_UINT16;
- XRes, YRes: Double;
- pal: TW_PALETTE8;
- ptr: PByte;
- xfer: TW_IMAGEMEMXFER;
- begin
- FillChar(twPendingXfer, sizeof(TW_PENDINGXFERS), #0);
- FillChar(info, sizeof(TW_IMAGEINFO), #0);
- FillChar(setup, sizeof(TW_SETUPMEMXFER), #0);
- FillChar(pal, sizeof(TW_PALETTE8), #0);
- FillChar(xfer, sizeof(TW_IMAGEMEMXFER), #0);
- repeat
- twRC := lpDSM_Entry(@FappID, @FdsID, DG_IMAGE, DAT_IMAGEINFO, MSG_GET, @info);
- if twRC <> TWRC_SUCCESS then
- DoTwMessage('DG_IMAGE/DAT_IMAGEINFO/MSG_GET', False)
- else
- begin
- size := (((info.ImageWidth * info.BitsPerPixel + 31) div 8) * info.ImageLength);
- lpDSM_Entry(@FappID, @FdsID, DG_CONTROL, DAT_SETUPMEMXFER, MSG_GET, @setup);
- blocks := size div setup.Preferred;
- size := (TW_UINT32(blocks) + 1) * setup.Preferred;
- hbm_acq := GlobalAlloc(GHND, size + sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD));
- if hbm_acq = 0 then
- DoTwMessage('GlobalAlloc Failed in DoMemTransfer', False)
- else
- begin
- pdib := GlobalLock(hbm_acq);
- // fill in the image information
- pdib^.bmiHeader.biSize := sizeof(BITMAPINFOHEADER);
- pdib^.bmiHeader.biWidth := info.ImageWidth;
- pdib^.bmiHeader.biHeight := info.ImageLength;
- // Only 1 is supported
- pdib^.bmiHeader.biPlanes := 1;
- pdib^.bmiHeader.biBitCount := info.BitsPerPixel;
- // This application does not support compression
- pdib^.bmiHeader.biCompression := BI_RGB;
- pdib^.bmiHeader.biSizeImage := size;
- // Get Units and calculate PelsPerMeter
- cap.Cap := ICAP_UNITS;
- cap.ConType := TW_UINT16(TWON_DONTCARE16);
- cap.hContainer := 0;
- twRC := lpDSM_Entry(@FappID, @FdsID, DG_CONTROL, DAT_CAPABILITY, MSG_GETCURRENT, @cap);
- if twRC <> TWRC_SUCCESS then
- begin
- // raise ETwainError.Create('DG_CONTROL/DAT_CAPABILITY/MSG_GETCURRENT');
- pdib^.bmiHeader.biXPelsPerMeter := 0;
- pdib^.bmiHeader.biYPelsPerMeter := 0;
- end
- else
- begin
- pOneV := GlobalLock(cap.hContainer);
- Units := pOneV^.Item;
- GlobalUnlock(cap.hContainer);
- GlobalFree(cap.hContainer);
- XRes := FIX32ToFloat(info.XResolution);
- YRes := FIX32ToFloat(info.YResolution);
- case Units of
- TWUN_INCHES:
- begin
- pdib^.bmiHeader.biXPelsPerMeter := Trunc((XRes * 2.54) * 100);
- pdib^.bmiHeader.biYPelsPerMeter := Trunc((YRes * 2.54) * 100);
- end;
- TWUN_CENTIMETERS:
- begin
- pdib^.bmiHeader.biXPelsPerMeter := Trunc(XRes * 100);
- pdib^.bmiHeader.biYPelsPerMeter := Trunc(YRes * 100);
- end;
- else
- begin
- pdib^.bmiHeader.biXPelsPerMeter := 0;
- pdib^.bmiHeader.biYPelsPerMeter := 0;
- end;
- end;
- case info.PixelType of
- TWPT_BW:
- begin
- pdib^.bmiHeader.biClrUsed := 2;
- pdib^.bmiHeader.biClrImportant := 0;
- cap.Cap := ICAP_PIXELFLAVOR;
- cap.ConType := TW_UINT16(TWON_DONTCARE16);
- cap.hContainer := 0;
- twRC := lpDSM_Entry(@FappID, @FdsID, DG_CONTROL, DAT_CAPABILITY, MSG_GETCURRENT, @cap);
- if twRC <> TWRC_SUCCESS then
- PixelFlavor := TWPF_CHOCOLATE
- else
- begin
- if cap.ConType <> TWON_ONEVALUE then
- PixelFlavor := TWPF_CHOCOLATE
- else
- begin
- pOneV := GlobalLock(cap.hContainer);
- PixelFlavor := TW_UINT16(pOneV^.Item);
- GlobalUnlock(cap.hContainer);
- end;
- GlobalFree(cap.hContainer);
- end;
- if PixelFlavor = 0 then
- begin
- pdib^.bmiColors[0].rgbRed := 0;
- pdib^.bmiColors[0].rgbGreen := 0;
- pdib^.bmiColors[0].rgbBlue := 0;
- pdib^.bmiColors[0].rgbReserved := 0;
- index := 1;
- pdib^.bmiColors[index].rgbRed := $00FF;
- pdib^.bmiColors[index].rgbGreen := $00FF;
- pdib^.bmiColors[index].rgbBlue := $00FF;
- pdib^.bmiColors[index].rgbReserved := 0;
- end
- else
- begin
- pdib^.bmiColors[0].rgbRed := $00FF;
- pdib^.bmiColors[0].rgbGreen := $00FF;
- pdib^.bmiColors[0].rgbBlue := $00FF;
- pdib^.bmiColors[0].rgbReserved := 0;
- index := 1;
- pdib^.bmiColors[index].rgbRed := 0;
- pdib^.bmiColors[index].rgbGreen := 0;
- pdib^.bmiColors[index].rgbBlue := 0;
- pdib^.bmiColors[index].rgbReserved := 0;
- end;
- end;
- TWPT_GRAY:
- begin
- pdib^.bmiHeader.biClrUsed := 256;
- for index := 0 to 255 do
- begin
- pdib^.bmiColors[index].rgbRed := BYTE(index);
- pdib^.bmiColors[index].rgbGreen := BYTE(index);
- pdib^.bmiColors[index].rgbBlue := BYTE(index);
- pdib^.bmiColors[index].rgbReserved := 0;
- end;
- end;
- TWPT_RGB:
- pdib^.bmiHeader.biClrUsed := 0;
- else
- twRC := lpDSM_Entry(@FappID, @FdsID, DG_IMAGE, DAT_PALETTE8, MSG_GET, @pal);
- if twRC <> TWRC_SUCCESS then
- begin
- // raise ETwainError.Create('DG_IMAGE/DAT_PALETTE8/MSG_GET -- defaulting to 256 gray image palette');
- pdib^.bmiHeader.biClrImportant := 0;
- pdib^.bmiHeader.biClrUsed := 256;
- for index := 0 to pal.NumColors - 1 do
- begin
- pdib^.bmiColors[index].rgbRed := BYTE(index);
- pdib^.bmiColors[index].rgbGreen := BYTE(index);
- pdib^.bmiColors[index].rgbBlue := BYTE(index);
- pdib^.bmiColors[index].rgbReserved := 0;
- end;
- end
- else
- begin
- pdib^.bmiHeader.biClrImportant := 0;
- pdib^.bmiHeader.biClrUsed := pal.NumColors;
- for index := 0 to pal.NumColors - 1 do
- begin
- pdib^.bmiColors[index].rgbRed := pal.Colors[index].Channel1;
- pdib^.bmiColors[index].rgbGreen := pal.Colors[index].Channel2;
- pdib^.bmiColors[index].rgbBlue := pal.Colors[index].Channel3;
- pdib^.bmiColors[index].rgbReserved := 0;
- end;
- end;
- end;
- ptr := PByte(pdib);
- Inc(ptr, sizeof(BITMAPINFOHEADER));
- Inc(ptr, pdib^.bmiHeader.biClrUsed * sizeof(RGBQUAD));
- twRC := lpDSM_Entry(@FappID, @FdsID, DG_CONTROL, DAT_SETUPMEMXFER, MSG_GET, @setup);
- if twRC <> TWRC_SUCCESS then
- DoTwMessage('DG_CONTROL/DAT_SETUPMEMXFER/MSG_GET', False)
- else
- begin
- // we will use a pointer to shared memory
- xfer.Memory.Flags := TWMF_APPOWNS or TWMF_POINTER;
- xfer.Memory.Length := setup.Preferred;
- xfer.Memory.TheMem := ptr;
- // transfer the data -- loop until done or canceled
- repeat
- twRC := lpDSM_Entry(@FappID, @FdsID, DG_IMAGE, DAT_IMAGEMEMXFER, MSG_GET, @xfer);
- case twRC of
- TWRC_SUCCESS:
- begin
- Inc(ptr, xfer.BytesWritten);
- xfer.Memory.TheMem := ptr;
- end;
- TWRC_XFERDONE:
- begin
- GlobalUnlock(hbm_acq);
- FlipBitMap(FHandle, hbm_acq, info.PixelType);
- twRC2 := lpDSM_Entry(@FappID, @FdsID, DG_CONTROL, DAT_PENDINGXFERS, MSG_ENDXFER, @twPendingXfer);
- if twRC2 <> TWRC_SUCCESS then
- DoTwMessage('DG_CONTROL / DAT_PENDINGXFERS / MSG_ENDXFER', False);
- if twPendingXfer.Count = 0 then
- Terminate;
- DoXferDone(hbm_acq);
- GlobalFree(hbm_acq);
- end;
- TWRC_CANCEL:
- begin
- // DoTwMessage('User Cancel. (DG_IMAGE/DAT_IMAGENATIVEXFER/MSG_GET)', False);
- twRC2 := lpDSM_Entry(@FappID, @FdsID, DG_CONTROL, DAT_PENDINGXFERS, MSG_ENDXFER, @twPendingXfer);
- if twRC2 <> TWRC_SUCCESS then
- DoTwMessage('DG_CONTROL / DAT_PENDINGXFERS / MSG_ENDXFER', False);
- GlobalUnlock(hbm_acq);
- GlobalFree(hbm_acq);
- if twPendingXfer.Count = 0 then
- Terminate;
- DoXferDone(0);
- end;
- else
- twRC2 := lpDSM_Entry(@FappID, @FdsID, DG_CONTROL, DAT_PENDINGXFERS, MSG_ENDXFER, @twPendingXfer);
- if twRC2 <> TWRC_SUCCESS then
- DoTwMessage('DG_CONTROL / DAT_PENDINGXFERS / MSG_ENDXFER', False);
- GlobalUnlock(hbm_acq);
- GlobalFree(hbm_acq);
- if twPendingXfer.Count = 0 then
- Terminate;
- DoXferDone(0);
- end;
- until(twRC <> TWRC_SUCCESS);
- end; // if twRC <> TWRC_SUCCESS then DoTwMessage('DG_CONTROL/DAT_SETUPMEMXFER/MSG_GET', False) else begin
- end;
- end; // hbm_acq = 0
- end; // twRC <> TWRC_SUCCESS
- until twPendingXfer.count = 0;
- end;
- procedure TCnTwain.DoXferDone(hDib: THandle);
- var
- lpDib, lpBi: PBITMAPINFOHEADER;
- lpBits: Pointer;
- dwColorTableSize: TW_UINT32;
- hBitMap: TW_UINT32;
- hDibPal: THandle;
- DC: HDC;
- bmp: TBitmap;
- begin
- if not Assigned(FOnCapture) then
- Exit;
- if hDib = 0 then
- begin
- FOnCapture(Self, nil);
- Exit;
- end;
- lpDib := GlobalLock(hDib);
- if lpDib = nil then
- begin
- DoTwMessage('Could Not Lock Bitmap Memory.', False);
- Exit;
- end;
- lpBi := lpDib;
- dwColorTableSize := DibNumColors(lpDib) * sizeof(RGBQUAD);
- lpBits := lpDib;
- Inc(pByte(lpBits), lpBi^.biSize + dwColorTableSize);
- DC := GetDC(FHandle);
- hDibPal := CreateBIPalette(lpBi);
- if hDibPal <> 0 then
- begin
- SelectPalette(DC, hDibPal, False);
- RealizePalette(DC);
- end;
- if lpDib^.biBitCount = 1 then
- begin
- hBitMap := CreateBitmap(lpDib^.biWidth, lpDib^.biHeight, 1, 1, lpBits);
- if hBitMap <> 0 then
- SetDIBits(DC, hBitMap, 0, lpDib^.biHeight, lpBits, pBITMAPINFO(lpDib)^, DIB_RGB_COLORS);
- end
- else
- hBitMap := CreateDIBitmap(DC, lpDib^, CBM_INIT, lpBits, pBITMAPINFO(lpDib)^, DIB_RGB_COLORS);
- GlobalUnlock(hDib);
- ReleaseDC(FHandle, DC);
- bmp := TBitmap.Create;
- bmp.Handle := hBitMap;
- FOnCapture(Self, bmp);
- bmp.Free;
- end;
- procedure TCnTwain.DoTwMessage(Msg: string; TerminateDS: Boolean = True);
- begin
- if TerminateDS then
- Terminate;
- if Assigned(FOnTwMessage) then
- FOnTwMessage(Self, Msg);
- end;
- function TCnTwain.OpenDSM: TW_UINT16;
- begin
- Result := TWRC_FAILURE;
- if IsDSMOpen then
- Exit;
- hDSMDLL := LoadLibrary('TWAIN_32.DLL');
- if hDSMDLL <> 0 then
- @lpDSM_Entry := GetProcAddress(hDSMDLL, 'DSM_Entry');
- if (hDSMDLL = 0) or (@lpDSM_Entry = nil) then
- DoTwMessage('Error in Open, LoadLibrary, or GetProcAddress.');
- Result := lpDSM_Entry(@FAppID, nil, DG_CONTROL, DAT_PARENT, MSG_OPENDSM, @FHandle);
- if Result = TWRC_SUCCESS then
- FIsDSMOpen := True
- else
- DoTwMessage('Error Open DSM. (DG_CONTROL/DAT_PARENT/MSG_OPENDSM)');
- end;
- function TCnTwain.CloseDSM: TW_UINT16;
- begin
- Result := TWRC_FAILURE;
- if IsDSMOpen then
- begin
- Result := lpDSM_Entry(@FAppID, nil, DG_CONTROL, DAT_PARENT, MSG_CLOSEDSM, @FHandle);
- if hDSMDLL <> 0 then
- begin
- FreeLibrary(hDSMDLL);
- hDSMDLL := 0;
- end;
- if Result <> TWRC_SUCCESS then
- DoTwMessage('Error Close DSM. (DG_CONTROL/DAT_PARENT/MSG_CLOSEDSM)');
- FdsID.Id := 0;
- end;
- FIsDSMOpen := False;
- end;
- function TCnTwain.OpenDS: TW_UINT16;
- begin
- Result := TWRC_FAILURE;
- if IsDSMOpen then
- if not IsDSOpen then
- begin
- Result := lpDSM_Entry(@FAppID, nil, DG_CONTROL, DAT_IDENTITY, MSG_OPENDS, @FdsID);
- if Result = TWRC_SUCCESS then
- begin
- FIsDSOpen := True;
- HookWin;
- end
- else
- DoTwMessage('Error Open DS. (DG_CONTROL/DAT_IDENTITY/MSG_OPENDS)');
- end
- else
- DoTwMessage('Can not Open DS while It is Openning')
- else
- DoTwMessage('Can not Open DS while DSM not Openning');
- end;
- function TCnTwain.CloseDS: TW_UINT16;
- begin
- Result := TWRC_FAILURE;
- if IsDSOpen then
- if not IsDSEnabled then
- begin
- Result := lpDSM_Entry(@FAppID, nil, DG_CONTROL, DAT_IDENTITY, MSG_CLOSEDS, @FdsID);
- if Result = TWRC_SUCCESS then
- begin
- FIsDSOpen := False;
- UnHookWin;
- end
- else
- DoTwMessage('Error Close DS. (DG_CONTROL/DAT_IDENTITY/MSG_CLOSEDS)');
- FillChar(FdsID, Sizeof(TW_IDENTITY), #0);
- end
- else
- DoTwMessage('Can not Close DS while DS is Enabled');
- FIsDSOpen := False;
- end;
- function TCnTwain.XferMechDS: TW_UINT16;
- var
- cap: TW_CAPABILITY;
- pval: pTW_ONEVALUE;
- begin
- Result := TWRC_FAILURE;
- cap.Cap := ICAP_XFERMECH;
- cap.ConType := TWON_ONEVALUE;
- cap.hContainer := GlobalAlloc(GHND, Sizeof(TW_ONEVALUE));
- if cap.hContainer = 0 then
- begin
- DoTwMessage('Memory Allocation Failed. (MSG_SET/ICAP_XFERMECH)');
- Exit;
- end;
- pval := GlobalLock(cap.hContainer);
- pval^.ItemType := TWTY_UINT16;
- case FTransferType of
- doNativeTransfer:
- pval^.Item := TWSX_NATIVE;
- doFileTransfer:
- pval^.Item := TWSX_FILE;
- doMemTransfer:
- pval^.Item := TWSX_MEMORY;
- end;
- GlobalUnlock(cap.hContainer);
- Result := lpDSM_Entry(@FAppID, @FdsID, DG_CONTROL, DAT_CAPABILITY, MSG_SET, @cap);
- GlobalFree(cap.hContainer);
- if Result <> TWRC_SUCCESS then
- DoTwMessage('Error XferMech DS. (DG_CONTROL/DAT_CAPABILITY/MSG_SET)');
- end;
- function TCnTwain.AutoFeedDS: TW_UINT16;
- var
- cap: TW_CAPABILITY;
- pval: pTW_ONEVALUE;
- begin
- Result := TWRC_SUCCESS;
- if not FAutoFeed then
- Exit;
- // Get Feeder Enabled
- FillChar(cap, Sizeof(TW_CAPABILITY), 0);
- cap.Cap := CAP_FEEDERENABLED;
- cap.ConType := TWON_ONEVALUE;
- Result := lpDSM_Entry(@FAppID, @FdsID, DG_CONTROL, DAT_CAPABILITY, MSG_GET, @cap);
- if Result <> TWRC_SUCCESS then
- begin
- GlobalFree(cap.hContainer);
- DoTwMessage('Error get AutoFeed. (DG_CONTROL/DAT_CAPABILITY/MSG_GET)');
- Exit;
- end;
- pval := GlobalLock(cap.hContainer);
- if pval^.Item <> 0 then
- begin // Feeder Enabled
- GlobalUnlock(cap.hContainer);
- GlobalFree(cap.hContainer);
- end
- else
- begin
- // Set Feeder Enabled
- pval^.ItemType := TWTY_BOOL;
- pval^.Item := 1; // TRUE
- Result := lpDSM_Entry(@FAppID, @FdsID, DG_CONTROL, DAT_CAPABILITY, MSG_SET, @cap);
- GlobalFree(cap.hContainer);
- if Result = TWRC_SUCCESS then
- begin
- // Verify Feeder Enabled
- Result := lpDSM_Entry(@FAppID, @FdsID, DG_CONTROL, DAT_CAPABILITY, MSG_GET, @cap);
- if Result = TWRC_SUCCESS then
- begin
- pval := GlobalLock(cap.hContainer);
- if pval^.Item = 0 then
- Result := TWRC_FAILURE; // not set
- GlobalUnlock(cap.hContainer);
- GlobalFree(cap.hContainer);
- end
- else
- DoTwMessage('Error Get AutoFeed. (DG_CONTROL, DAT_CAPABILITY, MSG_GET)');
- end
- else
- DoTwMessage('Error Get AutoFeed. (DG_CONTROL, DAT_CAPABILITY, MSG_SET)');
- end;
- if Result = TWRC_SUCCESS then
- begin
- // Get AutoFeed
- cap.Cap := CAP_AUTOFEED;
- cap.ConType := TWON_ONEVALUE;
- Result := lpDSM_Entry(@FAppID, @FdsID, DG_CONTROL, DAT_CAPABILITY, MSG_GET, @cap);
- pval := GlobalLock(cap.hContainer);
- if pval^.Item <> 0 then
- begin // already auto feed
- GlobalUnlock(cap.hContainer);
- GlobalFree(cap.hContainer);
- end
- else
- begin
- // Set AutoFeed
- pval^.ItemType := TWTY_BOOL;
- pval^.Item := 1; // TRUE;
- GlobalUnlock(cap.hContainer);
- Result := lpDSM_Entry(@FAppID, @FdsID, DG_CONTROL, DAT_CAPABILITY, MSG_SET, @cap);
- GlobalFree(cap.hContainer);
- if Result = TWRC_SUCCESS then
- begin
- // Verify AutoFeed
- Result := lpDSM_Entry(@FAppID, @FdsID, DG_CONTROL, DAT_CAPABILITY, MSG_GET, @cap);
- if Result = TWRC_SUCCESS then
- begin
- pval := GlobalLock(cap.hContainer);
- if pval^.Item <> 0 then
- Result := TWRC_FAILURE; // not been set
- GlobalUnlock(cap.hContainer);
- GlobalFree(cap.hContainer);
- end;
- end
- else
- DoTwMessage('Error set AutoFeed. (DG_CONTROL, DAT_CAPABILITY, MSG_SET)');
- end;
- end;
- // AutoFeedBOOL := Result = TWRC_SUCCESS;
- end;
- function TCnTwain.EnableDS(Show: Boolean): TW_UINT16;
- begin
- Result := TWRC_FAILURE;
- if IsDSOpen then
- if not IsDSEnabled then
- begin
- twUI.hParent := FHandle;
- twUI.ModalUI := 0; // Mac Only..
- if Show then
- twUI.ShowUI := 1
- else
- twUI.ShowUI := 0;
- Result := lpDSM_Entry(@FAppID, @FdsID, DG_CONTROL, DAT_USERINTERFACE, MSG_ENABLEDS, @twUI);
- if Result = TWRC_SUCCESS then
- FIsDSEnabled := True
- else
- DoTwMessage('Error Enable DS. (DG_CONTROL/DAT_USERINTERFACE/MSG_ENABLEDS)');
- end
- else
- DoTwMessage('Can not Enable DS while it already Enabled')
- else
- DoTwMessage('Can not Enable DS while DS is not Openning');
- end;
- function TCnTwain.DisableDS: TW_UINT16;
- begin
- Result := TWRC_FAILURE;
- if IsDSEnabled then
- begin
- twUI.hParent := FHandle;
- twUI.ShowUI := TW_BOOL(TWON_DONTCARE8);
- Result := lpDSM_Entry(@FAppID, @FdsID, DG_CONTROL, DAT_USERINTERFACE, MSG_DISABLEDS, @twUI);
- if Result = TWRC_SUCCESS then
- FIsDSEnabled := False
- else
- DoTwMessage('Error Disable DS. (DG_CONTROL/DAT_USERINTERFACE/MSG_DISABLEDS)');
- end;
- FIsDSEnabled := False;
- end;
- function TCnTwain.SelectDS: TW_UINT16;
- var
- NewDsID: TW_IDENTITY;
- begin
- Result := TWRC_FAILURE;
- NewDsID.Id := 0;
- NewDsID.ProductName[0] := #0;
- if not IsDSOpen then
- begin
- Result := lpDSM_Entry(@FAppID, nil, DG_CONTROL, DAT_IDENTITY, MSG_USERSELECT, @NewDsID);
- if Result = TWRC_SUCCESS then
- FdsID := NewDsID;
- end
- else
- DoTwMessage('Can not Select New DS while DS is Openning');
- end;
- function TCnTwain.Acquire(Show: Boolean): TW_UINT16;
- begin
- Result := TWRC_FAILURE;
- if not IsDSMOpen then
- Result := OpenDSM;
- if Result <> TWRC_SUCCESS then
- Exit;
- if not IsDSOpen then
- Result := OpenDS;
- if Result <> TWRC_SUCCESS then
- Exit;
- Result := XferMechDS;
- if Result <> TWRC_SUCCESS then
- Exit;
- Result := AutoFeedDS;
- if Result <> TWRC_SUCCESS then
- Exit;
- if not IsDSEnabled then
- Result := EnableDS(Show);
- end;
- function TCnTwain.GetDSInfo(var DsID: TW_IDENTITY): TW_UINT16;
- begin
- Result := TWRC_FAILURE;
- if not FIsDSMOpen then
- begin
- if OpenDSM <> TWRC_SUCCESS then
- Exit;
- if OpenDS <> TWRC_SUCCESS then
- Exit;
- DsID := FDsID;
- Result := TWRC_SUCCESS;
- CloseDS;
- CloseDSM;
- end
- else // DSM Openned.
- if FIsDSOpen then
- begin
- DsID := FDsID;
- Result := TWRC_SUCCESS;
- end
- else
- begin
- if OpenDS <> TWRC_SUCCESS then
- Exit;
- DsID := FDsID;
- CloseDS;
- end;
- end;
- function TCnTwain.GetComponentInfo(var DsID: TW_IDENTITY): TW_UINT16;
- begin
- Result := TWRC_SUCCESS;
- DsID := FAppId;
- end;
- function TCnTwain.SelectSource: TW_UINT16;
- begin
- Result := TWRC_FAILURE;
- if not IsDSMOpen then
- OpenDSM;
- if IsDSOpen then
- begin //Can't Do Select While DS is Openning!
- DoTwMessage('Can''t Do Select While DS is Openning.', False);
- Exit;
- end;
- Result := SelectDS;
- if IsDSMOpen then
- CloseDSM;
- end;
- procedure TCnTwain.Terminate;
- begin
- DisableDS;
- CloseDS;
- CloseDSM;
- end;
- end.
|