mirror of
https://github.com/soukoku/ntwain.git
synced 2025-09-19 18:27:56 +08:00
Added range value reads.
This commit is contained in:
@@ -1,5 +1,6 @@
|
|||||||
using NTwain;
|
using NTwain;
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
@@ -75,24 +76,13 @@ namespace Net5Console
|
|||||||
Console.WriteLine();
|
Console.WriteLine();
|
||||||
|
|
||||||
var caps = session.Capabilities;
|
var caps = session.Capabilities;
|
||||||
Console.WriteLine("Device supports these caps:");
|
Console.WriteLine("All device caps:");
|
||||||
foreach (var cap in caps.CAP_SUPPORTEDCAPS.GetValues())
|
foreach (var cap in caps.CAP_SUPPORTEDCAPS.GetValues())
|
||||||
{
|
{
|
||||||
WriteCapInfo(caps, cap);
|
WriteCapInfo(caps, cap);
|
||||||
}
|
}
|
||||||
Console.WriteLine();
|
Console.WriteLine();
|
||||||
|
|
||||||
var pxWrapper = caps.ICAP_PIXELTYPE;
|
|
||||||
Console.WriteLine($"Details on {pxWrapper.Cap}:");
|
|
||||||
Console.WriteLine($"\tDefault: {pxWrapper.GetDefault()}");
|
|
||||||
Console.WriteLine($"\tCurrent: {pxWrapper.GetCurrent()}");
|
|
||||||
Console.WriteLine($"\tValues:");
|
|
||||||
foreach (var val in pxWrapper.GetValues())
|
|
||||||
{
|
|
||||||
Console.WriteLine($"\t\t{val}");
|
|
||||||
}
|
|
||||||
Console.WriteLine();
|
|
||||||
|
|
||||||
var sts = session.StartCapture(false);
|
var sts = session.StartCapture(false);
|
||||||
if (sts == STS.SUCCESS)
|
if (sts == STS.SUCCESS)
|
||||||
{
|
{
|
||||||
@@ -124,15 +114,31 @@ namespace Net5Console
|
|||||||
|
|
||||||
private static void WriteCapInfo(Capabilities caps, CAP cap)
|
private static void WriteCapInfo(Capabilities caps, CAP cap)
|
||||||
{
|
{
|
||||||
// use reflection due to generics
|
// use reflection due to unknown generics
|
||||||
var propInfo = typeof(Capabilities).GetProperty(cap.ToString());
|
var propInfo = typeof(Capabilities).GetProperty(cap.ToString());
|
||||||
if (propInfo == null) return;
|
if (propInfo == null) return;
|
||||||
|
|
||||||
var capWrapper = propInfo.GetValue(caps);
|
var capWrapper = propInfo.GetValue(caps);
|
||||||
var label = (string)capWrapper.GetType().GetMethod(nameof(CapWrapper<int>.GetLabel)).Invoke(capWrapper, null);
|
var wrapType = capWrapper.GetType();
|
||||||
var supports = (TWQC)capWrapper.GetType().GetMethod(nameof(CapWrapper<int>.QuerySupport)).Invoke(capWrapper, null);
|
var label = (string)wrapType.GetMethod(nameof(CapWrapper<int>.GetLabel)).Invoke(capWrapper, null);
|
||||||
|
var supports = (TWQC)wrapType.GetMethod(nameof(CapWrapper<int>.QuerySupport)).Invoke(capWrapper, null);
|
||||||
|
|
||||||
Console.WriteLine($"\t{label ?? cap.ToString()}: {supports}");
|
Console.WriteLine($"\t{label ?? cap.ToString()}: {supports}");
|
||||||
|
Console.WriteLine($"\t\tDefault: {wrapType.GetMethod(nameof(CapWrapper<int>.GetDefault)).Invoke(capWrapper, null)}");
|
||||||
|
Console.WriteLine($"\t\tCurrent: {wrapType.GetMethod(nameof(CapWrapper<int>.GetCurrent)).Invoke(capWrapper, null)}");
|
||||||
|
bool first = true;
|
||||||
|
foreach (var val in (IEnumerable)wrapType.GetMethod(nameof(CapWrapper<int>.GetValues)).Invoke(capWrapper, null))
|
||||||
|
{
|
||||||
|
if (first)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"\t\tValues:\t{val}");
|
||||||
|
first = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Console.WriteLine($"\t\t\t{val}");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -66,7 +66,7 @@ namespace NTwain
|
|||||||
case TWON.ARRAY:
|
case TWON.ARRAY:
|
||||||
return ValueReader.ReadArray<TValue>(_twain, twCap);
|
return ValueReader.ReadArray<TValue>(_twain, twCap);
|
||||||
case TWON.RANGE:
|
case TWON.RANGE:
|
||||||
return ValueReader.ReadRange<TValue>(_twain, twCap).values.ToList();
|
return ValueReader.ReadRange<TValue>(_twain, twCap).ToList();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return new TValue[0];
|
return new TValue[0];
|
||||||
@@ -96,7 +96,7 @@ namespace NTwain
|
|||||||
return enumeration.Items[enumeration.CurrentIndex];
|
return enumeration.Items[enumeration.CurrentIndex];
|
||||||
break;
|
break;
|
||||||
case TWON.RANGE:
|
case TWON.RANGE:
|
||||||
return ValueReader.ReadRange<TValue>(_twain, twCap).currentVal;
|
return ValueReader.ReadRange<TValue>(_twain, twCap).CurrentValue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return default(TValue);
|
return default(TValue);
|
||||||
@@ -126,7 +126,7 @@ namespace NTwain
|
|||||||
return enumeration.Items[enumeration.DefaultIndex];
|
return enumeration.Items[enumeration.DefaultIndex];
|
||||||
break;
|
break;
|
||||||
case TWON.RANGE:
|
case TWON.RANGE:
|
||||||
return ValueReader.ReadRange<TValue>(_twain, twCap).defaultVal;
|
return ValueReader.ReadRange<TValue>(_twain, twCap).DefaultValue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return default(TValue);
|
return default(TValue);
|
||||||
|
@@ -7,6 +7,7 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.CSharp" Version="4.7.0" />
|
||||||
<PackageReference Include="System.ValueTuple" Version="4.5.0" />
|
<PackageReference Include="System.ValueTuple" Version="4.5.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
@@ -1,4 +1,6 @@
|
|||||||
using System;
|
using NTwain;
|
||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
@@ -30,14 +32,85 @@ namespace TWAINWorkingGroup
|
|||||||
/// <typeparam name="TValue"></typeparam>
|
/// <typeparam name="TValue"></typeparam>
|
||||||
public class Enumeration<TValue> where TValue : struct
|
public class Enumeration<TValue> where TValue : struct
|
||||||
{
|
{
|
||||||
public int CurrentIndex { get; set; }
|
public int CurrentIndex;
|
||||||
|
|
||||||
public int DefaultIndex { get; set; }
|
public int DefaultIndex;
|
||||||
|
|
||||||
public TValue[] Items { get; set; }
|
public TValue[] Items;
|
||||||
}
|
}
|
||||||
|
|
||||||
partial struct TW_FIX32 : IEquatable<TW_FIX32>
|
/// <summary>
|
||||||
|
/// A more dotnet-friendly representation of <see cref="TW_RANGE"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="TValue"></typeparam>
|
||||||
|
public partial class Range<TValue> : IEnumerable<TValue> where TValue : struct
|
||||||
|
{
|
||||||
|
public TValue MinValue;
|
||||||
|
public TValue MaxValue;
|
||||||
|
public TValue StepSize;
|
||||||
|
public TValue DefaultValue;
|
||||||
|
public TValue CurrentValue;
|
||||||
|
|
||||||
|
IEnumerator<TValue> IEnumerable<TValue>.GetEnumerator()
|
||||||
|
{
|
||||||
|
if (!(MinValue is IConvertible))
|
||||||
|
throw new NotSupportedException($"The value type {typeof(TValue).Name} is not supported as range.");
|
||||||
|
|
||||||
|
return new DynamicEnumerator(MinValue, MaxValue, StepSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
IEnumerator IEnumerable.GetEnumerator()
|
||||||
|
{
|
||||||
|
return ((IEnumerable<TValue>)this).GetEnumerator();
|
||||||
|
}
|
||||||
|
|
||||||
|
// dynamic is a cheap hack to sidestep the compiler restrictions if I know TValue is numeric
|
||||||
|
class DynamicEnumerator : IEnumerator<TValue>
|
||||||
|
{
|
||||||
|
private TValue _min;
|
||||||
|
private TValue _max;
|
||||||
|
private TValue _step;
|
||||||
|
private TValue _cur;
|
||||||
|
bool started = false;
|
||||||
|
|
||||||
|
public DynamicEnumerator(TValue min, TValue max, TValue step)
|
||||||
|
{
|
||||||
|
_min = min;
|
||||||
|
_max = max;
|
||||||
|
_step = step;
|
||||||
|
_cur = min;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TValue Current => _cur;
|
||||||
|
|
||||||
|
object IEnumerator.Current => this.Current;
|
||||||
|
|
||||||
|
public void Dispose() { }
|
||||||
|
|
||||||
|
public bool MoveNext()
|
||||||
|
{
|
||||||
|
if (!started)
|
||||||
|
{
|
||||||
|
started = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
var next = _cur + (dynamic)_step;
|
||||||
|
if (next == _cur || next < _min || next > _max) return false;
|
||||||
|
|
||||||
|
_cur = next;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Reset()
|
||||||
|
{
|
||||||
|
_cur = _min;
|
||||||
|
started = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
partial struct TW_FIX32 : IEquatable<TW_FIX32>, IConvertible
|
||||||
{
|
{
|
||||||
// the conversion logic is found in the spec.
|
// the conversion logic is found in the spec.
|
||||||
|
|
||||||
@@ -84,6 +157,96 @@ namespace TWAINWorkingGroup
|
|||||||
return Whole ^ Frac;
|
return Whole ^ Frac;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#region IConvertable
|
||||||
|
|
||||||
|
TypeCode IConvertible.GetTypeCode()
|
||||||
|
{
|
||||||
|
return TypeCode.Single;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IConvertible.ToBoolean(IFormatProvider provider)
|
||||||
|
{
|
||||||
|
return this != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
byte IConvertible.ToByte(IFormatProvider provider)
|
||||||
|
{
|
||||||
|
return Convert.ToByte((float)this);
|
||||||
|
}
|
||||||
|
|
||||||
|
char IConvertible.ToChar(IFormatProvider provider)
|
||||||
|
{
|
||||||
|
return Convert.ToChar((float)this);
|
||||||
|
}
|
||||||
|
|
||||||
|
DateTime IConvertible.ToDateTime(IFormatProvider provider)
|
||||||
|
{
|
||||||
|
return Convert.ToDateTime((float)this);
|
||||||
|
}
|
||||||
|
|
||||||
|
decimal IConvertible.ToDecimal(IFormatProvider provider)
|
||||||
|
{
|
||||||
|
return Convert.ToDecimal((float)this);
|
||||||
|
}
|
||||||
|
|
||||||
|
double IConvertible.ToDouble(IFormatProvider provider)
|
||||||
|
{
|
||||||
|
return Convert.ToDouble((float)this);
|
||||||
|
}
|
||||||
|
|
||||||
|
short IConvertible.ToInt16(IFormatProvider provider)
|
||||||
|
{
|
||||||
|
return Convert.ToInt16((float)this);
|
||||||
|
}
|
||||||
|
|
||||||
|
int IConvertible.ToInt32(IFormatProvider provider)
|
||||||
|
{
|
||||||
|
return Convert.ToInt32((float)this);
|
||||||
|
}
|
||||||
|
|
||||||
|
long IConvertible.ToInt64(IFormatProvider provider)
|
||||||
|
{
|
||||||
|
return Convert.ToInt64((float)this);
|
||||||
|
}
|
||||||
|
|
||||||
|
sbyte IConvertible.ToSByte(IFormatProvider provider)
|
||||||
|
{
|
||||||
|
return Convert.ToSByte((float)this);
|
||||||
|
}
|
||||||
|
|
||||||
|
float IConvertible.ToSingle(IFormatProvider provider)
|
||||||
|
{
|
||||||
|
return Convert.ToSingle((float)this);
|
||||||
|
}
|
||||||
|
|
||||||
|
string IConvertible.ToString(IFormatProvider provider)
|
||||||
|
{
|
||||||
|
return this.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
object IConvertible.ToType(Type conversionType, IFormatProvider provider)
|
||||||
|
{
|
||||||
|
return Convert.ChangeType((float)this, conversionType, CultureInfo.InvariantCulture);
|
||||||
|
}
|
||||||
|
|
||||||
|
ushort IConvertible.ToUInt16(IFormatProvider provider)
|
||||||
|
{
|
||||||
|
return Convert.ToUInt16((float)this);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint IConvertible.ToUInt32(IFormatProvider provider)
|
||||||
|
{
|
||||||
|
return Convert.ToUInt32((float)this);
|
||||||
|
}
|
||||||
|
|
||||||
|
ulong IConvertible.ToUInt64(IFormatProvider provider)
|
||||||
|
{
|
||||||
|
return Convert.ToUInt64((float)this);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
public static implicit operator float(TW_FIX32 value) => value.ToFloat();
|
public static implicit operator float(TW_FIX32 value) => value.ToFloat();
|
||||||
public static implicit operator TW_FIX32(float value) => new TW_FIX32(value);
|
public static implicit operator TW_FIX32(float value) => new TW_FIX32(value);
|
||||||
|
|
||||||
|
@@ -12503,7 +12503,7 @@ namespace TWAINWorkingGroup
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// The platform we're running on...
|
/// The platform we're running on...
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private static Platform ms_platform;
|
static Platform ms_platform;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Delegates for DAT_CALLBACK...
|
/// Delegates for DAT_CALLBACK...
|
||||||
|
@@ -14,6 +14,8 @@ namespace NTwain
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public static class ValueReader
|
public static class ValueReader
|
||||||
{
|
{
|
||||||
|
// most of these are modified from the original TWAIN.CapabilityToCsv()
|
||||||
|
|
||||||
public static TValue ReadOneValue<TValue>(TWAIN twain, TW_CAPABILITY cap, bool freeMemory = true) where TValue : struct
|
public static TValue ReadOneValue<TValue>(TWAIN twain, TW_CAPABILITY cap, bool freeMemory = true) where TValue : struct
|
||||||
{
|
{
|
||||||
if (cap.hContainer == IntPtr.Zero) return default(TValue);
|
if (cap.hContainer == IntPtr.Zero) return default(TValue);
|
||||||
@@ -157,10 +159,98 @@ namespace NTwain
|
|||||||
if (freeMemory) twain.DsmMemFree(ref cap.hContainer);
|
if (freeMemory) twain.DsmMemFree(ref cap.hContainer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public static (TValue defaultVal, TValue currentVal, IEnumerable<TValue> values)
|
public static Range<TValue> ReadRange<TValue>(TWAIN twain, TW_CAPABILITY cap, bool freeMemory = true) where TValue : struct
|
||||||
ReadRange<TValue>(TWAIN twain, TW_CAPABILITY cap, bool freeMemory = true) where TValue : struct
|
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
var retVal = new Range<TValue>();
|
||||||
|
|
||||||
|
if (cap.hContainer == IntPtr.Zero) return retVal;
|
||||||
|
|
||||||
|
var lockedPtr = twain.DsmMemLock(cap.hContainer);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
TW_RANGE twrange = default;
|
||||||
|
TW_RANGE_FIX32 twrangefix32 = default;
|
||||||
|
var platform = PlatformTools.GetPlatform();
|
||||||
|
|
||||||
|
// Mac has a level of indirection and a different structure (ick)...
|
||||||
|
if (platform == Platform.MACOSX)
|
||||||
|
{
|
||||||
|
var twrangemacosx = MarshalTo<TW_RANGE_MACOSX>(lockedPtr);
|
||||||
|
var twrangefix32macosx = MarshalTo<TW_RANGE_FIX32_MACOSX>(lockedPtr);
|
||||||
|
twrange.ItemType = (TWTY)twrangemacosx.ItemType;
|
||||||
|
twrange.MinValue = twrangemacosx.MinValue;
|
||||||
|
twrange.MaxValue = twrangemacosx.MaxValue;
|
||||||
|
twrange.StepSize = twrangemacosx.StepSize;
|
||||||
|
twrange.DefaultValue = twrangemacosx.DefaultValue;
|
||||||
|
twrange.CurrentValue = twrangemacosx.CurrentValue;
|
||||||
|
twrangefix32.ItemType = (TWTY)twrangefix32macosx.ItemType;
|
||||||
|
twrangefix32.MinValue = twrangefix32macosx.MinValue;
|
||||||
|
twrangefix32.MaxValue = twrangefix32macosx.MaxValue;
|
||||||
|
twrangefix32.StepSize = twrangefix32macosx.StepSize;
|
||||||
|
twrangefix32.DefaultValue = twrangefix32macosx.DefaultValue;
|
||||||
|
twrangefix32.CurrentValue = twrangefix32macosx.CurrentValue;
|
||||||
|
}
|
||||||
|
// Windows or the 2.4+ Linux DSM...
|
||||||
|
else if ((platform == Platform.WINDOWS) || (twain.m_linuxdsm == TWAIN.LinuxDsm.IsLatestDsm) ||
|
||||||
|
((twain.m_blFoundLatestDsm || twain.m_blFoundLatestDsm64) && (twain.m_linuxdsm == TWAIN.LinuxDsm.IsLatestDsm)))
|
||||||
|
{
|
||||||
|
twrange = MarshalTo<TW_RANGE>(lockedPtr);
|
||||||
|
twrangefix32 = MarshalTo<TW_RANGE_FIX32>(lockedPtr);
|
||||||
|
}
|
||||||
|
// The -2.3 Linux DSM...
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var twrangelinux64 = MarshalTo<TW_RANGE_LINUX64>(lockedPtr);
|
||||||
|
var twrangefix32macosx = MarshalTo<TW_RANGE_FIX32_MACOSX>(lockedPtr);
|
||||||
|
twrange.ItemType = twrangelinux64.ItemType;
|
||||||
|
twrange.MinValue = (uint)twrangelinux64.MinValue;
|
||||||
|
twrange.MaxValue = (uint)twrangelinux64.MaxValue;
|
||||||
|
twrange.StepSize = (uint)twrangelinux64.StepSize;
|
||||||
|
twrange.DefaultValue = (uint)twrangelinux64.DefaultValue;
|
||||||
|
twrange.CurrentValue = (uint)twrangelinux64.CurrentValue;
|
||||||
|
twrangefix32.ItemType = (TWTY)twrangefix32macosx.ItemType;
|
||||||
|
twrangefix32.MinValue = twrangefix32macosx.MinValue;
|
||||||
|
twrangefix32.MaxValue = twrangefix32macosx.MaxValue;
|
||||||
|
twrangefix32.StepSize = twrangefix32macosx.StepSize;
|
||||||
|
twrangefix32.DefaultValue = twrangefix32macosx.DefaultValue;
|
||||||
|
twrangefix32.CurrentValue = twrangefix32macosx.CurrentValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (twrange.ItemType)
|
||||||
|
{
|
||||||
|
// use dynamic since I know they fit the type.
|
||||||
|
case TWTY.FIX32:
|
||||||
|
retVal.MinValue = (dynamic)twrangefix32.MinValue;
|
||||||
|
retVal.MaxValue = (dynamic)twrangefix32.MaxValue;
|
||||||
|
retVal.StepSize = (dynamic)twrangefix32.StepSize;
|
||||||
|
retVal.CurrentValue = (dynamic)twrangefix32.CurrentValue;
|
||||||
|
retVal.DefaultValue = (dynamic)twrangefix32.DefaultValue;
|
||||||
|
break;
|
||||||
|
case TWTY.INT8:
|
||||||
|
case TWTY.UINT8:
|
||||||
|
case TWTY.INT16:
|
||||||
|
case TWTY.BOOL:
|
||||||
|
case TWTY.UINT16:
|
||||||
|
case TWTY.INT32:
|
||||||
|
case TWTY.UINT32:
|
||||||
|
retVal.MinValue = (dynamic)twrange.MinValue;
|
||||||
|
retVal.MaxValue = (dynamic)twrange.MaxValue;
|
||||||
|
retVal.StepSize = (dynamic)twrange.StepSize;
|
||||||
|
retVal.CurrentValue = (dynamic)twrange.CurrentValue;
|
||||||
|
retVal.DefaultValue = (dynamic)twrange.DefaultValue;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new NotSupportedException($"The value type {twrange.ItemType} is not supported as range.");
|
||||||
|
|
||||||
|
}
|
||||||
|
return retVal;
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
twain.DsmMemUnlock(cap.hContainer);
|
||||||
|
if (freeMemory) twain.DsmMemFree(ref cap.hContainer);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
Reference in New Issue
Block a user