/3rdparty/DelphiTwain/DelphiTwain.pas

https://bitbucket.org/reiniero/papertiger · Pascal · 2927 lines · 1889 code · 288 blank · 750 comment · 184 complexity · 571be27bc8bfc481a395d7a5b2dda35e MD5 · raw file

  1. {DELPHI IMPLEMENTATION OF TWAIN INTERFACE}
  2. {Initially created by Gustavo Daud December 2003}
  3. {This is my newest contribution for Delphi comunity, a powerfull}
  4. {implementation of latest Twain features. As you know, twain is }
  5. {the most common library to acquire images from most acquisition}
  6. {devices such as Scanners and Web-Cameras.}
  7. {Twain library is a bit different from other libraries, because}
  8. {most of the hard work can be done by a a single method. Also it}
  9. {automatically changes in the application message loop, which is}
  10. {not a simple task, at least in delphi VCL.}
  11. {It is not 100% sure to to Twain not to be installed in Windows,}
  12. {as it ships with Windows and later and with most of the }
  13. {acquisition device drivers (automatically with their installation)}
  14. {This library dynamically calls the library, avoiding the application}
  15. {hang when it is not present.}
  16. {Also, as in most of my other components, I included a trigger}
  17. {to allow the component to work without the heavy delphi VCL}
  18. {for small final executables. To enable, edit DelphiTwain.inc}
  19. {
  20. CHANGE LOG:
  21. 2014/04/29 - Fix for unloading library cancelling acquire window on Lazarus
  22. Typo fixes in language constants; cosmetic fixes.
  23. 2013/12/18 - FireMonkey support, color bug fix.
  24. 2013/08/18 - New method OnTransferComplete: fired when all documents are
  25. scanned or the scan is canceled. Thanks to Andrei Galatyn.
  26. 2013/07/26 - Color problems solved (thanks to Marco & Christian).
  27. TWAIN drivers did not respond - now both WIA and TWAIN can be used.
  28. 2012/11/01 - Ondrej Pokorny: small changes for Lazarus and 64bit compiler
  29. 2009/11/10 - Some changes to make it work in Delphi 2009, and above
  30. 2004/01/20 - Some updates and bug fixes by Nemeth Peter
  31. }
  32. unit DelphiTwain;
  33. {$I DelphiTwain.inc}
  34. interface
  35. {$IFDEF FPC}
  36. {$MODE delphi}
  37. {$ENDIF}
  38. {Used units}
  39. uses
  40. SysUtils, Windows, Messages,
  41. {$IFDEF FPC}Classes, {$ENDIF}
  42. Twain, DelphiTwainUtils;
  43. const
  44. {Name of the Twain library for 32 bits enviroment}
  45. {$IFDEF WIN64}
  46. TWAINLIBRARY: String = 'TWAINDSM.DLL';
  47. {$ELSE}
  48. TWAINLIBRARY: String = 'TWAIN_32.DLL';
  49. {$ENDIF}
  50. const
  51. {Error codes}
  52. ERROR_BASE = 300;
  53. ERROR_INT16: TW_INT16 = HIGH(TW_INT16);
  54. type
  55. {From twain}
  56. TW_STR255 = Twain.TW_STR255;
  57. {Forward declaration}
  58. TCustomDelphiTwain = class;
  59. {Component kinds}
  60. TTwainComponent = TObject;
  61. {File formats}
  62. TTwainFormat = (tfTIFF, tfPict, tfBMP, tfXBM, tfJPEG, tfFPX,
  63. tfTIFFMulti, tfPNG, tfSPIFF, tfEXIF, tfUnknown);
  64. {Twain units}
  65. TTwainUnit = (tuInches, tuCentimeters, tuPicas, tuPoints, tuTwips,
  66. tuPixels, tuUnknown);
  67. TTwainUnitSet = set of TTwainUnit;
  68. {Twain pixel flavor}
  69. TTwainPixelFlavor = (tpfChocolate, tpfVanilla, tpfUnknown);
  70. TTwainPixelFlavorSet = set of TTwainPixelFlavor;
  71. {Orientation}
  72. TTwainOrientation = (torPortrait, torLandscape);
  73. {Paper size}
  74. TTwainPaperSize = (tpsA4, tpsA5, tpsB4, tpsB5, tpsB6, tpsUSLetter, tpsUSLegal);
  75. {Twain pixel type}
  76. TTwainPixelType = (tbdBw, tbdGray, tbdRgb, tbdPalette, tbdCmy, tbdCmyk,
  77. tbdYuv, tbdYuvk, tbdCieXYZ, tbdUnknown, tbdUnknown1, tbdUnknown2, tbdBgr);
  78. TTwainPixelTypeSet = set of TTwainPixelType;
  79. {Twain bit depth}
  80. TTwainBitDepth = array of TW_UINT16;
  81. {Twain resolutions}
  82. TTwainResolution = array of Extended;
  83. {Events}
  84. TOnTwainError = procedure(Sender: TObject; const Index: Integer; ErrorCode,
  85. Additional: Integer) of object;
  86. TOnSourceNotify = procedure(Sender: TObject; const Index: Integer) of object;
  87. TOnTransferComplete = procedure(Sender: TObject; const Index: Integer; const Canceled: Boolean) of object;
  88. TOnSourceFileTransfer = procedure(Sender: TObject; const Index: Integer;
  89. Filename: TW_STR255; Format: TTwainFormat; var Cancel: Boolean) of object;
  90. {Available twain languages}
  91. TTwainLanguage = ({-1}tlUserLocale=-1, tlDanish, tlDutch, tlInternationalEnglish,
  92. tlFrenchCanadian, tlFinnish, tlFrench, tlGerman, tlIcelandic, tlItalian,
  93. tlNorwegian, tlPortuguese, tlSpanish, tlSwedish, tlUsEnglish,
  94. tlAfrikaans, tlAlbania, tlArabic, tlArabicAlgeria, tlArabicBahrain, {18}
  95. tlArabicEgypt, tlArabicIraq, tlArabJordan, tlArabicKuwait,
  96. tlArabicLebanon, tlArabicLibya, tlArabicMorocco, tlArabicOman,
  97. tlArabicQatar, tlArabicSaudiarabia, tlArabicSyria, tlArabicTunisia,
  98. tlArabicUae, tlArabicYemen, tlBasque, tlByelorussian, tlBulgarian, {35}
  99. tlCatalan, tlChinese, tlChineseHongkong, tlChinesePeoplesRepublic,
  100. tlChineseSingapore, tlChineseSimplified, tlChineseTwain, {42}
  101. tlChineseTraditional, tlCroatia, tlCzech, tlDutchBelgian, {46}
  102. tlEnglishAustralian, tlEnglishCanadian, tlEnglishIreland,
  103. tlEnglishNewZealand, tlEnglishSouthAfrica, tlEnglishUk, {52}
  104. tlEstonian, tlFaeroese, tlFarsi, tlFrenchBelgian, tlFrenchLuxembourg, {57}
  105. tlFrenchSwiss, tlGermanAustrian, tlGermanLuxembourg, tlGermanLiechtenstein,
  106. tlGermanSwiss, tlGreek, tlHebrew, tlHungarian, tlIndonesian, {66}
  107. tlItalianSwiss, tlJapanese, tlKorean, tlKoreanJohab, tlLatvian, {71}
  108. tlLithuanian, tlNorewgianBokmal, tlNorwegianNynorsk, tlPolish, {75}
  109. tlPortugueseBrazil, tlRomanian, tlRussian, tlSerbianLatin,
  110. tlSlovak, tlSlovenian, tlSpanishMexican, tlSpanishModern, tlThai,
  111. tlTurkish, tlUkranian, tlAssamese, tlBengali, tlBihari, tlBodo,
  112. tlDogri, tlGujarati {92}, tlHarayanvi, tlHindi, tlKannada, tlKashmiri,
  113. tlMalayalam, tlMarathi, tlMarwari, tlMeghalayan, tlMizo, tlNaga {102},
  114. tlOrissi, tlPunjabi, tlPushtu, tlSerbianCyrillic, tlSikkimi,
  115. tlSwedishFinland, tlTamil, tlTelugu, tlTripuri, tlUrdu, tlVietnamese);
  116. {Twain supported groups}
  117. TTwainGroups = set of (tgControl, tgImage, tgAudio);
  118. {Transfer mode for twain}
  119. TTwainTransferMode = (ttmFile, ttmNative, ttmMemory);
  120. {rect for LAYOUT; npeter 2004.01.12.}
  121. TTwainRect =
  122. record
  123. Left: double;
  124. Top: double;
  125. Right: double;
  126. Bottom: double;
  127. end;
  128. {Object to handle TW_IDENTITY}
  129. TTwainIdentity = class(TObject)
  130. private
  131. {Sets application language property}
  132. procedure SetLanguage(const Value: TTwainLanguage);
  133. {Sets text values}
  134. procedure SetString(const Index: Integer; const Value: String);
  135. {Sets avaliable groups}
  136. procedure SetGroups(const Value: TTwainGroups);
  137. protected
  138. {Structure which should be filled}
  139. Structure: TW_IDENTITY;
  140. {Returns application language property}
  141. function GetLanguage(): TTwainLanguage;
  142. {Returns text values}
  143. function GetString(const Index: integer): String;
  144. {Returns avaliable groups}
  145. function GetGroups(): TTwainGroups;
  146. public
  147. {Object being created}
  148. constructor Create;
  149. {Copy properties from another TTwainIdentity}
  150. procedure Assign(Source: TObject);
  151. public
  152. {Application major version}
  153. property MajorVersion: TW_UINT16 read Structure.Version.MajorNum
  154. write Structure.Version.MajorNum;
  155. {Application minor version}
  156. property MinorVersion: TW_UINT16 read Structure.Version.MinorNum
  157. write Structure.Version.MinorNum;
  158. {Language}
  159. property Language: TTwainLanguage read GetLanguage write SetLanguage;
  160. {Country code}
  161. property CountryCode: word read Structure.Version.Country write
  162. Structure.Version.Country;
  163. {Supported groups}
  164. property Groups: TTwainGroups read GetGroups write SetGroups;
  165. {Text values}
  166. property VersionInfo: String index 0 read GetString write
  167. SetString;
  168. {Scanner manufacturer}
  169. property Manufacturer: String index 1 read GetString write
  170. SetString;
  171. {Scanner product family}
  172. property ProductFamily: String index 2 read GetString write
  173. SetString;
  174. {Scanner product name}
  175. property ProductName: String index 3 read GetString write
  176. SetString;
  177. end;
  178. {Return set for capability retrieving/setting}
  179. TCapabilityRet = (crSuccess, crUnsupported, crBadOperation, crDependencyError,
  180. crLowMemory, crInvalidState, crInvalidContainer);
  181. {Kinds of capability retrieving}
  182. TRetrieveCap = (rcGet, rcGetCurrent, rcGetDefault, rcReset);
  183. {Capability list type}
  184. TGetCapabilityList = array of string;
  185. TSetCapabilityList = array of pointer;
  186. {Source object}
  187. TTwainSource = class(TTwainIdentity)
  188. private
  189. {Holds the item index}
  190. fIndex: Integer;
  191. {Transfer mode for the images}
  192. fTransferMode: TTwainTransferMode;
  193. {Stores if user interface should be shown}
  194. fShowUI: Boolean;
  195. {Stores if the source window is modal}
  196. fModal: Boolean;
  197. {Stores if the source is enabled}
  198. fEnabled: Boolean;
  199. {Stores if the source is loaded}
  200. fLoaded: Boolean;
  201. {Stores the owner}
  202. fOwner: TCustomDelphiTwain;
  203. {Used with property SourceManagerLoaded to test if the source manager}
  204. {is loaded or not.}
  205. function GetSourceManagerLoaded(): Boolean;
  206. {Returns a pointer to the application}
  207. function GetAppInfo(): pTW_IDENTITY;
  208. {Sets if the source is loaded}
  209. procedure SetLoaded(const Value: Boolean);
  210. {Sets if the source is enabled}
  211. procedure SetEnabled(const Value: Boolean);
  212. {Returns a pointer to the source pTW_IDENTITY}
  213. function GetStructure: pTW_IDENTITY;
  214. {Returns a resolution}
  215. function GetResolution(Capability: TW_UINT16; var Return: Extended;
  216. var Values: TTwainResolution; Mode: TRetrieveCap): TCapabilityRet;
  217. protected
  218. {Reads a native image}
  219. procedure ReadNative(Handle: TW_UINT32; var Cancel: Boolean);
  220. {Reads the file image}
  221. procedure ReadFile(Name: TW_STR255; Format: TW_UINT16; var Cancel: Boolean);
  222. {Call event for memory image}
  223. procedure ReadMemory(Image: HBitmap; var Cancel: Boolean);
  224. protected
  225. {Prepare image memory transference}
  226. function PrepareMemXfer(var BitmapHandle: HBitmap;
  227. var PixelType: TW_INT16): TW_UINT16;
  228. {Transfer image memory}
  229. function TransferImageMemory(var ImageHandle: HBitmap;
  230. {%H-}PixelType: TW_INT16): TW_UINT16;
  231. {Returns a pointer to the TW_IDENTITY for the application}
  232. property AppInfo: pTW_IDENTITY read GetAppInfo;
  233. {Method to transfer the images}
  234. procedure TransferImages();
  235. {Returns if the source manager is loaded}
  236. property SourceManagerLoaded: Boolean read GetSourceManagerLoaded;
  237. {Source configuration methods}
  238. {************************}
  239. protected
  240. {Gets an item and returns it in a string}
  241. procedure GetItem(var Return: String; ItemType: TW_UINT16; Data: Pointer);
  242. {Converts from a result to a TCapabilityRec}
  243. function ResultToCapabilityRec(const Value: TW_UINT16): TCapabilityRet;
  244. {Sets a capability}
  245. function SetCapabilityRec(const Capability, ConType: TW_UINT16;
  246. Data: HGLOBAL): TCapabilityRet;
  247. public
  248. {Message received in the event loop}
  249. function ProcessMessage(const Msg: TMsg): Boolean;
  250. {Returns a capability strucutre}
  251. function GetCapabilityRec(const Capability: TW_UINT16;
  252. var Handle: HGLOBAL; Mode: TRetrieveCap;
  253. var Container: TW_UINT16): TCapabilityRet;
  254. {************************}
  255. {Returns an one value capability}
  256. function GetOneValue(Capability: TW_UINT16;
  257. var ItemType: TW_UINT16; var Value: string;
  258. Mode: TRetrieveCap{$IFDEF DEFAULTPARAM}=rcGet{$ENDIF};
  259. MemHandle: HGLOBAL{$IFDEF DEFAULTPARAM}=0{$ENDIF}): TCapabilityRet;
  260. {Returns an range capability}
  261. function GetRangeValue(Capability: TW_UINT16; var ItemType: TW_UINT16;
  262. var Min, Max, Step, Default, Current: String;
  263. MemHandle: HGLOBAL{$IFDEF DEFAULTPARAM}=0{$ENDIF}): TCapabilityRet;
  264. {Returns an enumeration capability}
  265. function GetEnumerationValue(Capability: TW_UINT16;
  266. var ItemType: TW_UINT16; var List: TGetCapabilityList; var Current,
  267. Default: Integer; Mode: TRetrieveCap{$IFDEF DEFAULTPARAM}=rcGet{$ENDIF};
  268. MemHandle: HGLOBAL{$IFDEF DEFAULTPARAM}=0{$ENDIF}): TCapabilityRet;
  269. {Returns an array capability}
  270. function GetArrayValue(Capability: TW_UINT16; var ItemType: TW_UINT16;
  271. var List: TGetCapabilityList; MemHandle: HGLOBAL
  272. {$IFDEF DEFAULTPARAM}=0{$ENDIF}): TCapabilityRet;
  273. {************************}
  274. {Sets an one value capability}
  275. function SetOneValue(Capability: TW_UINT16; ItemType: TW_UINT16;
  276. Value: Pointer): TCapabilityRet;
  277. {Sets a range capability}
  278. function SetRangeValue(Capability, ItemType: TW_UINT16; Min, Max, Step,
  279. Current: TW_UINT32): TCapabilityRet;
  280. {Sets an enumeration capability}
  281. function SetEnumerationValue(Capability, ItemType: TW_UINT16;
  282. CurrentIndex: TW_UINT32; List: TSetCapabilityList): TCapabilityRet;
  283. {Sets an array capability}
  284. function SetArrayValue(Capability, ItemType: TW_UINT16;
  285. List: TSetCapabilityList): TCapabilityRet;
  286. public
  287. {Setup file transfer}
  288. function SetupFileTransfer(Filename: String; Format: TTwainFormat): Boolean;
  289. protected
  290. {Used with property PendingXfers}
  291. function GetPendingXfers(): TW_INT16;
  292. public
  293. {Set source transfer mode}
  294. //function ChangeTransferMode(NewMode: TTwainTransferMode): TCapabilityRet;
  295. {Transfer mode for transfering images from the source to}
  296. {the component and finally to the application}
  297. property TransferMode: TTwainTransferMode read fTransferMode write fTransferMode;
  298. public
  299. {Returns return status information}
  300. function GetReturnStatus(): TW_UINT16;
  301. {Capability setting}
  302. {Set the number of images that the application wants to receive}
  303. function SetCapXferCount(Value: SmallInt): TCapabilityRet;
  304. {Returns the number of images that the source will return}
  305. function GetCapXferCount(var Return: SmallInt;
  306. Mode: TRetrieveCap{$IFDEF DEFAULTPARAM}=rcGet{$ENDIF}): TCapabilityRet;
  307. {Retrieve the unit measure for all quantities}
  308. function GetICapUnits(var Return: TTwainUnit;
  309. var Supported: TTwainUnitSet; Mode: TRetrieveCap
  310. {$IFDEF DEFAULTPARAM}=rcGet{$ENDIF}): TCapabilityRet;
  311. {Set the unit measure}
  312. function SetICapUnits(Value: TTwainUnit): TCapabilityRet;
  313. {npeter 2004.01.12 begin}
  314. function SetImagelayoutFrame(const fLeft,fTop,fRight,
  315. fBottom: double): TCapabilityRet;
  316. function SetIndicators(Value: boolean): TCapabilityRet;
  317. {npeter 2004.01.12 end}
  318. {Retrieve the pixel flavor values}
  319. function GetIPixelFlavor(var Return: TTwainPixelFlavor;
  320. var Supported: TTwainPixelFlavorSet; Mode: TRetrieveCap
  321. {$IFDEF DEFAULTPARAM}=rcGet{$ENDIF}): TCapabilityRet;
  322. {Set the pixel flavor values}
  323. function SetIPixelFlavor(Value: TTwainPixelFlavor): TCapabilityRet;
  324. {Set orientation}
  325. function SetOrientation(Value: TTwainOrientation): TCapabilityRet;
  326. {Set paper size}
  327. function SetPaperSize(Value: TTwainPaperSize): TCapabilityRet;
  328. {Returns bitdepth values}
  329. function GetIBitDepth(var Return: Word;
  330. var Supported: TTwainBitDepth; Mode: TRetrieveCap
  331. {$IFDEF DEFAULTPARAM}=rcGet{$ENDIF}): TCapabilityRet;
  332. {Set current bitdepth value}
  333. function SetIBitDepth(Value: Word): TCapabilityRet;
  334. {Returns pixel type values}
  335. function GetIPixelType(var Return: TTwainPixelType;
  336. var Supported: TTwainPixelTypeSet; Mode: TRetrieveCap
  337. {$IFDEF DEFAULTPARAM}=rcGet{$ENDIF}): TCapabilityRet;
  338. {Set the pixel type value}
  339. function SetIPixelType(Value: TTwainPixelType): TCapabilityRet;
  340. {Returns X and Y resolutions}
  341. function GetIXResolution(var Return: Extended; var Values: TTwainResolution;
  342. Mode: TRetrieveCap {$IFDEF DEFAULTPARAM}=rcGet{$ENDIF}): TCapabilityRet;
  343. function GetIYResolution(var Return: Extended; var Values: TTwainResolution;
  344. Mode: TRetrieveCap {$IFDEF DEFAULTPARAM}=rcGet{$ENDIF}): TCapabilityRet;
  345. {Sets X and X resolutions}
  346. function SetIXResolution(Value: Extended): TCapabilityRet;
  347. function SetIYResolution(Value: Extended): TCapabilityRet;
  348. {Returns physical width and height}
  349. function GetIPhysicalWidth(var Return: Extended; Mode: TRetrieveCap
  350. {$IFDEF DEFAULTPARAM}=rcGet{$ENDIF}): TCapabilityRet;
  351. function GetIPhysicalHeight(var Return: Extended; Mode: TRetrieveCap
  352. {$IFDEF DEFAULTPARAM}=rcGet{$ENDIF}): TCapabilityRet;
  353. {Returns if user interface is controllable}
  354. function GetUIControllable(var Return: Boolean): TCapabilityRet;
  355. {Returns feeder is loaded or not}
  356. function GetFeederLoaded(var Return: Boolean): TCapabilityRet;
  357. {Returns/sets if feeder is enabled}
  358. function GetFeederEnabled(var Return: Boolean): TCapabilityRet;
  359. function SetFeederEnabled(Value: WordBool): TCapabilityRet;
  360. {Returns/sets if auto feed is enabled}
  361. function GetAutofeed(var Return: Boolean): TCapabilityRet;
  362. function SetAutoFeed(Value: WordBool): TCapabilityRet;
  363. {Returns number of pending transfer}
  364. property PendingXfers: TW_INT16 read GetPendingXfers;
  365. public
  366. {Enables the source}
  367. function EnableSource(ShowUI, Modal: Boolean): Boolean;
  368. {Disables the source}
  369. function DisableSource: Boolean;
  370. {Loads the source}
  371. function LoadSource(): Boolean;
  372. {Unloads the source}
  373. function UnloadSource(): Boolean;
  374. {Returns a pointer to the source identity}
  375. property SourceIdentity: pTW_IDENTITY read GetStructure;
  376. {Returns/sets if the source is enabled}
  377. property Enabled: Boolean read fEnabled write SetEnabled;
  378. {Returns/sets if this source is loaded}
  379. property Loaded: Boolean read fLoaded write SetLoaded;
  380. {Object being created/destroyed}
  381. constructor Create(AOwner: TCustomDelphiTwain);
  382. destructor Destroy; override;
  383. {Returns owner}
  384. property Owner: TCustomDelphiTwain read fOwner;
  385. {Source window is modal}
  386. property Modal: Boolean read fModal write fModal;
  387. {Sets if user interface should be shown}
  388. property ShowUI: Boolean read fShowUI write fShowUI;
  389. {Returns the item index}
  390. property Index: Integer read fIndex;
  391. {Convert properties from write/read to read only}
  392. {(read description on TTwainIdentity source)}
  393. property MajorVersion: TW_UINT16 read Structure.Version.MajorNum;
  394. property MinorVersion: TW_UINT16 read Structure.Version.MinorNum;
  395. property Language: TTwainLanguage read GetLanguage;
  396. property CountryCode: word read Structure.Version.Country;
  397. property Groups: TTwainGroups read GetGroups;
  398. property VersionInfo: String index 0 read GetString;
  399. property Manufacturer: String index 1 read GetString;
  400. property ProductFamily: String index 2 read GetString;
  401. property ProductName: String index 3 read GetString;
  402. end;
  403. {Component part}
  404. TCustomDelphiTwain = class(TTwainComponent)
  405. private
  406. {Should contain the number of Twain sources loaded}
  407. fSourcesLoaded: Integer;
  408. private
  409. {Event pointer holders}
  410. fOnSourceDisable: TOnSourceNotify;
  411. fOnAcquireCancel: TOnSourceNotify;
  412. fOnSourceSetupFileXfer: TOnSourceNotify;
  413. fOnSourceFileTransfer: TOnSourceFileTransfer;
  414. fOnAcquireError: TOnTwainError;
  415. fOnTransferComplete: TOnTransferComplete;
  416. private
  417. fSelectedSourceIndex: Integer;
  418. {Temp variable to allow SourceCount to be displayed in delphi}
  419. {property editor}
  420. fDummySourceCount: Integer;
  421. {Contains list of source devices}
  422. DeviceList: TPointerList;
  423. {Contains a pointer to the structure with the application}
  424. {information}
  425. AppInfo: pTW_IDENTITY;
  426. {Holds the object to allow the user to set the application information}
  427. fInfo: TTwainIdentity;
  428. {Holds the handle for the virtual window which will receive}
  429. {twain message notifications}
  430. {Will hold Twain library handle}
  431. fHandle: HInst;
  432. {Holds if the component has enumerated the devices}
  433. fHasEnumerated: Boolean;
  434. {Holds twain dll procedure handle}
  435. fTwainProc: TDSMEntryProc;
  436. {Holds the transfer mode to be used}
  437. fTransferMode: TTwainTransferMode;
  438. {Contains if the library is loaded}
  439. fLibraryLoaded: Boolean;
  440. {Contains if the source manager was loaded}
  441. fSourceManagerLoaded: Boolean;
  442. {Set to true if the host application does not create any windows}
  443. fIsConsoleApplication: Boolean;
  444. {Procedure to load and unload twain library and update property}
  445. procedure SetLibraryLoaded(const Value: Boolean);
  446. {Procedure to load or unloaded the twain source manager}
  447. procedure SetSourceManagerLoaded(const Value: Boolean);
  448. {Updates the application information object}
  449. procedure SetInfo(const Value: TTwainIdentity);
  450. {Returns the number of sources}
  451. function GetSourceCount(): Integer;
  452. {Returns a source from the list}
  453. function GetSource(Index: Integer): TTwainSource;
  454. {Finds a matching source index}
  455. function FindSource(Value: pTW_IDENTITY): Integer;
  456. //Gets selected source
  457. function GetSelectedSource: TTwainSource;
  458. //Gets selected source index
  459. function GetSelectedSourceIndex: Integer;
  460. //Sets selected source index
  461. procedure SetSelectedSourceIndex(const Value: Integer);
  462. //Refresh the VirtualWindow - usually needed when transfer was completed
  463. procedure RefreshVirtualWindow;
  464. protected
  465. fVirtualWindow: THandle;
  466. {Returns the default source}
  467. function GetDefaultSource: Integer;
  468. procedure DoCreate; virtual;
  469. procedure DoDestroy; virtual;
  470. procedure MessageTimer_Enable; virtual; abstract;
  471. procedure MessageTimer_Disable; virtual; abstract;
  472. function CustomSelectSource: Integer; virtual; abstract;
  473. function CustomGetParentWindow: TW_HANDLE; virtual; abstract;
  474. procedure DoTwainAcquire(Sender: TObject; const Index: Integer; Image:
  475. HBitmap; var Cancel: Boolean); virtual; abstract;
  476. procedure DoAcquireProgress(Sender: TObject; const Index: Integer;
  477. const Image: HBitmap; const Current, Total: Integer); virtual; abstract;
  478. public
  479. {Clears the list of sources}
  480. procedure ClearDeviceList();
  481. public
  482. {Allows Twain to display a dialog to let the user choose any source}
  483. {and returns the source index in the list}
  484. function SelectSource(): Integer;
  485. {Returns the number of loaded sources}
  486. property SourcesLoaded: Integer read fSourcesLoaded;
  487. {Enumerate the avaliable devices after Source Manager is loaded}
  488. function EnumerateDevices(): Boolean;
  489. {Object being created}
  490. constructor Create; virtual;
  491. {Object being destroyed}
  492. destructor Destroy; override;
  493. {Loads twain library and returns if it loaded sucessfully}
  494. function LoadLibrary(): Boolean;
  495. {Unloads twain and returns if it unloaded sucessfully}
  496. function UnloadLibrary(): Boolean;
  497. {Loads twain source manager}
  498. function LoadSourceManager(): Boolean;
  499. {Unloads the source manager}
  500. function UnloadSourceManager(forced: boolean): Boolean;
  501. {Returns the application TW_IDENTITY}
  502. property AppIdentity: pTW_IDENTITY read AppInfo;
  503. {Returns Twain library handle}
  504. property Handle: HInst read fHandle;
  505. {Returns virtual window that receives messages}
  506. property VirtualWindow: THandle read fVirtualWindow;
  507. {Returns a pointer to Twain only procedure}
  508. property TwainProc: TDSMEntryProc read fTwainProc;
  509. {Holds if the component has enumerated the devices}
  510. property HasEnumerated: Boolean read fHasEnumerated;
  511. {Returns a source}
  512. property Source[Index: Integer]: TTwainSource read GetSource;
  513. {Set to true if the host application does not create any windows}
  514. property IsConsoleApplication: Boolean read fIsConsoleApplication write fIsConsoleApplication default False;
  515. public
  516. {Events}
  517. {Source being disabled}
  518. property OnSourceDisable: TOnSourceNotify read fOnSourceDisable
  519. write fOnSourceDisable;
  520. {Acquire cancelled}
  521. property OnAcquireCancel: TOnSourceNotify read fOnAcquireCancel
  522. write fOnAcquireCancel;
  523. {User should set information to prepare for the file transfer}
  524. property OnSourceSetupFileXfer: TOnSourceNotify read fOnSourceSetupFileXfer
  525. write fOnSourceSetupFileXfer;
  526. {File transfered}
  527. property OnSourceFileTransfer: TOnSourceFileTransfer read
  528. fOnSourceFileTransfer write fOnSourceFileTransfer;
  529. {Acquire error}
  530. property OnAcquireError: TOnTwainError read fOnAcquireError
  531. write fOnAcquireError;
  532. {All images transfered}
  533. property OnTransferComplete: TOnTransferComplete read fOnTransferComplete
  534. write fOnTransferComplete;
  535. public
  536. {Default transfer mode to be used with sources}
  537. property TransferMode: TTwainTransferMode read fTransferMode
  538. write fTransferMode;
  539. {Returns the number of sources, after Library and Source Manager}
  540. {has being loaded}
  541. property SourceCount: Integer read GetSourceCount write fDummySourceCount;
  542. //Selected source in a dialog
  543. property SelectedSourceIndex: Integer read GetSelectedSourceIndex write SetSelectedSourceIndex;
  544. //Selected source in a dialog
  545. property SelectedSource: TTwainSource read GetSelectedSource;
  546. {User should fill the application information}
  547. property Info: TTwainIdentity read fInfo write SetInfo;
  548. {Loads or unload Twain library}
  549. property LibraryLoaded: Boolean read fLibraryLoaded write SetLibraryLoaded;
  550. {Loads or unloads the source manager}
  551. property SourceManagerLoaded: Boolean read fSourceManagerLoaded write
  552. SetSourceManagerLoaded;
  553. end;
  554. {Puts a string inside a TW_STR255}
  555. {$IFDEF UNICODE}
  556. function StrToStr255(Value: RawByteString): TW_STR255;
  557. {$ELSE}
  558. function StrToStr255(Value: String): TW_STR255;
  559. {$ENDIF}
  560. {This method returns if Twain is installed in the current machine}
  561. function IsTwainInstalled(): Boolean;
  562. {Called by Delphi to register the component}
  563. {Returns the size of a twain type}
  564. function TWTypeSize(TypeName: TW_UINT16): Integer;
  565. function MakeMsg(const Handle: THandle; uMsg: UINT; wParam: WPARAM;
  566. lParam: LPARAM): TMsg;
  567. implementation
  568. {Returns the size of a twain type}
  569. function TWTypeSize(TypeName: TW_UINT16): Integer;
  570. begin
  571. {Test the type to return the size}
  572. case TypeName of
  573. TWTY_INT8 : Result := sizeof(TW_INT8);
  574. TWTY_UINT8 : Result := sizeof(TW_UINT8);
  575. TWTY_INT16 : Result := sizeof(TW_INT16);
  576. TWTY_UINT16: Result := sizeof(TW_UINT16);
  577. TWTY_INT32 : Result := sizeof(TW_INT32);
  578. TWTY_UINT32: Result := sizeof(TW_UINT32);
  579. TWTY_FIX32 : Result := sizeof(TW_FIX32);
  580. TWTY_FRAME : Result := sizeof(TW_FRAME);
  581. TWTY_STR32 : Result := sizeof(TW_STR32);
  582. TWTY_STR64 : Result := sizeof(TW_STR64);
  583. TWTY_STR128: Result := sizeof(TW_STR128);
  584. TWTY_STR255: Result := sizeof(TW_STR255);
  585. //npeter: the following types were not implemented
  586. //especially the bool caused problems
  587. TWTY_BOOL: Result := sizeof(TW_BOOL);
  588. TWTY_UNI512: Result := sizeof(TW_UNI512);
  589. TWTY_STR1024: Result := sizeof(TW_STR1024);
  590. else Result := 0;
  591. end {case}
  592. end;
  593. {Puts a string inside a TW_STR255}
  594. {$IFDEF UNICODE}
  595. function StrToStr255(Value: RawByteString): TW_STR255;
  596. {$ELSE}
  597. function StrToStr255(Value: String): TW_STR255;
  598. {$ENDIF}
  599. begin
  600. {Clean result}
  601. Fillchar({%H-}Result, sizeof(TW_STR255), #0);
  602. {If value fits inside the TW_STR255, copy memory}
  603. if Length(Value) <= sizeof(TW_STR255) then
  604. CopyMemory(@Result[0], @Value[1], Length(Value))
  605. else CopyMemory(@Result[0], @Value[1], sizeof(TW_STR255));
  606. end;
  607. {Returns full Twain directory (usually in Windows directory)}
  608. function GetTwainDirectory(): String;
  609. var
  610. i: TDirectoryKind;
  611. Dir: String;
  612. begin
  613. {Searches in all the directories}
  614. FOR i := LOW(TDirectoryKind) TO HIGH(TDirectoryKind) DO
  615. begin
  616. {Directory to search}
  617. Dir := GetCustomDirectory(i);
  618. {Tests if the file exists in this directory}
  619. if FileExists(Dir + String(TWAINLIBRARY)) then
  620. begin
  621. {In case it exists, returns this directory and exit}
  622. {the for loop}
  623. Result := Dir;
  624. Break;
  625. end {if FileExists}
  626. end {FOR i}
  627. end;
  628. {This method returns if Twain is installed in the current machine}
  629. function IsTwainInstalled(): Boolean;
  630. begin
  631. {If GetTwainDirectory function returns an empty string, it means}
  632. {that Twain was not found}
  633. Result := (GetTwainDirectory() <> '');
  634. end;
  635. { TTwainIdentity object implementation }
  636. {Object being created}
  637. constructor TTwainIdentity.Create;
  638. begin
  639. {Allows ancestor to work}
  640. inherited Create;
  641. {Set initial properties}
  642. FillChar(Structure, sizeof(Structure), #0);
  643. Language := tlUserLocale;
  644. CountryCode := 1;
  645. MajorVersion := 1;
  646. VersionInfo := 'Application name';
  647. Structure.ProtocolMajor := TWON_PROTOCOLMAJOR;
  648. Structure.ProtocolMinor := TWON_PROTOCOLMINOR;
  649. Groups := [tgImage, tgControl];
  650. Manufacturer := 'Application manufacturer';
  651. ProductFamily := 'App product family';
  652. ProductName := 'App product name';
  653. end;
  654. {Sets a text value}
  655. procedure TTwainIdentity.SetString(const Index: Integer;
  656. const Value: String);
  657. var
  658. PropStr: PAnsiChar;
  659. begin
  660. {Select and copy pointer}
  661. case Index of
  662. 0: PropStr := @Structure.Version.Info[0];
  663. 1: PropStr := @Structure.Manufacturer[0];
  664. 2: PropStr := @Structure.ProductFamily[0];
  665. else PropStr := @Structure.ProductName[0];
  666. end {case};
  667. {Set value}
  668. Fillchar(PropStr^, sizeof(TW_STR32), #0);
  669. if Length(Value) > sizeof(TW_STR32) then
  670. CopyMemory(PropStr, @Value[1], sizeof(TW_STR32))
  671. else
  672. CopyMemory(PropStr, @Value[1], Length(Value));
  673. end;
  674. {Returns a text value}
  675. function TTwainIdentity.GetString(const Index: Integer): String;
  676. begin
  677. {Test for the required property}
  678. case Index of
  679. 0: Result := string(Structure.Version.Info);
  680. 1: Result := string(Structure.Manufacturer);
  681. 2: Result := string(Structure.ProductFamily);
  682. else Result := string(Structure.ProductName);
  683. end {case}
  684. end;
  685. {Returns application language property}
  686. function TTwainIdentity.GetLanguage(): TTwainLanguage;
  687. begin
  688. Result := TTwainLanguage(Structure.Version.Language + 1);
  689. end;
  690. {Sets application language property}
  691. procedure TTwainIdentity.SetLanguage(const Value: TTwainLanguage);
  692. begin
  693. Structure.Version.Language := Word(Value) - 1;
  694. end;
  695. {Copy properties from another TTwainIdentity}
  696. procedure TTwainIdentity.Assign(Source: TObject);
  697. begin
  698. {The source should also be a TTwainIdentity}
  699. if Source is TTwainIdentity then begin
  700. {Copy properties}
  701. Structure := TTwainIdentity(Source).Structure
  702. end;
  703. end;
  704. {Returns avaliable groups}
  705. function TTwainIdentity.GetGroups(): TTwainGroups;
  706. begin
  707. {Convert from Structure.SupportedGroups to TTwainGroups}
  708. Result := [];
  709. Include(Result, tgControl);
  710. if DG_IMAGE AND Structure.SupportedGroups <> 0 then
  711. Include(Result, tgImage);
  712. if DG_AUDIO AND Structure.SupportedGroups <> 0 then
  713. Include(Result, tgAudio);
  714. end;
  715. {Sets avaliable groups}
  716. procedure TTwainIdentity.SetGroups(const Value: TTwainGroups);
  717. begin
  718. {Convert from TTwainGroups to Structure.SupportedGroups}
  719. Structure.SupportedGroups := DG_CONTROL;
  720. if tgImage in Value then
  721. Structure.SupportedGroups := Structure.SupportedGroups or DG_IMAGE;
  722. if tgAudio in Value then
  723. Structure.SupportedGroups := Structure.SupportedGroups or DG_AUDIO;
  724. end;
  725. { TCustomDelphiTwain component implementation }
  726. {Loads twain library and returns if it loaded sucessfully}
  727. function TCustomDelphiTwain.LoadLibrary(): Boolean;
  728. var
  729. TwainDirectory: String;
  730. begin
  731. {The library must not be already loaded}
  732. if (not LibraryLoaded) then
  733. begin
  734. Result := FALSE; {Initially returns FALSE}
  735. {Searches for Twain directory}
  736. TwainDirectory := GetTwainDirectory();
  737. {Continue only if twain is installed in an known directory}
  738. if TwainDirectory <> '' then
  739. begin
  740. fHandle := Windows.LoadLibrary(PChar(TwainDirectory + TWAINLIBRARY));
  741. {If the library was sucessfully loaded}
  742. if (fHandle <> INVALID_HANDLE_VALUE) then
  743. begin
  744. {Obtains method handle}
  745. @fTwainProc := GetProcAddress(fHandle, MAKEINTRESOURCE(1));
  746. {Returns TRUE/FALSE if the method was obtained}
  747. Result := (@fTwainProc <> nil);
  748. {If the method was not obtained, also free the library}
  749. if not Result then
  750. begin
  751. {Free the handle and clears the variable}
  752. Windows.FreeLibrary(fHandle);
  753. fHandle := 0;
  754. end {if not Result}
  755. end
  756. else
  757. {If it was not loaded, clears handle value}
  758. fHandle := 0;
  759. end {if TwainDirectory <> ''};
  760. end
  761. else
  762. {If it was already loaded, returns true, since that is}
  763. {what was supposed to happen}
  764. Result := TRUE;
  765. {In case the method was sucessful, updates property}
  766. if Result then fLibraryLoaded := TRUE;
  767. end;
  768. {Unloads twain and returns if it unloaded sucessfully}
  769. function TCustomDelphiTwain.UnloadLibrary(): Boolean;
  770. begin
  771. {The library must not be already unloaded}
  772. if (LibraryLoaded) then
  773. begin
  774. {Unloads the source manager}
  775. SourceManagerLoaded := FALSE;
  776. {Just call windows method to unload}
  777. Result := Windows.FreeLibrary(Handle);
  778. {If it was sucessfull, also clears handle value}
  779. if Result then fHandle := 0;
  780. {Updates property}
  781. fLibraryLoaded := not Result;
  782. end
  783. else
  784. {If it was already unloaded, returns true, since that is}
  785. {what was supposed to happen}
  786. Result := TRUE;
  787. {In case the method was sucessful, updates property}
  788. {if Result then }fLibraryLoaded := FALSE;
  789. MessageTimer_Disable;
  790. end;
  791. {Enumerate the avaliable devices after Source Manager is loaded}
  792. function TCustomDelphiTwain.EnumerateDevices(): Boolean;
  793. var
  794. NewSource: TTwainSource;
  795. CallRes : TW_UINT16;
  796. begin
  797. {Booth library and source manager must be loaded}
  798. if (LibraryLoaded and SourceManagerLoaded) then
  799. begin
  800. {Clears the preview list of sources}
  801. ClearDeviceList();
  802. {Allocate new identity and tries to enumerate}
  803. NewSource := TTwainSource.Create(Self);
  804. CallRes := TwainProc(AppInfo, nil, DG_CONTROL, DAT_IDENTITY,
  805. MSG_GETFIRST, @NewSource.Structure);
  806. if CallRes = TWRC_SUCCESS then
  807. repeat
  808. {Add this item to the list}
  809. DeviceList.Add(NewSource);
  810. {Allocate memory for the next}
  811. NewSource := TTwainSource.Create(Self);
  812. NewSource.TransferMode := Self.TransferMode;
  813. NewSource.fIndex := DeviceList.Count;
  814. {Try to get the next item}
  815. until TwainProc(AppInfo, nil, DG_CONTROL, DAT_IDENTITY,
  816. MSG_GETNEXT, @NewSource.Structure) <> TWRC_SUCCESS;
  817. {Set that the component has enumerated the devices}
  818. {if everything went correctly}
  819. Result := TRUE;
  820. fHasEnumerated := Result;
  821. {Dispose un-needed source object}
  822. NewSource.Free;
  823. end
  824. else Result := FALSE; {If library and source manager aren't loaded}
  825. end;
  826. {Procedure to load and unload twain library and update property}
  827. procedure TCustomDelphiTwain.SetLibraryLoaded(const Value: Boolean);
  828. begin
  829. {The value must be changing to activate}
  830. if (Value <> fLibraryLoaded) then
  831. begin
  832. {Depending on the parameter load/unload the library and updates}
  833. {property whenever it loaded or unloaded sucessfully}
  834. if Value then LoadLibrary()
  835. else {if not Value then} UnloadLibrary();
  836. end {if (Value <> fLibraryLoaded)}
  837. end;
  838. {Loads twain source manager}
  839. function TCustomDelphiTwain.LoadSourceManager(): Boolean;
  840. begin
  841. {The library must be loaded}
  842. if LibraryLoaded and not SourceManagerLoaded then begin
  843. {Loads source manager}
  844. Result := (fTwainProc(AppInfo, nil, DG_CONTROL, DAT_PARENT,
  845. MSG_OPENDSM, @VirtualWindow) = TWRC_SUCCESS);
  846. end else begin
  847. {The library is not loaded, thus the source manager could}
  848. {not be loaded}
  849. Result := FALSE or SourceManagerLoaded;
  850. end;
  851. {In case the method was sucessful, updates property}
  852. if Result then fSourceManagerLoaded := TRUE;
  853. end;
  854. procedure TCustomDelphiTwain.RefreshVirtualWindow;
  855. begin
  856. //BUG WORKAROUND
  857. DoDestroy;
  858. DoCreate;
  859. if LoadLibrary then
  860. SourceManagerLoaded := True;
  861. end;
  862. {UnLoads twain source manager}
  863. function TCustomDelphiTwain.UnloadSourceManager(forced: boolean): Boolean;
  864. begin
  865. {The library must be loaded}
  866. if LibraryLoaded and SourceManagerLoaded then
  867. begin
  868. {Clears the list of sources}
  869. ClearDeviceList();
  870. {Unload source manager}
  871. if not forced then
  872. Result := (TwainProc(AppInfo, nil, DG_CONTROL, DAT_PARENT, MSG_CLOSEDSM, @VirtualWindow) = TWRC_SUCCESS)
  873. else result:=true;
  874. end
  875. else
  876. {The library is not loaded, meaning that the Source Manager isn't either}
  877. Result := TRUE;
  878. {In case the method was sucessful, updates property}
  879. if Result then fSourceManagerLoaded := FALSE;
  880. end;
  881. procedure TCustomDelphiTwain.DoCreate;
  882. begin
  883. {Create source list}
  884. DeviceList := TPointerList.Create;
  885. {Clear variables}
  886. fSourcesLoaded := 0;
  887. fHandle := 0;
  888. @fTwainProc := nil;
  889. fSourceManagerLoaded := FALSE;
  890. fHasEnumerated := FALSE;
  891. fTransferMode := ttmNative;
  892. {Creates the object to allow the user to set the application}
  893. {information to inform twain source manager and sources}
  894. fInfo := TTwainIdentity.Create;
  895. AppInfo := @fInfo.Structure;
  896. end;
  897. procedure TCustomDelphiTwain.DoDestroy;
  898. begin
  899. {Completely unload the library}
  900. LibraryLoaded := FALSE;
  901. {Free the object}
  902. fInfo.Free;
  903. {Clears and free source list}
  904. ClearDeviceList();
  905. DeviceList.Free();
  906. end;
  907. {Returns a TMsg structure}
  908. function MakeMsg(const Handle: THandle; uMsg: UINT; wParam: WPARAM;
  909. lParam: LPARAM): TMsg;
  910. begin
  911. {Fill structure with the parameters}
  912. Result.hwnd := Handle;
  913. Result.message := uMsg;
  914. Result.wParam := wParam;
  915. Result.lParam := lParam;
  916. GetCursorPos(Result.pt);
  917. end;
  918. {Procedure to load or unloaded the twain source manager}
  919. procedure TCustomDelphiTwain.SetSelectedSourceIndex(const Value: Integer);
  920. begin
  921. fSelectedSourceIndex := Value;
  922. end;
  923. procedure TCustomDelphiTwain.SetSourceManagerLoaded(const Value: Boolean);
  924. begin
  925. {The library must be loaded to have access to the method}
  926. if LibraryLoaded and (Value <> fSourceManagerLoaded) then
  927. begin
  928. {Load/unload the source manager}
  929. if Value then LoadSourceManager()
  930. else {if not Value then} UnloadSourceManager(false);
  931. end {if LibraryLoaded}
  932. end;
  933. {Clears the list of sources}
  934. procedure TCustomDelphiTwain.ClearDeviceList();
  935. var
  936. i: Integer;
  937. begin
  938. {Deallocate pTW_IDENTITY}
  939. FOR i := 0 TO DeviceList.Count - 1 DO
  940. TTwainSource(DeviceList.Item[i]).Free;
  941. {Clears the list}
  942. DeviceList.Clear;
  943. {Set trigger to tell that it has not enumerated again yet}
  944. fHasEnumerated := FALSE;
  945. end;
  946. {Finds a matching source index}
  947. function TCustomDelphiTwain.FindSource(Value: pTW_IDENTITY): Integer;
  948. var
  949. i : Integer;
  950. begin
  951. Result := -1; {Default result}
  952. {Search for this source in the list}
  953. for i := 0 TO SourceCount - 1 DO
  954. if CompareMem(@Source[i].Structure, PAnsiChar(Value), SizeOf(TW_IDENTITY)) then
  955. begin
  956. {Return index and exit}
  957. Result := i;
  958. break;
  959. end; {if CompareMem, for i}
  960. end;
  961. {Allows Twain to display a dialog to let the user choose any source}
  962. {and returns the source index in the list}
  963. function TCustomDelphiTwain.SelectSource: Integer;
  964. begin
  965. Result := -1; {Default result}
  966. {Booth library and source manager must be loaded}
  967. if (LibraryLoaded and SourceManagerLoaded) then
  968. begin
  969. Result := CustomSelectSource;
  970. SelectedSourceIndex := Result;
  971. end {(LibraryLoaded and SourceManagerLoaded)}
  972. end;
  973. {Returns the number of sources}
  974. function TCustomDelphiTwain.GetSourceCount(): Integer;
  975. begin
  976. {Library and source manager must be loaded}
  977. if (LibraryLoaded and SourceManagerLoaded) then
  978. begin
  979. {Enumerate devices, if needed}
  980. if not HasEnumerated then EnumerateDevices();
  981. {Returns}
  982. Result := DeviceList.Count;
  983. end
  984. {In case library and source manager aren't loaded, returns 0}
  985. else Result := 0
  986. end;
  987. {Returns the default source}
  988. function TCustomDelphiTwain.GetDefaultSource: Integer;
  989. var
  990. Identity: TW_IDENTITY;
  991. begin
  992. {Call twain to display the dialog}
  993. if SourceManagerLoaded and (TwainProc(AppInfo, nil, DG_CONTROL, DAT_IDENTITY,
  994. MSG_GETDEFAULT, @Identity) = TWRC_SUCCESS) then
  995. Result := FindSource(@Identity)
  996. else Result := 0 {Returns}
  997. end;
  998. {Returns a source from the list}
  999. function TCustomDelphiTwain.GetSelectedSource: TTwainSource;
  1000. begin
  1001. if SourceCount = 0 then begin
  1002. Result := nil;
  1003. end else begin
  1004. if (fSelectedSourceIndex >= 0) and (fSelectedSourceIndex < SourceCount) then
  1005. Result := Source[fSelectedSourceIndex]
  1006. else
  1007. Result := nil;
  1008. end;
  1009. end;
  1010. function TCustomDelphiTwain.GetSelectedSourceIndex: Integer;
  1011. begin
  1012. Result := fSelectedSourceIndex;
  1013. end;
  1014. function TCustomDelphiTwain.GetSource(Index: Integer): TTwainSource;
  1015. begin
  1016. {Both library and source manager must be loaded}
  1017. if (LibraryLoaded and SourceManagerLoaded) then
  1018. begin
  1019. {If index is in range, returns}
  1020. {(Call to SourceCount property enumerates the devices, if needed)}
  1021. if Index in [0..SourceCount - 1] then
  1022. Result := DeviceList.Item[Index]
  1023. else if (Index = -1) and (SourceCount > 0) then
  1024. Result := DeviceList.Item[GetDefaultSource]
  1025. {Unknown object, returns nil}
  1026. else Result := nil;
  1027. end
  1028. {In case either the library or the source manager aren't}
  1029. {loaded, it returns nil}
  1030. else Result := nil
  1031. end;
  1032. {Object being created}
  1033. constructor TCustomDelphiTwain.Create;
  1034. begin
  1035. inherited Create;
  1036. fLibraryLoaded:=false;
  1037. fSelectedSourceIndex := -1;
  1038. DoCreate;
  1039. end;
  1040. {Object being destroyed}
  1041. destructor TCustomDelphiTwain.Destroy;
  1042. begin
  1043. DoDestroy;
  1044. {Let ancestor class handle}
  1045. inherited Destroy;
  1046. end;
  1047. {Updates the application information object}
  1048. procedure TCustomDelphiTwain.SetInfo(const Value: TTwainIdentity);
  1049. begin
  1050. {Assign one object to another}
  1051. fInfo.Assign(Value);
  1052. end;
  1053. { TTwainSource object implementation }
  1054. {Used with property SourceManagerLoaded to test if the source manager}
  1055. {is loaded or not.}
  1056. function TTwainSource.GetSourceManagerLoaded: Boolean;
  1057. begin
  1058. {Obtain information from owner TCustomDelphiTwain}
  1059. Result := Owner.SourceManagerLoaded;
  1060. end;
  1061. {Sets if the source is loaded}
  1062. procedure TTwainSource.SetLoaded(const Value: Boolean);
  1063. begin
  1064. {Value should be changing}
  1065. if (Value <> fLoaded) then
  1066. begin
  1067. {Loads or unloads the source}
  1068. if Value then LoadSource()
  1069. else {if not Value then} UnloadSource();
  1070. end {if (Value <> fLoaded)}
  1071. end;
  1072. {Sets if the source is enabled}
  1073. procedure TTwainSource.SetEnabled(const Value: Boolean);
  1074. begin
  1075. {Source must be already enabled and value changing}
  1076. if (Loaded) and (Value <> fEnabled) then
  1077. begin
  1078. {Enables/disables}
  1079. if Value then EnableSource(ShowUI, Modal)
  1080. else {if not Value then} DisableSource();
  1081. end {if (Loaded) and (Value <> fEnabled)}
  1082. end;
  1083. {Enables the source}
  1084. function TTwainSource.EnableSource(ShowUI, Modal: Boolean): Boolean;
  1085. var
  1086. twUserInterface: TW_USERINTERFACE;
  1087. begin
  1088. {Source must be loaded and the value changing}
  1089. if (Loaded) and (not Enabled) then
  1090. begin
  1091. {Builds UserInterface structure}
  1092. twUserInterface.ShowUI := ShowUI;
  1093. twUserInterface.ModalUI := Modal;
  1094. twUserInterface.hParent := Owner.CustomGetParentWindow;
  1095. //npeter may be it is better to send messages to VirtualWindow
  1096. //I am not sure, but it seems more stable with a HP TWAIN driver
  1097. //it was: := GetActiveWindow;
  1098. //fEnabled := TRUE;
  1099. Owner.MessageTimer_Enable;
  1100. {Call method}
  1101. Result := (Owner.TwainProc(AppInfo, @Structure, DG_CONTROL,
  1102. DAT_USERINTERFACE, MSG_ENABLEDS, @twUserInterface) in
  1103. [TWRC_SUCCESS, TWRC_CHECKSTATUS]);
  1104. end
  1105. else {If it's either not loaded or already enabled}
  1106. {If it is not loaded}
  1107. Result := FALSE or Enabled;
  1108. {Updates property}
  1109. if (Result = TRUE) then fEnabled := TRUE;
  1110. end;
  1111. {Disables the source}
  1112. function TTwainSource.DisableSource(): Boolean;
  1113. var
  1114. twUserInterface: TW_USERINTERFACE;
  1115. begin
  1116. {Source must be loaded and the value changing}
  1117. if (Loaded) and (Enabled) then
  1118. begin
  1119. {Call method}
  1120. Result := (Owner.TwainProc(AppInfo, @Structure, DG_CONTROL,
  1121. DAT_USERINTERFACE, MSG_DISABLEDS, @twUserInterface) = TWRC_SUCCESS);
  1122. {Call notification event if being used}
  1123. if (Result) and (Assigned(Owner.OnSourceDisable)) then
  1124. Owner.OnSourceDisable(Owner, Index);
  1125. end
  1126. else {If it's either not loaded or already disabled}
  1127. {If it is not loaded}
  1128. Result := TRUE;
  1129. {Updates property}
  1130. //if (Result = TRUE) then fEnabled := FALSE;
  1131. fEnabled := False;
  1132. Owner.MessageTimer_Disable;
  1133. end;
  1134. {Loads the source}
  1135. function TTwainSource.LoadSource: Boolean;
  1136. begin
  1137. {Only loads if it is not already loaded}
  1138. if Not Loaded then
  1139. begin
  1140. Result := (Owner.TwainProc(AppInfo, nil, DG_CONTROL, DAT_IDENTITY,
  1141. MSG_OPENDS, @Structure) = TWRC_SUCCESS);
  1142. {Increase the loaded sources count variable}
  1143. if Result then inc(Owner.fSourcesLoaded);
  1144. end
  1145. else
  1146. {If it was already loaded, returns true}
  1147. Result := TRUE;
  1148. {In case the method was sucessful, updates property}
  1149. if Result then
  1150. fLoaded := TRUE;
  1151. end;
  1152. {Unloads the source}
  1153. function TTwainSource.UnloadSource: Boolean;
  1154. begin
  1155. {Only unloads if it is loaded}
  1156. if Loaded then
  1157. begin
  1158. {If the source was enabled, disable it}
  1159. DisableSource();
  1160. {Call method to load}
  1161. Result := (Owner.TwainProc(AppInfo, nil, DG_CONTROL, DAT_IDENTITY,
  1162. MSG_CLOSEDS, @Structure) = TWRC_SUCCESS);
  1163. {Decrease the loaded sources count variable}
  1164. if Result then dec(Owner.fSourcesLoaded);
  1165. end
  1166. else
  1167. {If it was already unloaded, returns true}
  1168. Result := TRUE;
  1169. {In case the method was sucessful, updates property}
  1170. fLoaded := FALSE;
  1171. end;
  1172. {Object being destroyed}
  1173. destructor TTwainSource.Destroy;
  1174. begin
  1175. {If loaded, unloads source}
  1176. UnloadSource();
  1177. {Let ancestor class process}
  1178. inherited Destroy;
  1179. end;
  1180. {Returns a pointer to the application}
  1181. function TTwainSource.GetAppInfo: pTW_IDENTITY;
  1182. begin
  1183. Result := Owner.AppInfo;
  1184. end;
  1185. {Returns a pointer to the source identity}
  1186. function TTwainSource.GetStructure: pTW_IDENTITY;
  1187. begin
  1188. Result := @Structure;
  1189. end;
  1190. {Object being created}
  1191. constructor TTwainSource.Create(AOwner: TCustomDelphiTwain);
  1192. begin
  1193. {Allows ancestor class to process}
  1194. inherited Create;
  1195. {Initial values}
  1196. fTransferMode := AOwner.TransferMode;
  1197. fLoaded := FALSE;
  1198. fShowUI := TRUE;
  1199. fEnabled := FALSE;
  1200. fModal := TRUE;
  1201. {Stores owner}
  1202. fOwner := AOwner;
  1203. end;
  1204. {Set source transfer mode}
  1205. {function TTwainSource.ChangeTransferMode(
  1206. NewMode: TTwainTransferMode): TCapabilityRet;
  1207. const
  1208. TransferModeToTwain: Array[TTwainTransferMode] of TW_UINT16 =
  1209. (TWSX_FILE, TWSX_NATIVE, TWSX_MEMORY);
  1210. var
  1211. Value: TW_UINT16;
  1212. begin
  1213. //Set transfer mode method
  1214. Value := TransferModeToTwain[NewMode];
  1215. Result := SetOneValue(ICAP_XFERMECH, TWTY_UINT16, @Value);
  1216. TransferMode := NewMode;
  1217. end;}
  1218. {Message received in the event loop}
  1219. function TTwainSource.ProcessMessage(const Msg: TMsg): Boolean;
  1220. var
  1221. twEvent: TW_EVENT;
  1222. begin
  1223. {Make twEvent structure}
  1224. twEvent.TWMessage := MSG_NULL;
  1225. twEvent.pEvent := TW_MEMREF(@Msg);
  1226. {Call Twain procedure to handle message}
  1227. Result := (Owner.TwainProc(AppInfo, @Structure, DG_CONTROL, DAT_EVENT,
  1228. MSG_PROCESSEVENT, @twEvent) = TWRC_DSEVENT);
  1229. {If it is a message from the source, process}
  1230. if Result then
  1231. case twEvent.TWMessage of
  1232. {No message from the source}
  1233. MSG_NULL: exit;
  1234. {Requested to close the source}
  1235. MSG_CLOSEDSREQ:
  1236. begin
  1237. {Call notification event}
  1238. if (Assigned(Owner.OnAcquireCancel)) then
  1239. Owner.OnAcquireCancel(Owner, Index);
  1240. if Assigned(Owner.OnTransferComplete) then
  1241. Owner.OnTransferComplete(Owner, Index, True);
  1242. {Disable the source}
  1243. DisableSource();
  1244. Owner.RefreshVirtualWindow;
  1245. end;
  1246. {Ready to transfer the images}
  1247. MSG_XFERREADY:
  1248. {Call method to transfer}
  1249. TransferImages();
  1250. MSG_CLOSEDSOK:
  1251. result:=true;
  1252. MSG_DEVICEEVENT:
  1253. result:=true;
  1254. end {case twEvent.TWMessage}
  1255. end;
  1256. {Returns return status information}
  1257. function TTwainSource.GetReturnStatus: TW_UINT16;
  1258. var
  1259. StatusInfo: TW_STATUS;
  1260. begin
  1261. {The source must be loaded in order to get the status}
  1262. if Loaded then
  1263. begin
  1264. {Call method to get the information}
  1265. Owner.TwainProc(AppInfo, @Structure, DG_CONTROL, DAT_STATUS, MSG_GET,
  1266. @StatusInfo);
  1267. Result := StatusInfo.ConditionCode;
  1268. end else Result := 0 {In case it was called while the source was not loaded}
  1269. end;
  1270. {Converts from a result to a TCapabilityRec}
  1271. function TTwainSource.ResultToCapabilityRec(
  1272. const Value: TW_UINT16): TCapabilityRet;
  1273. begin
  1274. {Test result code to return}
  1275. case Value of
  1276. {Successull, copy handle and return a success value}
  1277. TWRC_SUCCESS: Result := crSuccess;
  1278. {Error, get more on the error, and return result}
  1279. {case} else
  1280. case GetReturnStatus() of
  1281. TWCC_CAPUNSUPPORTED: Result := crUnsupported;
  1282. TWCC_CAPBADOPERATION: Result := crBadOperation;
  1283. TWCC_CAPSEQERROR: Result := crDependencyError;
  1284. TWCC_LOWMEMORY: Result := crLowMemory;
  1285. TWCC_SEQERROR: Result := crInvalidState;
  1286. else Result := crBadOperation;
  1287. end {case GetReturnStatus of}
  1288. end {case};
  1289. end;
  1290. {Sets a capability}
  1291. function TTwainSource.SetCapabilityRec(const Capability,
  1292. ConType: TW_UINT16; Data: HGlobal): TCapabilityRet;
  1293. var
  1294. CapabilityInfo: TW_CAPABILITY;
  1295. begin
  1296. {Source must be loaded to set}
  1297. if Loaded then
  1298. begin
  1299. {Fill structure}
  1300. CapabilityInfo.Cap := Capability;
  1301. CapabilityInfo.ConType := ConType;
  1302. CapabilityInfo.hContainer := Data;
  1303. {Call method and store return}
  1304. Result := ResultToCapabilityRec(Owner.TwainProc(AppInfo, @Structure,
  1305. DG_CONTROL, DAT_CAPABILITY, MSG_SET, @CapabilityInfo));
  1306. end
  1307. else Result := crInvalidState {In case the source is not loaded}
  1308. end;
  1309. {Returns a capability strucutre}
  1310. function TTwainSource.GetCapabilityRec( const Capability: TW_UINT16;
  1311. var Handle: HGLOBAL; Mode: TRetrieveCap;
  1312. var Container: TW_UINT16): TCapabilityRet;
  1313. const
  1314. ModeToTwain: Array[TRetrieveCap] of TW_UINT16 = (MSG_GET, MSG_GETCURRENT,
  1315. MSG_GETDEFAULT, MSG_RESET);
  1316. var
  1317. CapabilityInfo: TW_CAPABILITY;
  1318. begin
  1319. {Source must be loaded}
  1320. if Loaded then
  1321. begin
  1322. {Fill structure}
  1323. CapabilityInfo.Cap := Capability;
  1324. CapabilityInfo.ConType := TWON_DONTCARE16;
  1325. CapabilityInfo.hContainer := 0;
  1326. {Call method and store return}
  1327. Result := ResultToCapabilityRec(Owner.TwainProc(AppInfo, @Structure,
  1328. DG_CONTROL, DAT_CAPABILITY, ModeToTwain[Mode], @CapabilityInfo));
  1329. if Result = crSuccess then
  1330. begin
  1331. Handle := CapabilityInfo.hContainer;
  1332. Container := CapabilityInfo.ConType;
  1333. end
  1334. end {if not Loaded}
  1335. else Result := crInvalidState {In case the source is not loaded}
  1336. end;
  1337. {Gets an item and returns it in a string}
  1338. procedure TTwainSource.GetItem(var Return: String; ItemType: TW_UINT16;
  1339. Data: Pointer);
  1340. begin
  1341. {Test the item type}
  1342. case ItemType of
  1343. TWTY_INT8 : Return := IntToStr(pTW_INT8(Data)^);
  1344. TWTY_UINT8 : Return := IntToStr(pTW_UINT8(Data)^);
  1345. TWTY_INT16,
  1346. 44 {TWTY_HANDLE} : Return := IntToStr(pTW_INT16(Data)^);
  1347. TWTY_UINT16,
  1348. TWTY_BOOL : Return := IntToStr(pTW_UINT16(Data)^);
  1349. TWTY_INT32 : Return := IntToStr(pTW_INT32(Data)^);
  1350. TWTY_UINT32,
  1351. 43 {TWTY_MEMREF} : Return := IntToStr(pTW_UINT32(Data)^);
  1352. {Floating integer type}
  1353. TWTY_FIX32:
  1354. with pTW_FIX32(Data)^ do
  1355. //npeter bugfix:
  1356. //it is better to use the actual decimal separator
  1357. //and not a wired in value!
  1358. //If not, you may get error on strtofloat
  1359. //original: Return := IntToStr(Whole) + ',' + IntToStr(Frac);
  1360. Return := IntToStr(Whole) + {%H-}{$IFDEF DELPHI_XE2_UP}FormatSettings.{$ENDIF}DecimalSeparator + IntToStr(Frac);
  1361. {String types, which are all ended by a null char (#0)}
  1362. TWTY_STR32,
  1363. TWTY_STR64,
  1364. TWTY_STR128,
  1365. TWTY_STR255 : Return := String(PAnsiChar(Data));
  1366. end {case ItemType}
  1367. end;
  1368. {Returns an array capability}
  1369. function TTwainSource.GetArrayValue(Capability: TW_UINT16;
  1370. var ItemType: TW_UINT16; var List: TGetCapabilityList;
  1371. MemHandle: HGLOBAL): TCapabilityRet;
  1372. var
  1373. ArrayV : pTW_ARRAY;
  1374. ItemSize : Integer;
  1375. Data : PAnsiChar;//ccc
  1376. CurItem : Integer;
  1377. Value : String;
  1378. Container: TW_UINT16;
  1379. begin
  1380. {Call method to get the memory to the return}
  1381. if MemHandle = 0 then
  1382. Result := GetCapabilityRec(Capability, MemHandle, rcGet, {%H-}Container)
  1383. else
  1384. begin
  1385. Result := crSuccess;
  1386. Container := TWON_ARRAY;
  1387. end;
  1388. if (Result = crSuccess) and (Container <> TWON_ARRAY) then
  1389. begin
  1390. Result := crInvalidContainer;
  1391. GlobalFree(MemHandle);
  1392. Exit;
  1393. end;
  1394. {If result was sucessfull and memory was allocated}
  1395. if (Result = crSuccess) then
  1396. begin
  1397. {Obtain structure pointer}
  1398. ArrayV := GlobalLock(MemHandle);
  1399. {Fill return properties}
  1400. ItemType := ArrayV^.ItemType;
  1401. {Prepare to list items}
  1402. ItemSize := TWTypeSize(ItemType);
  1403. Data := @ArrayV^.ItemList[0];
  1404. SetLength(List, ArrayV^.NumItems);
  1405. {Copy items}
  1406. for CurItem := 0 TO ArrayV^.NumItems - 1 do
  1407. begin
  1408. {Obtain this item}
  1409. GetItem({%H-}Value, ItemType, Data);
  1410. List[CurItem] := Value;
  1411. {Move memory to the next}
  1412. inc(Data, ItemSize);
  1413. end;
  1414. {Unlock memory and unallocate}
  1415. GlobalUnlock(MemHandle);
  1416. GlobalFree(MemHandle);
  1417. end {if (Result = crSuccess)}
  1418. end;
  1419. {Returns an enumeration capability}
  1420. function TTwainSource.GetEnumerationValue(Capability: TW_UINT16;
  1421. var ItemType: TW_UINT16; var List: TGetCapabilityList;
  1422. var Current, Default: Integer; Mode: TRetrieveCap;
  1423. MemHandle: HGLOBAL): TCapabilityRet;
  1424. var
  1425. EnumV : pTW_ENUMERATION;
  1426. ItemSize : Integer;
  1427. Data : PAnsiChar;//ccc
  1428. CurItem : Integer;
  1429. Value : String;
  1430. Container: TW_UINT16;
  1431. begin
  1432. {Call method to get the memory to the return}
  1433. if MemHandle = 0 then
  1434. Result := GetCapabilityRec(Capability, MemHandle, Mode, {%H-}Container)
  1435. else
  1436. begin
  1437. Result := crSuccess;
  1438. Container := TWON_ENUMERATION;
  1439. end;
  1440. if (Result = crSuccess) and (Container <> TWON_ENUMERATION) then
  1441. begin
  1442. Result := crInvalidContainer;
  1443. GlobalFree(MemHandle);
  1444. Exit;
  1445. end;
  1446. {If result was sucessfull and memory was allocated}
  1447. if (Result = crSuccess) then
  1448. begin
  1449. {Obtain structure pointer}
  1450. EnumV := GlobalLock(MemHandle);
  1451. {Fill return properties}
  1452. Current := EnumV^.CurrentIndex;
  1453. Default := EnumV^.DefaultIndex;
  1454. ItemType := EnumV^.ItemType;
  1455. {Prepare to list items}
  1456. ItemSize := TWTypeSize(ItemType);
  1457. Data := @EnumV^.ItemList[0];
  1458. SetLength(List, EnumV^.NumItems);
  1459. {Copy items}
  1460. for CurItem := 0 TO EnumV^.NumItems - 1 do
  1461. begin
  1462. {Obtain this item}
  1463. GetItem({%H-}Value, ItemType, Data);
  1464. List[CurItem] := Value;
  1465. {Move memory to the next}
  1466. inc(Data, ItemSize);
  1467. end;
  1468. {Unlock memory and unallocate}
  1469. GlobalUnlock(MemHandle);
  1470. GlobalFree(MemHandle);
  1471. end {if (Result = crSuccess)}
  1472. end;
  1473. {Returns a range capability}
  1474. function TTwainSource.GetRangeValue(Capability: TW_UINT16;
  1475. var ItemType: TW_UINT16; var Min, Max, Step, Default,
  1476. Current: String; MemHandle: HGLOBAL): TCapabilityRet;
  1477. var
  1478. RangeV : pTW_RANGE;
  1479. Container: TW_UINT16;
  1480. begin
  1481. {Call method to get the memory to the return}
  1482. if MemHandle = 0 then
  1483. Result := GetCapabilityRec(Capability, MemHandle, rcGet, {%H-}Container)
  1484. else
  1485. begin
  1486. Result := crSuccess;
  1487. Container := TWON_RANGE;
  1488. end;
  1489. if (Result = crSuccess) and (Container <> TWON_RANGE) then
  1490. begin
  1491. Result := crInvalidContainer;
  1492. GlobalFree(MemHandle);
  1493. Exit;
  1494. end;
  1495. {If result was sucessfull and memory was allocated}
  1496. if (Result = crSuccess) then
  1497. begin
  1498. {Obtain structure pointer}
  1499. RangeV := GlobalLock(MemHandle);
  1500. {Fill return}
  1501. ItemType := RangeV^.ItemType;
  1502. GetItem(Min, ItemType, @RangeV^.MinValue);
  1503. GetItem(Max, ItemType, @RangeV^.MaxValue);
  1504. GetItem(Step, ItemType, @RangeV^.StepSize);
  1505. GetItem(Default, ItemType, @RangeV^.DefaultValue);
  1506. GetItem(Current, ItemType, @RangeV^.CurrentValue);
  1507. {Unlock memory and unallocate}
  1508. GlobalUnlock(MemHandle);
  1509. GlobalFree(MemHandle);
  1510. end {if (Result = crSuccess)}
  1511. end;
  1512. {Returns an one value capability}
  1513. function TTwainSource.GetOneValue(Capability: TW_UINT16;
  1514. var ItemType: TW_UINT16; var Value: String;
  1515. Mode: TRetrieveCap; MemHandle: HGLOBAL): TCapabilityRet;
  1516. var
  1517. OneV : pTW_ONEVALUE;
  1518. Container: TW_UINT16;
  1519. begin
  1520. {Call method to get the memory to the return}
  1521. if MemHandle = 0 then
  1522. Result := GetCapabilityRec(Capability, MemHandle, Mode, {%H-}Container)
  1523. else
  1524. begin
  1525. Result := crSuccess;
  1526. Container := TWON_ONEVALUE;
  1527. end;
  1528. if (Result = crSuccess) and (Container <> TWON_ONEVALUE) then
  1529. begin
  1530. Result := crInvalidContainer;
  1531. GlobalFree(MemHandle);
  1532. Exit;
  1533. end;
  1534. {If result was sucessfull and memory was allocated}
  1535. if (Result = crSuccess) then
  1536. begin
  1537. {Obtain structure pointer}
  1538. OneV := GlobalLock(MemHandle);
  1539. {Fill return}
  1540. ItemType := OneV^.ItemType;
  1541. GetItem(Value, OneV^.ItemType, @OneV^.Item);
  1542. {Unlock memory and unallocate}
  1543. GlobalUnlock(MemHandle);
  1544. GlobalFree(MemHandle);
  1545. end {if (Result = crSuccess)}
  1546. end;
  1547. {Sets an one value capability}
  1548. function TTwainSource.SetOneValue(Capability: TW_UINT16;
  1549. ItemType: TW_UINT16; Value: Pointer): TCapabilityRet;
  1550. var
  1551. Data: HGLOBAL;
  1552. OneV: pTW_ONEVALUE;
  1553. ItemSize,ItemSize2: Integer;
  1554. begin
  1555. {Allocate enough memory for the TW_ONEVALUE and obtain pointer}
  1556. ItemSize := TWTypeSize(ItemType);
  1557. //npeter: TW_ONEVALUE minimal size !!!
  1558. //I think to meet the specifications the
  1559. //Item's size must be at least sizeof(TW_UINT32)!
  1560. //when I did it, some mistic errors on some drivers went gone
  1561. if ItemSize<TWTypeSize(TWTY_UINT32) then ItemSize2:=TWTypeSize(TWTY_UINT32) else ItemSize2:=ItemSize;
  1562. Data := GlobalAlloc(GHND, sizeof({%H-}OneV^.ItemType) + ItemSize2);
  1563. OneV := GlobalLock(Data);
  1564. {Fill value}
  1565. OneV^.ItemType := ItemType;
  1566. CopyMemory(@OneV^.Item, Value, ItemSize);
  1567. GlobalUnlock(Data);
  1568. {Call method to set}
  1569. Result := SetCapabilityRec(Capability, TWON_ONEVALUE, Data);
  1570. {Unload memory}
  1571. GlobalFree(Data);
  1572. end;
  1573. function TTwainSource.SetOrientation(Value: TTwainOrientation): TCapabilityRet;
  1574. const Transfer: array [TTwainOrientation] of TW_UINT16 = (TWOR_PORTRAIT, TWOR_LANDSCAPE);
  1575. var iValue: TW_UINT16;
  1576. begin
  1577. iValue:=Transfer[value];
  1578. Result := SetOneValue(ICAP_ORIENTATION, TWTY_UINT16, @iValue);
  1579. end;
  1580. function TTwainSource.SetPaperSize(Value: TTwainPaperSize): TCapabilityRet;
  1581. //(tpsA4, tpsA5, tpsB4, tpsB5, tpsB6, tpsUSLetter, tpsUSLegal);
  1582. const Transfer: array [TTwainPaperSize] of TW_UINT16 = (TWSS_A4LETTER, TWSS_A5, TWSS_B4, TWSS_B5LETTER, TWSS_B6, TWSS_USLETTER, TWSS_USLEGAL);
  1583. var iValue: TW_UINT16;
  1584. begin
  1585. iValue:=Transfer[value];
  1586. Result := SetOneValue(ICAP_SUPPORTEDSIZES, TWTY_UINT16, @iValue);
  1587. end;
  1588. {Sets a range capability}
  1589. function TTwainSource.SetRangeValue(Capability: TW_UINT16;
  1590. ItemType: TW_UINT16; Min, Max, Step, Current: TW_UINT32): TCapabilityRet;
  1591. var
  1592. Data: HGLOBAL;
  1593. RangeV: pTW_RANGE;
  1594. begin
  1595. {Allocate enough memory for the TW_RANGE and obtain pointer}
  1596. Data := GlobalAlloc(GHND, sizeof(TW_RANGE));
  1597. RangeV := GlobalLock(Data);
  1598. {Fill value}
  1599. RangeV^.ItemType := ItemType;
  1600. RangeV^.MinValue := Min;
  1601. RangeV^.MaxValue := Max;
  1602. RangeV^.StepSize := Step;
  1603. RangeV^.CurrentValue := Current;
  1604. GlobalUnlock(Data);
  1605. {Call method to set}
  1606. Result := SetCapabilityRec(Capability, TWON_RANGE, Data);
  1607. {Unload memory}
  1608. GlobalFree(Data);
  1609. end;
  1610. {Sets an array capability}
  1611. function TTwainSource.SetArrayValue(Capability: TW_UINT16;
  1612. ItemType: TW_UINT16; List: TSetCapabilityList): TCapabilityRet;
  1613. var
  1614. Data: HGLOBAL;
  1615. EnumV: pTW_ENUMERATION;
  1616. i, ItemSize: Integer;
  1617. DataPt: PAnsiChar;//ccc
  1618. begin
  1619. {Allocate enough memory for the TW_ARRAY and obtain pointer}
  1620. ItemSize := TWTypeSize(ItemType);
  1621. Data := GlobalAlloc(GHND, sizeof(TW_ARRAY) + ItemSize * Length(List));
  1622. EnumV := GlobalLock(Data);
  1623. {Fill values}
  1624. EnumV^.ItemType := ItemType;
  1625. EnumV^.NumItems := Length(List);
  1626. {Copy item values}
  1627. DataPt := @EnumV^.ItemList[0];
  1628. for i := Low(List) TO High(List) do
  1629. begin
  1630. {Copy item}
  1631. CopyMemory(DataPt, List[i], ItemSize);
  1632. {Move to next item}
  1633. inc(DataPt, ItemSize);
  1634. end;
  1635. GlobalUnlock(Data);
  1636. {Call method to set}
  1637. Result := SetCapabilityRec(Capability, TWON_ARRAY, Data);
  1638. {Unload memory}
  1639. GlobalFree(Data);
  1640. end;
  1641. {Sets an enumeration capability}
  1642. function TTwainSource.SetEnumerationValue(Capability: TW_UINT16;
  1643. ItemType: TW_UINT16; CurrentIndex: TW_UINT32;
  1644. List: TSetCapabilityList): TCapabilityRet;
  1645. var
  1646. Data: HGLOBAL;
  1647. EnumV: pTW_ENUMERATION;
  1648. i, ItemSize: Integer;
  1649. DataPt: PAnsiChar;//ccc
  1650. begin
  1651. {Allocate enough memory for the TW_ENUMERATION and obtain pointer}
  1652. ItemSize := TWTypeSize(ItemType);
  1653. Data := GlobalAlloc(GHND, sizeof(TW_ENUMERATION) + ItemSize * Length(List));
  1654. EnumV := GlobalLock(Data);
  1655. {Fill values}
  1656. EnumV^.ItemType := ItemType;
  1657. EnumV^.NumItems := Length(List);
  1658. EnumV^.CurrentIndex := CurrentIndex;
  1659. {Copy item values}
  1660. DataPt := @EnumV^.ItemList[0];
  1661. for i := Low(List) TO High(List) do
  1662. begin
  1663. {Copy item}
  1664. CopyMemory(DataPt, List[i], ItemSize);
  1665. {Move to next item}
  1666. inc(DataPt, ItemSize);
  1667. end;
  1668. GlobalUnlock(Data);
  1669. {Call method to set}
  1670. Result := SetCapabilityRec(Capability, TWON_ENUMERATION, Data);
  1671. {Unload memory}
  1672. GlobalFree(Data);
  1673. end;
  1674. {Transfer image memory}
  1675. function TTwainSource.TransferImageMemory(var ImageHandle: HBitmap;
  1676. PixelType: TW_INT16): TW_UINT16;
  1677. var
  1678. {Memory buffer information from the source}
  1679. Setup : TW_SETUPMEMXFER;
  1680. {Memory information from the image}
  1681. Xfer : TW_IMAGEMEMXFER;
  1682. {Image processing variables}
  1683. ImageInfo : Windows.TBitmap;
  1684. Ptr : PAnsiChar;//ccc
  1685. LineLength,
  1686. CurLine: Cardinal;
  1687. LinePtr,
  1688. AllocPtr : pointer;
  1689. DataSize,
  1690. Readed: Cardinal;
  1691. Index : Cardinal;
  1692. ItemPtr : pRGBTriple;
  1693. Temp : Byte;
  1694. begin
  1695. {Obtain information on the transference buffers}
  1696. Result := Owner.TwainProc(AppInfo, @Structure, DG_CONTROL, DAT_SETUPMEMXFER,
  1697. MSG_GET, @Setup);
  1698. {Get information on the bitmap}
  1699. GetObject(ImageHandle, sizeof(Windows.TBitmap), @ImageInfo);
  1700. LineLength := (((ImageInfo.bmWidth * ImageInfo.bmBitsPixel + 31) div 32) * 4);
  1701. {Get pointer for the last line}
  1702. CurLine := ImageInfo.bmHeight - 1;
  1703. {%H-}DTNativeUInt(LinePtr) := DTNativeUInt(ImageInfo.bmBits) + LineLength * CurLine;
  1704. Ptr := LinePtr;
  1705. DataSize := 0;
  1706. {Prepare buffer record to transfer}
  1707. Fillchar({%H-}Xfer, SizeOf(TW_IMAGEMEMXFER), $FF);
  1708. Xfer.Memory.Flags := TWMF_APPOWNS or TWMF_POINTER;
  1709. Xfer.Memory.Length := Setup.Preferred;
  1710. GetMem(AllocPtr, Setup.Preferred);
  1711. Xfer.Memory.TheMem := AllocPtr;
  1712. {Transfer data until done or cancelled}
  1713. if Result = TWRC_SUCCESS then begin
  1714. repeat
  1715. {Retrieve another piece of memory to the pointer}
  1716. Xfer.BytesWritten := 0;
  1717. Result := Owner.TwainProc(AppInfo, @Structure, DG_IMAGE,
  1718. DAT_IMAGEMEMXFER, MSG_GET, @Xfer);
  1719. {Test the result}
  1720. {Piece sucessfully transfer, move to next}
  1721. if (Result = TWRC_SUCCESS) or (Result = TWRC_XFERDONE) then
  1722. begin
  1723. {While we have data}
  1724. while Xfer.BytesWritten > 0 do
  1725. begin
  1726. {In case the total bytes received now have more than we}
  1727. {need to complete the line}
  1728. if Xfer.BytesWritten + DataSize > LineLength then
  1729. begin
  1730. Readed := LineLength - DataSize;
  1731. CopyMemory(Ptr, Xfer.Memory.TheMem, LineLength - DataSize);
  1732. end
  1733. else
  1734. {Otherwise, continue completing the line}
  1735. begin
  1736. Readed := Xfer.BytesWritten;
  1737. CopyMemory(Ptr, Xfer.Memory.TheMem, Readed);
  1738. end;
  1739. {Adjust}
  1740. inc(DataSize, Readed); inc(Ptr, Readed);
  1741. dec(Xfer.BytesWritten, Readed);
  1742. {%H-}DTNativeUInt(Xfer.Memory.TheMem) :=
  1743. {%H-}DTNativeUInt(Xfer.Memory.TheMem) + Readed;
  1744. {Reached end of line}
  1745. if (DataSize >= LineLength) then
  1746. begin
  1747. {Fix RGB to BGR}
  1748. if PixelType = TWPT_RGB then
  1749. begin
  1750. ItemPtr := LinePtr;
  1751. FOR Index := 1 TO ImageInfo.bmWidth DO
  1752. begin
  1753. Temp := ItemPtr^.rgbtRed;
  1754. ItemPtr^.rgbtRed := ItemPtr^.rgbtBlue;
  1755. ItemPtr^.rgbtBlue := Temp;
  1756. inc(ItemPtr);
  1757. end {FOR Index};
  1758. end {if PixelType = TWPT_RGB};
  1759. {Adjust pointers}
  1760. {%H-}DTNativeUInt(LinePtr) := {%H-}DTNativeUInt(LinePtr) - LineLength;
  1761. Ptr := LinePtr; dec(CurLine); DataSize := 0;
  1762. {Call event}
  1763. Owner.DoAcquireProgress(Self, Self.Index, ImageHandle,
  1764. Cardinal(ImageInfo.bmHeight) - CurLine - 1,
  1765. ImageInfo.bmHeight - 1);
  1766. end {if DataSize >= LineLength}
  1767. end {while Xfer.BytesWritten > 0};
  1768. {Set again pointer to write to}
  1769. Xfer.Memory.TheMem := AllocPtr;
  1770. end {TWRC_SUCCESS};
  1771. until Result <> TWRC_SUCCESS;
  1772. end;
  1773. {Free allocated memory}
  1774. FreeMem(AllocPtr, Setup.Preferred);
  1775. {Some error ocurred, free memory and returns}
  1776. if Result <> TWRC_XFERDONE then
  1777. DeleteObject(ImageHandle);
  1778. end;
  1779. {Prepare image memory transference}
  1780. function TTwainSource.PrepareMemXfer(var BitmapHandle: HBitmap;
  1781. var PixelType: TW_INT16): TW_UINT16;
  1782. const
  1783. PixelColor: Array[TTwainPixelFlavor] of Array[0..1] of Byte =
  1784. ((0, $FF), ($FF, 00), (0, $FF));
  1785. var
  1786. Handle: HGlobal;
  1787. Info: TW_IMAGEINFO;
  1788. Setup: TW_SETUPMEMXFER;
  1789. structsize, index, Size, Blocks: Integer;
  1790. XRes, YRes: Extended;
  1791. Pal : TW_PALETTE8;
  1792. vUnit : TTwainUnit;
  1793. vUnits: TTwainUnitSet;
  1794. Dib : pBitmapInfo;
  1795. PixelFlavor: TTwainPixelFlavor;
  1796. PixelFlavors: TTwainPixelFlavorSet;
  1797. DC: HDC;
  1798. Data : Pointer;
  1799. begin
  1800. {First of all, get information on the image being acquired}
  1801. Result := Owner.TwainProc(AppInfo, @Structure, DG_IMAGE, DAT_IMAGEINFO,
  1802. MSG_GET, @Info);
  1803. if Result <> TWRC_SUCCESS then exit;
  1804. {Calculate image size}
  1805. with Info do
  1806. size := ((((ImageWidth * BitsPerPixel + 31) div 32)*4) * info.ImageLength);
  1807. {Obtain image buffer transference sizes}
  1808. Owner.TwainProc(AppInfo, @Structure, DG_CONTROL, DAT_SETUPMEMXFER,
  1809. MSG_GET, @Setup);
  1810. blocks := (size div Integer(setup.Preferred));
  1811. size := (blocks + 1) * Integer(setup.Preferred);
  1812. {Prepare new bitmap}
  1813. structsize := size + sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD);
  1814. Handle := GlobalAlloc(GHND, StructSize);
  1815. Dib := GlobalLock(Handle);
  1816. Fillchar(Dib^, structsize, #0);
  1817. {Fill image information}
  1818. Dib^.bmiHeader.biSize := sizeof(BITMAPINFOHEADER);
  1819. Dib^.bmiHeader.biWidth := info.ImageWidth;
  1820. Dib^.bmiHeader.biHeight := info.ImageLength;
  1821. {Only 1 plane supported}
  1822. Dib^.bmiHeader.biPlanes := 1;
  1823. Dib^.bmiHeader.biBitCount := info.BitsPerPixel;
  1824. {No compression}
  1825. Dib^.bmiHeader.biCompression := BI_RGB;
  1826. Dib^.bmiHeader.biSizeImage := Size;
  1827. {Adjust units}
  1828. XRes := Fix32ToFloat(Info.XResolution);
  1829. YRes := Fix32ToFloat(Info.YResolution);
  1830. GetICapUnits({%H-}vUnit, {%H-}vUnits);
  1831. case vUnit of
  1832. tuInches: begin
  1833. Dib^.bmiHeader.biXPelsPerMeter := Trunc((XRes*2.54)*100);
  1834. Dib^.bmiHeader.biYPelsPerMeter := Trunc((YRes*2.54)*100);
  1835. end;
  1836. tuCentimeters: begin
  1837. Dib^.bmiHeader.biXPelsPerMeter := Trunc(XRes*100);
  1838. Dib^.bmiHeader.biYPelsPerMeter := Trunc(YRes*100);
  1839. end
  1840. else begin
  1841. Dib^.bmiHeader.biXPelsPerMeter := 0;
  1842. Dib^.bmiHeader.biYPelsPerMeter := 0;
  1843. end
  1844. end {case vUnits of};
  1845. {Now it should setup the palette to be used by the image}
  1846. {by either building a definied palette or retrieving the}
  1847. {image's one}
  1848. case (Info.PixelType) of
  1849. TWPT_BW:
  1850. begin
  1851. {Only two colors are used}
  1852. Dib^.bmiHeader.biClrUsed := 2;
  1853. Dib^.bmiHeader.biClrImportant := 0;
  1854. {Try obtaining the pixel flavor}
  1855. if GetIPixelFlavor({%H-}PixelFlavor, {%H-}PixelFlavors) <> crSuccess then
  1856. PixelFlavor := tpfChocolate;
  1857. {Set palette colors}
  1858. for Index := 0 to 1 do
  1859. begin
  1860. Dib^.bmiColors[Index].rgbRed := PixelColor[PixelFlavor][Index];
  1861. Dib^.bmiColors[Index].rgbGreen := PixelColor[PixelFlavor][Index];
  1862. Dib^.bmiColors[Index].rgbBlue := PixelColor[PixelFlavor][Index];
  1863. Dib^.bmiColors[Index].rgbReserved := 0;
  1864. end;
  1865. end;
  1866. TWPT_GRAY:
  1867. begin
  1868. {Creates a 256 shades of gray palette}
  1869. Dib^.bmiHeader.biClrUsed := 256;
  1870. for index := 0 to 255 do
  1871. begin
  1872. Dib^.bmiColors[index].rgbRed := index;
  1873. Dib^.bmiColors[index].rgbGreen := index;
  1874. Dib^.bmiColors[index].rgbBlue := index;
  1875. Dib^.bmiColors[index].rgbReserved := 0;
  1876. end {for i}
  1877. end;
  1878. TWPT_RGB: Dib^.bmiHeader.biClrUsed := 0;
  1879. else
  1880. begin
  1881. {Try obtaining the palette}
  1882. if Owner.TwainProc(AppInfo, @Structure, DG_CONTROL, DAT_PALETTE8,
  1883. MSG_GET, @Pal) <> TWRC_SUCCESS then
  1884. begin
  1885. {If the source did not provide a palette, uses shades of gray here}
  1886. Dib^.bmiHeader.biClrUsed := 256;
  1887. for index := 0 to 255 do
  1888. begin
  1889. Dib^.bmiColors[index].rgbRed := index;
  1890. Dib^.bmiColors[index].rgbGreen := index;
  1891. Dib^.bmiColors[index].rgbBlue := index;
  1892. Dib^.bmiColors[index].rgbReserved := 0;
  1893. end {for i}
  1894. end
  1895. else
  1896. begin
  1897. {Uses source palette here}
  1898. Dib^.bmiHeader.biClrUsed := Pal.NumColors;
  1899. for Index := 0 TO Pal.NumColors - 1 do
  1900. begin
  1901. Dib^.bmiColors[index].rgbRed := pal.Colors[index].Channel1;
  1902. Dib^.bmiColors[index].rgbGreen := pal.Colors[index].Channel2;
  1903. Dib^.bmiColors[index].rgbBlue := pal.Colors[index].Channel3;
  1904. Dib^.bmiColors[index].rgbReserved := 0;
  1905. end {for Index}
  1906. end {if Owner.TwainProc(AppInfo...}
  1907. end {case else};
  1908. end {case Info.PixelType};
  1909. {Creates the bitmap}
  1910. DC := GetDC(Owner.VirtualWindow);
  1911. {%H-}DTNativeUInt({%H-}Data) := DTNativeUInt(Dib) + Dib^.bmiHeader.biSize +
  1912. (Dib^.bmiHeader.biClrUsed * sizeof(RGBQUAD));
  1913. BitmapHandle := CreateDIBSection(DC, Dib^, DIB_RGB_COLORS, Data, 0, 0);
  1914. ReleaseDC(Owner.VirtualWindow, DC);
  1915. PixelType := Info.PixelType;
  1916. {Unlock and free data}
  1917. GlobalUnlock(Handle);
  1918. GlobalFree(Handle);
  1919. end;
  1920. {Method to transfer the images}
  1921. procedure TTwainSource.TransferImages();
  1922. var
  1923. {To test if the image transfer is done}
  1924. Cancel, Done : Boolean;
  1925. {Return code from Twain method}
  1926. rc : TW_UINT16;
  1927. {Handle to the native Device independent Image (DIB)}
  1928. hNative: TW_UINT32;
  1929. {Pending transfers structure}
  1930. PendingXfers: TW_PENDINGXFERS;
  1931. {File transfer info}
  1932. Info: TW_SETUPFILEXFER;
  1933. {Image handle and pointer}
  1934. ImageHandle: HBitmap;
  1935. PixelType : TW_INT16;
  1936. begin
  1937. {Set the transfer mode}
  1938. //npeter:
  1939. //on a HP driver I got error events
  1940. //when it was set above state 5;
  1941. //commented out
  1942. // ChangeTransferMode(TransferMode);
  1943. Cancel := FALSE; {Testing if it was cancelled}
  1944. Done := FALSE; {Initialize done variable}
  1945. {Obtain all the images from the source}
  1946. repeat
  1947. {Transfer depending on the transfer mode}
  1948. case TransferMode of
  1949. {Native transfer, the source creates the image thru a device}
  1950. {dependent image}
  1951. ttmNative:
  1952. begin
  1953. {Call method to obtain the image}
  1954. hNative := 0;
  1955. rc := Owner.TwainProc(AppInfo, @Structure, DG_IMAGE,
  1956. DAT_IMAGENATIVEXFER, MSG_GET, @hNative);
  1957. end {case ttmNative};
  1958. {File transfering, the source should create a file with}
  1959. {the acquired image}
  1960. ttmFile:
  1961. begin
  1962. {Event to allow user to set the file transfer information}
  1963. if Assigned(Owner.OnSourceSetupFileXfer) then
  1964. Owner.OnSourceSetupFileXfer(Owner, Index);
  1965. Owner.TwainProc(AppInfo, @Structure, DG_CONTROL, DAT_SETUPFILEXFER,
  1966. MSG_GET, @Info);
  1967. {Call method to make source acquire and create file}
  1968. rc := Owner.TwainProc(AppInfo, @Structure, DG_IMAGE,
  1969. DAT_IMAGEFILEXFER, MSG_GET, nil);
  1970. end {case ttmFile};
  1971. {Memory buffer transfers}
  1972. ttmMemory:
  1973. begin
  1974. {Prepare for memory transference}
  1975. rc := PrepareMemXfer({%H-}ImageHandle, {%H-}PixelType);
  1976. {If the image was sucessfully prepared to be transfered, it's}
  1977. {now time to transfer it}
  1978. if rc = TWRC_SUCCESS then rc := TransferImageMemory(ImageHandle,
  1979. PixelType);
  1980. end
  1981. {Unknown transfer mode ?}
  1982. else Rc := 0;
  1983. end;
  1984. {Twain call to transfer image return}
  1985. case rc of
  1986. {Transfer sucessfully done}
  1987. TWRC_XFERDONE:
  1988. case TransferMode of
  1989. {Native transfer sucessfull}
  1990. ttmNative: ReadNative(hNative, Cancel);
  1991. {File transfer sucessfull}
  1992. ttmFile: ReadFile(Info.FileName, Info.Format, Cancel);
  1993. {Memory transfer sucessfull}
  1994. ttmMemory: ReadMemory(ImageHandle, Cancel);
  1995. end {case TransferMode, TWRC_XFERDONE};
  1996. {User cancelled the transfers}
  1997. TWRC_CANCEL:
  1998. begin
  1999. {Acknowledge end of transfer}
  2000. Done := TRUE;
  2001. Cancel := TRUE;
  2002. {Call event, if avaliable}
  2003. if Assigned(Owner.OnAcquireCancel) then
  2004. Owner.OnAcquireCancel(Owner, Index)
  2005. end
  2006. else {Unknown return or error}
  2007. if Assigned(Owner.OnAcquireError) then
  2008. Owner.OnAcquireError(Owner, Index, Rc, GetReturnStatus())
  2009. end;
  2010. {Check if there are pending transfers}
  2011. if not Done then
  2012. Done := (Owner.TwainProc(AppInfo, @Structure, DG_CONTROL,
  2013. DAT_PENDINGXFERS, MSG_ENDXFER, @PendingXfers) <> TWRC_SUCCESS) or
  2014. (PendingXfers.Count = 0);
  2015. {If user has cancelled}
  2016. if not Done and Cancel then
  2017. Done := (Owner.TwainProc(AppInfo, @Structure, DG_CONTROL,
  2018. DAT_PENDINGXFERS, MSG_RESET, @PendingXfers) = TWRC_SUCCESS);
  2019. until Done;
  2020. {Disable source}
  2021. Enabled := False;
  2022. {All documents have been transfered}
  2023. if Assigned(Owner.OnTransferComplete) then
  2024. Owner.OnTransferComplete(Owner, Index, Cancel);
  2025. Owner.RefreshVirtualWindow;
  2026. end;
  2027. {Returns the number of colors in the DIB}
  2028. function DibNumColors (pv: Pointer): Word;
  2029. var
  2030. Bits: Integer;
  2031. lpbi: PBITMAPINFOHEADER absolute pv;
  2032. lpbc: PBITMAPCOREHEADER absolute pv;
  2033. begin
  2034. //With the BITMAPINFO format headers, the size of the palette
  2035. //is in biClrUsed, whereas in the BITMAPCORE - style headers, it
  2036. //is dependent on the bits per pixel ( = 2 raised to the power of
  2037. //bits/pixel).
  2038. if (lpbi^.biSize <> sizeof(BITMAPCOREHEADER)) then
  2039. begin
  2040. if (lpbi^.biClrUsed <> 0) then
  2041. begin
  2042. result := lpbi^.biClrUsed;
  2043. exit;
  2044. end;
  2045. Bits := lpbi^.biBitCount;
  2046. end
  2047. else
  2048. Bits := lpbc^.bcBitCount;
  2049. {Test bits to return}
  2050. case (Bits) of
  2051. 1: Result := 2;
  2052. 4: Result := 16;
  2053. 8: Result := 256;
  2054. else Result := 0;
  2055. end {case};
  2056. end;
  2057. {Converts from TWain TW_UINT16 to TTwainFormat}
  2058. function TwainToTTwainFormat(Value: TW_UINT16): TTwainFormat;
  2059. begin
  2060. Case Value of
  2061. TWFF_TIFF : Result := tfTIFF;
  2062. TWFF_PICT : Result := tfPict;
  2063. TWFF_BMP : Result := tfBMP;
  2064. TWFF_XBM : Result := tfXBM;
  2065. TWFF_JFIF : Result := tfJPEG;
  2066. TWFF_FPX : Result := tfFPX;
  2067. TWFF_TIFFMULTI: Result := tfTIFFMulti;
  2068. TWFF_PNG : Result := tfPNG;
  2069. TWFF_SPIFF : Result := tfSPIFF;
  2070. TWFF_EXIF : Result := tfEXIF;
  2071. else Result := tfUnknown;
  2072. end {case Value of}
  2073. end;
  2074. {Reads the file image}
  2075. procedure TTwainSource.ReadFile(Name: TW_STR255; Format: TW_UINT16;
  2076. var Cancel: Boolean);
  2077. begin
  2078. {Call event, if set}
  2079. if Assigned(Owner.OnSourceFileTransfer) then
  2080. Owner.OnSourceFileTransfer(Self, Index, Name, TwainToTTwainFormat(Format),
  2081. Cancel);
  2082. end;
  2083. {Call event for memory image}
  2084. procedure TTwainSource.ReadMemory(Image: HBitmap; var Cancel: Boolean);
  2085. begin
  2086. Owner.DoTwainAcquire(Owner, Index, Image, Cancel);
  2087. end;
  2088. {Reads a native image}
  2089. procedure TTwainSource.ReadNative(Handle: TW_UINT32; var Cancel: Boolean);
  2090. var
  2091. DibInfo: ^TBITMAPINFO;
  2092. ColorTableSize: Integer;
  2093. lpBits: PAnsiChar;//ccc
  2094. DC: HDC;
  2095. BitmapHandle: HBitmap;
  2096. begin
  2097. {Get image information pointer and size}
  2098. DibInfo := GlobalLock(Handle);
  2099. ColorTableSize := (DibNumColors(DibInfo) * SizeOf(RGBQUAD));
  2100. {Get data memory position}
  2101. lpBits := PAnsiChar(DibInfo);//ccc
  2102. //{$IFDEF FPC}
  2103. Inc(lpBits, DibInfo.bmiHeader.biSize);
  2104. //{$ELSE}ccc
  2105. //DELPHI BUG - due to wrong PChar definition
  2106. //Inc(lpBits, DibInfo.bmiHeader.biSize div 2);
  2107. //{$ENDIF}
  2108. Inc(lpBits, ColorTableSize);
  2109. //lpBits := PAnsiChar(DibInfo^.bmiColors);//ccc
  2110. {Creates the bitmap}
  2111. DC := GetDC(Owner.VirtualWindow);
  2112. BitmapHandle := CreateDIBitmap(DC, DibInfo.bmiHeader, CBM_INIT,
  2113. lpBits, DibInfo^, DIB_RGB_COLORS);
  2114. ReleaseDC(Owner.VirtualWindow, DC);
  2115. Owner.DoTwainAcquire(Owner, Index, BitmapHandle, Cancel);
  2116. {Free bitmap}
  2117. GlobalUnlock(Handle);
  2118. GlobalFree(Handle);
  2119. end;
  2120. {Setup file transfer}
  2121. function TTwainSource.SetupFileTransfer(Filename: String;
  2122. Format: TTwainFormat): Boolean;
  2123. const
  2124. FormatToTwain: Array[TTwainFormat] of TW_UINT16 = (TWFF_TIFF,
  2125. TWFF_PICT, TWFF_BMP, TWFF_XBM, TWFF_JFIF, TWFF_FPX, TWFF_TIFFMULTI,
  2126. TWFF_PNG, TWFF_SPIFF, TWFF_EXIF, 0);
  2127. var
  2128. FileTransferInfo: TW_SETUPFILEXFER;
  2129. begin
  2130. {Source must be loaded to set things}
  2131. if (Loaded) then
  2132. begin
  2133. {Prepare structure}
  2134. FileTransferInfo.FileName := StrToStr255({$IFDEF UNICODE}RawByteString{$ENDIF}(FileName));
  2135. FileTransferInfo.Format := FormatToTwain[Format];
  2136. {Call method}
  2137. Result := (Owner.TwainProc(AppInfo, @Structure, DG_CONTROL,
  2138. DAT_SETUPFILEXFER, MSG_SET, @FileTransferInfo) = TWRC_SUCCESS);
  2139. end
  2140. else Result := FALSE; {Could not set file transfer with source unloaded}
  2141. end;
  2142. {Set the number of images that the application wants to receive}
  2143. function TTwainSource.SetCapXferCount(Value: SmallInt): TCapabilityRet;
  2144. begin
  2145. {Call method to set the value}
  2146. Result := SetOneValue(CAP_XFERCOUNT, TWTY_UINT16, @Value);
  2147. end;
  2148. {Returns the number of images that the source will return}
  2149. function TTwainSource.GetCapXferCount(var Return: SmallInt;
  2150. Mode: TRetrieveCap): TCapabilityRet;
  2151. var
  2152. {Will hold the capability information}
  2153. ItemType: TW_UINT16;
  2154. Value : String;
  2155. begin
  2156. {Call method to return information}
  2157. Result := GetOneValue(CAP_XFERCOUNT, {%H-}ItemType, {%H-}Value, Mode);
  2158. {Item type must be of TW_UINT16}
  2159. if (Result = crSuccess) and (ItemType <> TWTY_INT16) then
  2160. Result := crUnsupported;
  2161. {If everything gone ok, fill result}
  2162. if Result = crSuccess then Return := StrToIntDef(Value, -1);
  2163. end;
  2164. {Set the unit measure}
  2165. function TTwainSource.SetICapUnits(Value: TTwainUnit): TCapabilityRet;
  2166. //npeter
  2167. //the TTwainUnit is byte!!!
  2168. //so we have to convert it to TW_UINT16
  2169. //before this fix I was not able to set this capability
  2170. //on a HP driver
  2171. const Transfer: Array[TTwainUnit] of TW_UINT16 =
  2172. (TWUN_INCHES, TWUN_CENTIMETERS, TWUN_PICAS, TWUN_POINTS, TWUN_TWIPS, TWUN_PIXELS, TWUN_INCHES);
  2173. var
  2174. iValue: TW_UINT16;
  2175. begin
  2176. ivalue:=Transfer[Value];
  2177. Result := SetOneValue(ICAP_UNITS, TWTY_UINT16, @iValue);
  2178. end;
  2179. {Convert from Twain to TTwainPixelFlavor}
  2180. function TwainToTTwainPixelFlavor(Value: TW_UINT16): TTwainPixelFlavor;
  2181. begin
  2182. {Test the value to make the convertion}
  2183. case Value of
  2184. TWPF_CHOCOLATE: Result := tpfChocolate;
  2185. TWPF_VANILLA : Result := tpfVanilla;
  2186. else Result := tpfUnknown;
  2187. end {case Value}
  2188. end;
  2189. {Convert from Twain to TTwainUnit}
  2190. function TwainToTTwainUnit(Value: TW_UINT16): TTwainUnit;
  2191. begin
  2192. {Test the value to make the convertion}
  2193. case Value of
  2194. TWUN_INCHES : Result := tuInches;
  2195. TWUN_CENTIMETERS: Result := tuCentimeters;
  2196. TWUN_PICAS : Result := tuPicas;
  2197. TWUN_POINTS : Result := tuPoints;
  2198. TWUN_TWIPS : Result := tuTwips;
  2199. TWUN_PIXELS : Result := tuPixels;
  2200. else Result := tuUnknown;
  2201. end {case Value}
  2202. end;
  2203. {Retrieve the unit measure for all quantities}
  2204. function TTwainSource.GetICapUnits(var Return: TTwainUnit;
  2205. var Supported: TTwainUnitSet; Mode: TRetrieveCap): TCapabilityRet;
  2206. var
  2207. ItemType: TW_UINT16;
  2208. List : TGetCapabilityList;
  2209. Current, i,
  2210. Default : Integer;
  2211. begin
  2212. {Call method to get result}
  2213. Result := GetEnumerationValue(ICAP_UNITS, {%H-}ItemType, {%H-}List, {%H-}Current, {%H-}Default,
  2214. Mode);
  2215. if ItemType <> TWTY_UINT16 then Result := crUnsupported;
  2216. {If it was sucessfull, return values}
  2217. if Result = crSuccess then
  2218. begin
  2219. {Make list}
  2220. for i := Low(List) to High(List) do
  2221. Include(Supported, TwainToTTwainUnit(StrToIntDef(List[i], -1)));
  2222. {Return values depending on the mode}
  2223. if Mode = rcGetDefault then
  2224. Return := TwainToTTwainUnit(StrToIntDef(List[Default], -1))
  2225. else
  2226. Return := TwainToTTwainUnit(StrToIntDef(List[Current], -1));
  2227. end {if Result = crSuccess}
  2228. end;
  2229. {Retrieve the pixel flavor values}
  2230. function TTwainSource.GetIPixelFlavor(var Return: TTwainPixelFlavor;
  2231. var Supported: TTwainPixelFlavorSet; Mode: TRetrieveCap): TCapabilityRet;
  2232. var
  2233. ItemType: TW_UINT16;
  2234. List : TGetCapabilityList;
  2235. Current, i,
  2236. Default : Integer;
  2237. begin
  2238. {Call method to get result}
  2239. Result := GetEnumerationValue(ICAP_PIXELFLAVOR, {%H-}ItemType, {%H-}List, {%H-}Current,
  2240. {%H-}Default, Mode);
  2241. if ItemType <> TWTY_UINT16 then Result := crUnsupported;
  2242. {If it was sucessfull, return values}
  2243. if Result = crSuccess then
  2244. begin
  2245. {Make list}
  2246. for i := Low(List) to High(List) do
  2247. Include(Supported, TwainToTTwainPixelFlavor(StrToIntDef(List[i], -1)));
  2248. {Return values depending on the mode}
  2249. if Mode = rcGetDefault then
  2250. Return := TwainToTTwainPixelFlavor(StrToIntDef(List[Default], -1))
  2251. else
  2252. Return := TwainToTTwainPixelFlavor(StrToIntDef(List[Current], -1));
  2253. end {if Result = crSuccess}
  2254. end;
  2255. function TTwainSource.SetIPixelFlavor(Value: TTwainPixelFlavor): TCapabilityRet;
  2256. //npeter
  2257. //the TTwainPixelFlavor is byte!!!
  2258. //so we have to convert it to TW_UINT16
  2259. //before this fix I was not able to set this capability
  2260. //on a HP driver
  2261. const Transfer: array [TTwainPixelFlavor] of TW_UINT16 = (TWPF_CHOCOLATE,TWPF_VANILLA,TWPF_CHOCOLATE);
  2262. var iValue: TW_UINT16;
  2263. begin
  2264. iValue:=Transfer[value];
  2265. Result := SetOneValue(ICAP_PIXELFLAVOR, TWTY_UINT16, @iValue);
  2266. end;
  2267. {Convert from Twain to TTwainPixelType}
  2268. function TwainToTTwainPixelType(Value: TW_UINT16): TTwainPixelType;
  2269. begin
  2270. {Test the value to make the convertion}
  2271. case Value of
  2272. TWPT_BW : Result := tbdBw;
  2273. TWPT_GRAY : Result := tbdGray;
  2274. TWPT_RGB : Result := tbdRgb;
  2275. TWPT_BGR : Result := tbdBgr;
  2276. TWPT_PALETTE : Result := tbdPalette;
  2277. TWPT_CMY : Result := tbdCmy;
  2278. TWPT_CMYK : Result := tbdCmyk;
  2279. TWPT_YUV : Result := tbdYuv;
  2280. TWPT_YUVK : Result := tbdYuvk;
  2281. TWPT_CIEXYZ : Result := tbdCieXYZ;
  2282. else Result := tbdUnknown;
  2283. end {case Value}
  2284. end;
  2285. {Returns pixel type values}
  2286. function TTwainSource.GetIPixelType(var Return: TTwainPixelType;
  2287. var Supported: TTwainPixelTypeSet; Mode: TRetrieveCap): TCapabilityRet;
  2288. var
  2289. ItemType: TW_UINT16;
  2290. List : TGetCapabilityList;
  2291. Current, i,
  2292. Default : Integer;
  2293. begin
  2294. {Call method to get result}
  2295. Result := GetEnumerationValue(ICAP_PIXELTYPE, {%H-}ItemType, {%H-}List, {%H-}Current,
  2296. {%H-}Default, Mode);
  2297. if ItemType <> TWTY_UINT16 then Result := crUnsupported;
  2298. {If it was sucessfull, return values}
  2299. if Result = crSuccess then
  2300. begin
  2301. {Make list}
  2302. for i := Low(List) to High(List) do
  2303. Include(Supported, TwainToTTwainPixelType(StrToIntDef(List[i], -1)));
  2304. {Return values depending on the mode}
  2305. if Mode = rcGetDefault then
  2306. Return := TwainToTTwainPixelType(StrToIntDef(List[Default], -1))
  2307. else
  2308. Return := TwainToTTwainPixelType(StrToIntDef(List[Current], -1));
  2309. end {if Result = crSuccess}
  2310. end;
  2311. {Set the pixel type value}
  2312. function TTwainSource.SetIPixelType(Value: TTwainPixelType): TCapabilityRet;
  2313. //npeter
  2314. //the TTwainPixelType is byte!!!
  2315. //so we have to convert it to TW_UINT16
  2316. //before this fix occasionally I was not able to set this capability
  2317. //on a HP driver
  2318. var ivalue: smallint;
  2319. begin
  2320. ivalue:=ord(value);
  2321. Result := SetOneValue(ICAP_PIXELTYPE, TWTY_UINT16, @iValue);
  2322. end;
  2323. {Returns bitdepth values}
  2324. function TTwainSource.GetIBitDepth(var Return: Word;
  2325. var Supported: TTwainBitDepth; Mode: TRetrieveCap): TCapabilityRet;
  2326. var
  2327. ItemType: TW_UINT16;
  2328. List : TGetCapabilityList;
  2329. Current, i,
  2330. Default : Integer;
  2331. begin
  2332. {Call GetOneValue to obtain this property}
  2333. Result := GetEnumerationValue(ICAP_BITDEPTH, {%H-}ItemType, {%H-}List, {%H-}Current,
  2334. {%H-}Default, Mode);
  2335. if ItemType <> TWTY_UINT16 then Result := crUnsupported;
  2336. {In case everything went ok, fill parameters}
  2337. if Result = crSuccess then
  2338. begin
  2339. {Build bit depth list}
  2340. SetLength(Supported, Length(List));
  2341. FOR i := LOW(List) TO HIGH(List) DO
  2342. Supported[i] := StrToIntDef(List[i], -1);
  2343. {Return values depending on the mode}
  2344. if Mode = rcGetDefault then Return := StrToIntDef(List[Default], -1)
  2345. else Return := StrToIntDef(List[Current], -1);
  2346. end {if Result = crSuccess}
  2347. end;
  2348. {Set current bitdepth value}
  2349. function TTwainSource.SetIBitDepth(Value: Word): TCapabilityRet;
  2350. begin
  2351. Result := SetOneValue(ICAP_BITDEPTH, TWTY_UINT16, @Value);
  2352. end;
  2353. {Returns physical width}
  2354. function TTwainSource.GetIPhysicalWidth(var Return: Extended;
  2355. Mode: TRetrieveCap): TCapabilityRet;
  2356. var
  2357. Handle: HGlobal;
  2358. OneV : pTW_ONEVALUE;
  2359. Container: TW_UINT16;
  2360. begin
  2361. {Obtain handle to data from this capability}
  2362. Result := GetCapabilityRec(ICAP_PHYSICALWIDTH, {%H-}Handle, {%H-}Mode, {%H-}Container);
  2363. if Result = crSuccess then
  2364. begin
  2365. {Obtain data}
  2366. OneV := GlobalLock(Handle);
  2367. if OneV^.ItemType <> TWTY_FIX32 then Result := crUnsupported
  2368. else Return := Fix32ToFloat(pTW_FIX32(@OneV^.Item)^);
  2369. {Free data}
  2370. GlobalUnlock(Handle);
  2371. GlobalFree(Handle);
  2372. end;
  2373. end;
  2374. {Returns physical height}
  2375. function TTwainSource.GetIPhysicalHeight(var Return: Extended;
  2376. Mode: TRetrieveCap): TCapabilityRet;
  2377. var
  2378. Handle: HGlobal;
  2379. OneV : pTW_ONEVALUE;
  2380. Container: TW_UINT16;
  2381. begin
  2382. {Obtain handle to data from this capability}
  2383. Result := GetCapabilityRec(ICAP_PHYSICALHEIGHT, {%H-}Handle, {%H-}Mode, {%H-}Container);
  2384. if Result = crSuccess then
  2385. begin
  2386. {Obtain data}
  2387. OneV := GlobalLock(Handle);
  2388. if OneV^.ItemType <> TWTY_FIX32 then Result := crUnsupported
  2389. else Return := Fix32ToFloat(pTW_FIX32(@OneV^.Item)^);
  2390. {Free data}
  2391. GlobalUnlock(Handle);
  2392. GlobalFree(Handle);
  2393. end;
  2394. end;
  2395. {Returns a resolution}
  2396. function TTwainSource.GetResolution(Capability: TW_UINT16; var Return: Extended;
  2397. var Values: TTwainResolution; Mode: TRetrieveCap): TCapabilityRet;
  2398. var
  2399. Handle: HGlobal;
  2400. EnumV: pTW_ENUMERATION;
  2401. Container: TW_UINT16;
  2402. Item: pTW_FIX32;
  2403. i : Integer;
  2404. begin
  2405. {Obtain handle to data from this capability}
  2406. Result := GetCapabilityRec(Capability, {%H-}Handle, Mode, {%H-}Container);
  2407. if Result = crSuccess then
  2408. begin
  2409. {Obtain data}
  2410. //npeter
  2411. //the "if" is just for sure!
  2412. if (Container<>TWON_ENUMERATION) and (Container<>TWON_ARRAY) then
  2413. begin
  2414. result:=crUnsupported;
  2415. exit;
  2416. end;
  2417. EnumV := GlobalLock(Handle);
  2418. if EnumV^.ItemType <> TWTY_FIX32 then Result := crUnsupported
  2419. else begin
  2420. {Set array size and pointer to the first item}
  2421. Item := @EnumV^.ItemList[0];
  2422. SetLength(Values, EnumV^.NumItems);
  2423. {Fill array}
  2424. FOR i := 1 TO EnumV^.NumItems DO
  2425. begin
  2426. {Fill array with the item}
  2427. Values[i - 1] := Fix32ToFloat(Item^);
  2428. {Move to next item}
  2429. inc(Item);
  2430. end {FOR i};
  2431. {Fill return}
  2432. //npeter
  2433. //DefaultIndex and CurrentIndex valid for enum only!
  2434. //I got nice AV with an old Mustek scanner which uses TWON_ARRAY
  2435. //i return 0 in this case (may be not the best solution, but not AV at least :-)
  2436. if (Container<>TWON_ARRAY) then
  2437. begin
  2438. if Mode = rcGetDefault then Return := Values[EnumV^.DefaultIndex]
  2439. else Return := Values[EnumV^.CurrentIndex];
  2440. end
  2441. else return:=0;
  2442. end;
  2443. {Free data}
  2444. GlobalUnlock(Handle);
  2445. GlobalFree(Handle);
  2446. end;
  2447. end;
  2448. {Sets X resolution}
  2449. function TTwainSource.SetIXResolution(Value: Extended): TCapabilityRet;
  2450. var
  2451. Fix32: TW_FIX32;
  2452. begin
  2453. Fix32 := FloatToFix32(Value);
  2454. Result := SetOneValue(ICAP_XRESOLUTION, TWTY_FIX32, @Fix32);
  2455. end;
  2456. {Sets Y resolution}
  2457. function TTwainSource.SetIYResolution(Value: Extended): TCapabilityRet;
  2458. var
  2459. Fix32: TW_FIX32;
  2460. begin
  2461. Fix32 := FloatToFix32(Value);
  2462. Result := SetOneValue(ICAP_YRESOLUTION, TWTY_FIX32, @Fix32);
  2463. end;
  2464. {Returns X resolution}
  2465. function TTwainSource.GetIXResolution(var Return: Extended;
  2466. var Values: TTwainResolution; Mode: TRetrieveCap): TCapabilityRet;
  2467. begin
  2468. Result := GetResolution(ICAP_XRESOLUTION, Return, Values, Mode);
  2469. end;
  2470. {Returns Y resolution}
  2471. function TTwainSource.GetIYResolution(var Return: Extended;
  2472. var Values: TTwainResolution; Mode: TRetrieveCap): TCapabilityRet;
  2473. begin
  2474. Result := GetResolution(ICAP_YRESOLUTION, Return, Values, Mode);
  2475. end;
  2476. {Returns if user interface is controllable}
  2477. function TTwainSource.GetUIControllable(var Return: Boolean): TCapabilityRet;
  2478. var
  2479. ItemType: TW_UINT16;
  2480. Value : String;
  2481. begin
  2482. {Try to obtain value and make sure it is of type TW_BOOL}
  2483. Result := GetOneValue(CAP_UICONTROLLABLE, {%H-}ItemType, {%H-}Value, rcGet);
  2484. if (Result = crSuccess) and (ItemType <> TWTY_BOOL) then
  2485. Result := crUnsupported;
  2486. {Return value, by checked the return value from GetOneValue}
  2487. if Result = crSuccess then Return := (Value = '1');
  2488. end;
  2489. {Returns if feeder is loaded}
  2490. function TTwainSource.GetFeederLoaded(var Return: Boolean): TCapabilityRet;
  2491. var
  2492. ItemType: TW_UINT16;
  2493. Value : String;
  2494. begin
  2495. {Try to obtain value and make sure it is of type TW_BOOL}
  2496. Result := GetOneValue(CAP_FEEDERLOADED, {%H-}ItemType, {%H-}Value, rcGet);
  2497. if (Result = crSuccess) and (ItemType <> TWTY_BOOL) then
  2498. Result := crUnsupported;
  2499. {Return value, by checked the return value from GetOneValue}
  2500. if Result = crSuccess then Return := (Value = '1');
  2501. end;
  2502. {Returns if feeder is enabled}
  2503. function TTwainSource.GetFeederEnabled(var Return: Boolean): TCapabilityRet;
  2504. var
  2505. ItemType: TW_UINT16;
  2506. Value : String;
  2507. begin
  2508. {Try to obtain value and make sure it is of type TW_BOOL}
  2509. Result := GetOneValue(CAP_FEEDERENABLED, {%H-}ItemType, {%H-}Value, rcGet);
  2510. if (Result = crSuccess) and (ItemType <> TWTY_BOOL) then
  2511. Result := crUnsupported;
  2512. {Return value, by checked the return value from GetOneValue}
  2513. if Result = crSuccess then Return := (Value = '1');
  2514. end;
  2515. {Set if feeder is enabled}
  2516. function TTwainSource.SetFeederEnabled(Value: WordBool): TCapabilityRet;
  2517. begin
  2518. {Call SetOneValue to set value}
  2519. Result := SetOneValue(CAP_FEEDERENABLED, TWTY_BOOL, @Value);
  2520. end;
  2521. {Returns if autofeed is enabled}
  2522. function TTwainSource.GetAutofeed(var Return: Boolean): TCapabilityRet;
  2523. var
  2524. ItemType: TW_UINT16;
  2525. Value : String;
  2526. begin
  2527. {Try to obtain value and make sure it is of type TW_BOOL}
  2528. Result := GetOneValue(CAP_AUTOFEED, {%H-}ItemType, {%H-}Value, rcGet);
  2529. if (Result = crSuccess) and (ItemType <> TWTY_BOOL) then
  2530. Result := crUnsupported;
  2531. {Return value, by checked the return value from GetOneValue}
  2532. if Result = crSuccess then Return := (Value = '1');
  2533. end;
  2534. {Set if autofeed is enabled}
  2535. function TTwainSource.SetAutoFeed(Value: WordBool): TCapabilityRet;
  2536. begin
  2537. {Call SetOneValue to set value}
  2538. Result := SetOneValue(CAP_AUTOFEED, TWTY_BOOL, @Value);
  2539. end;
  2540. {Used with property PendingXfers}
  2541. function TTwainSource.GetPendingXfers: TW_INT16;
  2542. var
  2543. PendingXfers: TW_PENDINGXFERS;
  2544. begin
  2545. if Loaded and Enabled then
  2546. begin
  2547. {Call method to retrieve}
  2548. if Owner.TwainProc(AppInfo, @Structure, DG_CONTROL, DAT_PENDINGXFERS,
  2549. MSG_GET, @PendingXfers) = TWRC_SUCCESS then
  2550. Result := PendingXfers.Count
  2551. else Result := ERROR_INT16; {Some error ocurred while calling message}
  2552. end
  2553. else Result := ERROR_INT16; {Source not loaded/enabled}
  2554. end;
  2555. {Virtual window procedure handler}
  2556. function VirtualWinProc(Handle: THandle; uMsg: UINT; wParam: WPARAM;
  2557. lParam: LPARAM): LResult; stdcall;
  2558. {Returns the TCustomDelphiTwain object}
  2559. function Obj: TCustomDelphiTwain;
  2560. begin
  2561. DTNativeUInt(Result) := GetWindowLong(Handle, GWL_USERDATA);
  2562. end {function};
  2563. var
  2564. Twain: TCustomDelphiTwain;
  2565. i : Integer;
  2566. Msg : TMsg;
  2567. begin
  2568. {Tests for the message}
  2569. case uMsg of
  2570. {Creation of the window}
  2571. WM_CREATE:
  2572. {Stores the TCustomDelphiTwain object handle}
  2573. with {%H-}pCreateStruct(lParam)^ do
  2574. SetWindowLong(Handle, GWL_USERDATA, {%H-}Longint(lpCreateParams));
  2575. {case} else
  2576. begin
  2577. {Try to obtain the current object pointer}
  2578. Twain := Obj;
  2579. if Assigned(Twain) then
  2580. {If there are sources loaded, we need to verify}
  2581. {this message}
  2582. if (Twain.SourcesLoaded > 0) then
  2583. begin
  2584. {Convert parameters to a TMsg}
  2585. Msg := MakeMsg(Handle, uMsg, wParam, lParam);
  2586. {Tell about this message}
  2587. FOR i := 0 TO Twain.SourceCount - 1 DO
  2588. if ((Twain.Source[i].Loaded) and (Twain.Source[i].Enabled)) then
  2589. if Twain.Source[i].ProcessMessage(Msg) then
  2590. begin
  2591. {Case this was a message from the source, there is}
  2592. {no need for the default procedure to process}
  2593. Result := 0;
  2594. Exit;
  2595. end;
  2596. end {if (Twain.SourcesLoaded > 0)}
  2597. end {case Else}
  2598. end {case uMsg of};
  2599. {Calls method to handle}
  2600. Result := DefWindowProc(Handle, uMsg, wParam, lParam);
  2601. end;
  2602. //npeter: 2004.01.12
  2603. //sets the acquired area
  2604. function TTwainSource.SetImagelayoutFrame(const fLeft, fTop, fRight,
  2605. fBottom: double): TCapabilityRet;
  2606. var ImageLayout: TW_IMAGELAYOUT;
  2607. begin
  2608. if not Loaded then
  2609. begin
  2610. Result := crInvalidState; {In case the source is not loaded}
  2611. exit;
  2612. end;
  2613. fillchar({%H-}ImageLayout,sizeof(TW_IMAGELAYOUT),0);
  2614. with ImageLayout.Frame do
  2615. begin
  2616. Left:=FloatToFIX32(fLeft);
  2617. Top:=FloatToFIX32(fTop);
  2618. Right:=FloatToFIX32(fRight);
  2619. Bottom:=FloatToFIX32(fBottom);
  2620. end;
  2621. {Call method and store return}
  2622. Result := ResultToCapabilityRec(Owner.TwainProc(AppInfo, @Structure,
  2623. DG_IMAGE, DAT_IMAGELAYOUT, MSG_SET, @ImageLayout));
  2624. end;
  2625. //npeter: 2004.01.12
  2626. //enable/disable progress indicators
  2627. function TTwainSource.SetIndicators(Value: boolean): TCapabilityRet;
  2628. begin
  2629. {Call SetOneValue to set value}
  2630. Result := SetOneValue(CAP_INDICATORS, TWTY_BOOL, @Value);
  2631. end;
  2632. end.