T O P I C R E V I E W |
Elemental |
Posted - Mar 26 2014 : 10:38:31 I wrote a class helper in Delphi XE5 for the TIETwainParams class. It loads and stores certain settings from and to a file of your choice. You can specify any extension you like, but it will be plain text regardless.
Note that this is not a new class that inherits from TIETwainParams, but a class helper. This is nice because various ImageEn components and objects already have properties of this type, and an overridden class would not help much there. So, whenever you have access to an instance of TIETwainParams from the ImageEn product, you can call these new methods. Note that Delphi's Code Insight feature will show these as available methods, Error Insight will be OK with them, and the compiler will be happy, too.
unit uImageEnTwain;
interface
uses ietwain, System.SysUtils;
type
TIETwainHelper = class helper for TIETwainParams
protected
const StoredSettingsProperties: array[0..36] of String = (
'SelectedSource',
'AcceptedImages',
'AcquireFrameEnabled',
'AcquireFrameLeft',
'AcquireFrameRight',
'AcquireFrameTop',
'AcquireFrameBottom',
'AutoBorderDetection',
'AutoDeskew',
'AutoDiscardBlankPages',
'AutoScan',
'BitDepth', //(TIEIntegerList)
'AutoBright',
'Brightness', //(TIEDoubleList)
'BufferedTransfer',
'Contrast', //(TIEDoubleList)
'DuplexSupported',
'DuplexEnabled',
'AutoFeed',
'FeederSupported',
'FeederEnabled',
'Gamma',
'Highlight',
'Orientation', //(TIEDoubleList)
'PaperDetectable',
'PhysicalWidth',
'PhysicalHeight',
'PixelType', // (TIEIntegerList)
'AutoRotate',
'Rotation', //(TIEDoubleList)
'Shadow',
'Threshold', // (TIEDoubleList)
'VisibleDialog',
'XResolution', // (TIEDoubleList)
'YResolution', // (TIEDoubleList)
'XScaling', // (TIEDoubleList)
'YScaling' // (TIEDoubleList)
);
public
function SaveSettingsToFile( FileName: TFileName ): Boolean;
function LoadSettingsFromFile( FileName: TFileName ): Boolean;
end;
implementation
uses System.Rtti, System.TypInfo, System.Variants, System.Classes, System.IOUtils, hyieutils, System.StrUtils;
{ TIETwainHelper }
function TIETwainHelper.LoadSettingsFromFile(FileName: TFileName): Boolean;
var
slPropVals: TStringList;
iLastSource: Integer;
rcRttiContext: TRttiContext;
rtThisType: TRttiType;
iPropertyIndex: Integer;
sPropName: String;
rpThisProperty: TRttiProperty;
tvThisValue: TValue;
varThisValue: Variant;
begin
if TFile.Exists( FileName ) then
begin
slPropVals := TStringList.Create;
try
begin
slPropVals.LoadFromFile( FileName );
iLastSource := StrToIntDef( slPropVals.Values[ 'SelectedSource' ], -1 );
SelectedSource := iLastSource;
rcRttiContext := TRttiContext.Create;
rtThisType := rcRttiContext.GetType( ClassType );
for iPropertyIndex := Low( StoredSettingsProperties ) to High( StoredSettingsProperties ) do
begin
sPropName := StoredSettingsProperties[ iPropertyIndex ];
rpThisProperty := rtThisType.GetProperty( sPropName );
if Assigned( rpThisProperty ) then
try
tvThisValue := rpThisProperty.GetValue( Self );
if tvThisValue.IsObject then
if tvThisValue.AsObject is TIEDoubleList then
begin
if slPropVals.IndexOfName( sPropName + '.CurrentValue' ) > -1 then
TIEDoubleList(tvThisValue.AsObject).CurrentValue :=
StrToFloat( slPropVals.Values[ sPropName + '.CurrentValue' ] );
end
else
if tvThisValue.AsObject is TIEIntegerList then
begin
if slPropVals.IndexOfName( sPropName + '.CurrentValue' ) > -1 then
TIEIntegerList(tvThisValue.AsObject).CurrentValue :=
StrToInt( slPropVals.Values[ sPropName + '.CurrentValue' ] );
end
else
if slPropVals.IndexOfName( sPropName ) > -1 then
begin
if rpThisProperty.IsWritable then
begin
varThisValue := slPropVals.Values[ sPropName ];
tvThisValue.FromVariant( varThisValue );
rpThisProperty.SetValue( Self, tvThisValue );
end;
end;
except
on E: Exception do
raise Exception.CreateFmt( 'Error reading TWAIN property %s from file %s',
[ sPropName, FileName ] );
end
end;
end;
finally
slPropVals.Free;
end;
Update;
Result := True;
end
else
Result := False;
end;
function TIETwainHelper.SaveSettingsToFile(FileName: TFileName): Boolean;
var
slPropVals: TStringList;
iSourceIndex: Integer;
rcRttiContext: TRttiContext;
rtThisType: TRttiType;
iPropertyIndex: Integer;
sPropName: String;
rpThisProperty: TRttiProperty;
tvThisValue: TValue;
varThisValue: Variant;
sThisValue: String;
sParentDirectory: TFileName;
ItemIndex: Integer;
begin
slPropVals := TStringList.Create;
try
for iSourceIndex := 0 to SourceCount - 1 do
slPropVals.Values[ 'Source' + IntToStr( iSourceIndex ) ] := String(SourceName[ iSourceIndex ]);
slPropVals.Values[ 'GetDefaultSource' ] := IntToStr( GetDefaultSource );
rcRttiContext := TRttiContext.Create;
rtThisType := rcRttiContext.GetType( ClassType );
for iPropertyIndex := Low( StoredSettingsProperties ) to High( StoredSettingsProperties ) do
begin
sPropName := StoredSettingsProperties[ iPropertyIndex ];
rpThisProperty := rtThisType.GetProperty( sPropName );
if Assigned( rpThisProperty ) and rpThisProperty.IsReadable then
try
tvThisValue := rpThisProperty.GetValue( Self );
if tvThisValue.IsInstanceOf( TIEDoubleList ) then
begin
sThisValue := FormatFloat( '0.0', TIEDoubleList(tvThisValue.AsObject).CurrentValue );
slPropVals.Values[ sPropName + '.CurrentValue' ] := sThisValue;
sThisValue := FormatFloat( '0.0', TIEDoubleList(tvThisValue.AsObject).RangeMin );
slPropVals.Values[ sPropName + '.RangeMin' ] := sThisValue;
sThisValue := FormatFloat( '0.0', TIEDoubleList(tvThisValue.AsObject).RangeStep );
slPropVals.Values[ sPropName + '.RangeStep' ] := sThisValue;
sThisValue := FormatFloat( '0.0', TIEDoubleList(tvThisValue.AsObject).RangeMax );
slPropVals.Values[ sPropName + '.RangeMax' ] := sThisValue;
sThisValue := '';
for ItemIndex := 0 to TIEDoubleList(tvThisValue.AsObject).Count - 1 do
begin
if ItemIndex > 0 then
sThisValue := sThisValue + ',';
sThisValue := sThisValue +
FormatFloat( '0.0', TIEDoubleList(tvThisValue.AsObject)[ ItemIndex ] );
end;
slPropVals.Values[ sPropName + '.Items' ] := sThisValue;
end
else
if tvThisValue.IsInstanceOf( TIEIntegerList ) then
begin
sThisValue := IntToStr( TIEIntegerList(tvThisValue.AsObject).CurrentValue );
slPropVals.Values[ sPropName + '.CurrentValue' ] := sThisValue;
sThisValue := IntToStr( TIEIntegerList(tvThisValue.AsObject).RangeMin );
slPropVals.Values[ sPropName + '.RangeMin' ] := sThisValue;
sThisValue := IntToStr( TIEIntegerList(tvThisValue.AsObject).RangeStep );
slPropVals.Values[ sPropName + '.RangeStep' ] := sThisValue;
sThisValue := IntToStr( TIEIntegerList(tvThisValue.AsObject).RangeMax );
slPropVals.Values[ sPropName + '.RangeMax' ] := sThisValue;
sThisValue := '';
for ItemIndex := 0 to TIEIntegerList(tvThisValue.AsObject).Count - 1 do
begin
if ItemIndex > 0 then
sThisValue := sThisValue + ',';
sThisValue := sThisValue +
IntToStr( TIEIntegerList(tvThisValue.AsObject)[ ItemIndex ] );
end;
slPropVals.Values[ sPropName + '.Items' ] := sThisValue;
end
else
begin
varThisValue := tvThisValue.AsVariant;
sThisValue := VarToStr( varThisValue );
slPropVals.Values[ sPropName ] := sThisValue;
end;
except
on E: Exception do
raise Exception.CreateFmt( 'Error writing TWAIN property %s to file %s',
[ sPropName, FileName ] );
end;
end;
sParentDirectory := TPath.GetDirectoryName( FileName );
if ( sParentDirectory <> '' ) and
TPath.HasValidPathChars( sParentDirectory, False ) and
not TDirectory.Exists( sParentDirectory ) then
TDirectory.CreateDirectory( sParentDirectory );
slPropVals.SaveToFile( FileName );
Result := True;
finally
slPropVals.Free;
end;
end;
end.
"Roj"
|
6 L A T E S T R E P L I E S (Newest First) |
xequte |
Posted - Aug 27 2015 : 00:03:31 Hi
You should not need to call Update after acquire, because properties such as AcquireParams.DuplexEnabled will automatically read the current Twain capabilities.
Nigel Xequte Software www.xequte.com nigel@xequte.com
|
Elemental |
Posted - Aug 25 2015 : 14:48:13 The executable was last modified in May 2015, so I believe it's using ImageEn 6.0.0. I have deployed a temporary version of my program using 6.0.1, but nothing changed.
I wanted to verify what we're supposed to do after setting ShowSettingsOnly to True and calling Acquire. It doesn't seem that the user's settings actually change the properties until I call Update. That's what I have to do, right? The documentation doesn't really say that; it says that Update validates the current parameters against what the scanner supports.
One thought I had was that it was the fault of a Windows Update. One such update was KB2952664, which was a compatibility update. It updates a file called imagingprovider.dll which is not in a standard Windows directory. I don't know if that had anything to do with anything.
|
xequte |
Posted - Aug 24 2015 : 23:04:47 So it worked previously in ImageEn on her system then it stopped working? Did she install a newer driver of firmware for the scanner?
Nigel Xequte Software www.xequte.com nigel@xequte.com
|
Elemental |
Posted - Aug 24 2015 : 18:14:50 Recently, one of my primary users started to report that my ImageEn program wasn't remembering her choice for Duplex scanning. My program shows her a TWAIN dialog, she makes the change, clicks OK and ImageEn doesn't realize it. I verified that her ImageEn program could pull other settings out of the TWAIN dialog such as resolution, color depth, and page size, but it doesn't realize when she chooses Duplex. This is a Canon DR-9080C scanner.
Now, there IS the option to Scan Both Sides Ignoring Blank Pages. She can use that, but sometimes she wants true Duplex where it keeps blank pages. ImageEn used to be able to know which scanning option she chose, but it doesn't anymore. Without any changes on my end in the past few months, it doesn't work anymore. Any ideas?
|
xequte |
Posted - Apr 03 2014 : 17:42:17 Thanks Roj,
Avaialble as a unit here with some modifications to make it more similar to ImageEn styling:
www.imageen.com/files/Other/iexTwainHelperFunctions.pas
Note: - Not tested - Requires Delphu/C++ 2010 or newer
Nigel Xequte Software www.xequte.com nigel@xequte.com
|
Elemental |
Posted - Mar 26 2014 : 13:55:09 I apologize, but the code that read the parameters was wrong, where a certain else statement would never be reached.
function TIETwainHelper.LoadSettingsFromFile(FileName: TFileName): Boolean;
var
slPropVals: TStringList;
iLastSource: Integer;
rcRttiContext: TRttiContext;
rtThisType: TRttiType;
iPropertyIndex: Integer;
sPropName: String;
rpThisProperty: TRttiProperty;
tvThisValue: TValue;
varThisValue: Variant;
begin
if TFile.Exists( FileName ) then
begin
slPropVals := TStringList.Create;
try
begin
slPropVals.LoadFromFile( FileName );
iLastSource := StrToIntDef( slPropVals.Values[ 'SelectedSource' ], -1 );
SelectedSource := iLastSource;
rcRttiContext := TRttiContext.Create;
rtThisType := rcRttiContext.GetType( ClassType );
for iPropertyIndex := Low( StoredSettingsProperties ) to High( StoredSettingsProperties ) do
begin
sPropName := StoredSettingsProperties[ iPropertyIndex ];
if sPropName <> 'SelectedSource' then
begin
rpThisProperty := rtThisType.GetProperty( sPropName );
if Assigned( rpThisProperty ) then
try
tvThisValue := rpThisProperty.GetValue( Self );
if tvThisValue.IsObject then
begin
if tvThisValue.AsObject is TIEDoubleList then
begin
if slPropVals.IndexOfName( sPropName + '.CurrentValue' ) > -1 then
TIEDoubleList(tvThisValue.AsObject).CurrentValue :=
StrToFloat( slPropVals.Values[ sPropName + '.CurrentValue' ] );
end
else
if tvThisValue.AsObject is TIEIntegerList then
begin
if slPropVals.IndexOfName( sPropName + '.CurrentValue' ) > -1 then
TIEIntegerList(tvThisValue.AsObject).CurrentValue :=
StrToInt( slPropVals.Values[ sPropName + '.CurrentValue' ] );
end
end
else
if slPropVals.IndexOfName( sPropName ) > -1 then
if rpThisProperty.IsWritable then
begin
varThisValue := slPropVals.Values[ sPropName ];
tvThisValue.FromVariant( varThisValue );
rpThisProperty.SetValue( Self, tvThisValue );
end;
except
on E: Exception do
raise Exception.CreateFmt( 'Error reading TWAIN property %s from file %s',
[ sPropName, FileName ] );
end;
end;
end;
end;
finally
slPropVals.Free;
end;
Result := True;
end
else
Result := False;
end;
|
|
|