Added workaround ability for #50.

This commit is contained in:
Eugene Wang 2015-08-26 20:54:57 -04:00
parent 69d76569ff
commit c1c61c471b
7 changed files with 196 additions and 61 deletions

View File

@ -70,7 +70,7 @@
<HintPath>..\..\packages\Microsoft.WindowsAPICodePack-Shell.1.1.0.0\lib\Microsoft.WindowsAPICodePack.ShellExtensions.dll</HintPath> <HintPath>..\..\packages\Microsoft.WindowsAPICodePack-Shell.1.1.0.0\lib\Microsoft.WindowsAPICodePack.ShellExtensions.dll</HintPath>
</Reference> </Reference>
<Reference Include="ModernWPF, Version=1.0.0.0, Culture=neutral, PublicKeyToken=c99d0cfbea7491ef, processorArchitecture=MSIL"> <Reference Include="ModernWPF, Version=1.0.0.0, Culture=neutral, PublicKeyToken=c99d0cfbea7491ef, processorArchitecture=MSIL">
<HintPath>..\..\packages\ModernWPF.1.3.0\lib\net40-Client\ModernWPF.dll</HintPath> <HintPath>..\..\packages\ModernWPF.1.3.4\lib\net40-Client\ModernWPF.dll</HintPath>
<Private>True</Private> <Private>True</Private>
</Reference> </Reference>
<Reference Include="ModernWPF.Mvvm, Version=0.7.0.0, Culture=neutral, processorArchitecture=MSIL"> <Reference Include="ModernWPF.Mvvm, Version=0.7.0.0, Culture=neutral, processorArchitecture=MSIL">

View File

@ -1,10 +1,10 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<packages> <packages>
<package id="CommonServiceLocator" version="1.3" targetFramework="net4-client" userInstalled="true" /> <package id="CommonServiceLocator" version="1.3" targetFramework="net4-client" />
<package id="CommonWin32" version="2.0.5.6" targetFramework="net4-client" userInstalled="true" /> <package id="CommonWin32" version="2.0.5.6" targetFramework="net4-client" />
<package id="Microsoft.WindowsAPICodePack-Core" version="1.1.0.2" targetFramework="net4-client" userInstalled="true" /> <package id="Microsoft.WindowsAPICodePack-Core" version="1.1.0.2" targetFramework="net4-client" />
<package id="Microsoft.WindowsAPICodePack-Shell" version="1.1.0.0" targetFramework="net4-client" userInstalled="true" /> <package id="Microsoft.WindowsAPICodePack-Shell" version="1.1.0.0" targetFramework="net4-client" />
<package id="ModernWPF" version="1.3.0" targetFramework="net4-client" userInstalled="true" /> <package id="ModernWPF" version="1.3.4" targetFramework="net4-client" />
<package id="ModernWPF.Mvvm" version="0.7.3" targetFramework="net4-client" userInstalled="true" /> <package id="ModernWPF.Mvvm" version="0.7.3" targetFramework="net4-client" />
<package id="MvvmLightLibs" version="5.1.1.0" targetFramework="net4-client" userInstalled="true" /> <package id="MvvmLightLibs" version="5.1.1.0" targetFramework="net4-client" />
</packages> </packages>

View File

@ -300,13 +300,43 @@ namespace NTwain
return default(TValue); return default(TValue);
} }
/// <summary>
/// Gets all the possible values of this capability without expanding.
/// This may be required to work with large range values that cannot be safely enumerated
/// with <see cref="GetValues"/>.
/// </summary>
/// <returns></returns>
public CapabilityReader GetValuesRaw()
{
using (TWCapability cap = new TWCapability(Capability))
{
var rc = _source.DGControl.Capability.Get(cap);
if (rc == ReturnCode.Success)
{
return CapabilityReader.ReadValue(cap);
}
}
return null;
}
/// <summary>
/// Converts the object values into typed values using the conversion routine
/// for this capability.
/// </summary>
/// <param name="values">The values.</param>
/// <returns></returns>
public IEnumerable<TValue> ConvertValues(IEnumerable<object> values)
{
return values.Select(o => _getConvertRoutine(o));
}
/// <summary> /// <summary>
/// Gets all the possible values of this capability. /// Gets all the possible values of this capability.
/// </summary> /// </summary>
/// <returns></returns> /// <returns></returns>
public IList<TValue> GetValues() public IEnumerable<TValue> GetValues()
{ {
return _source.Capabilities.GetValues(Capability).Select(o => _getConvertRoutine(o)).ToList(); return _source.Capabilities.GetValues(Capability).Select(o => _getConvertRoutine(o));//.ToList();
} }
/// <summary> /// <summary>
@ -366,7 +396,7 @@ namespace NTwain
/// [Experimental] Gets the display names for possible values of this capability. /// [Experimental] Gets the display names for possible values of this capability.
/// </summary> /// </summary>
/// <returns></returns> /// <returns></returns>
public IList<string> GetLabelEnum() public IEnumerable<string> GetLabelEnum()
{ {
var list = new List<object>(); var list = new List<object>();
@ -375,10 +405,10 @@ namespace NTwain
var rc = _source.DGControl.Capability.GetLabelEnum(cap); var rc = _source.DGControl.Capability.GetLabelEnum(cap);
if (rc == ReturnCode.Success) if (rc == ReturnCode.Success)
{ {
CapabilityReader.ReadValue(cap).PopulateFromCapValues(list); return CapabilityReader.ReadValue(cap).EnumerateCapValues().Select(o => o.ToString());
} }
} }
return list.Select(o => o.ToString()).ToList(); return Enumerable.Empty<string>();
} }
#endregion #endregion

View File

@ -134,18 +134,17 @@ namespace NTwain
/// </summary> /// </summary>
/// <param name="capabilityId">The capability id.</param> /// <param name="capabilityId">The capability id.</param>
/// <returns></returns> /// <returns></returns>
public IList<object> GetValues(CapabilityId capabilityId) public IEnumerable<object> GetValues(CapabilityId capabilityId)
{ {
var list = new List<object>();
using (TWCapability cap = new TWCapability(capabilityId)) using (TWCapability cap = new TWCapability(capabilityId))
{ {
var rc = _source.DGControl.Capability.Get(cap); var rc = _source.DGControl.Capability.Get(cap);
if (rc == ReturnCode.Success) if (rc == ReturnCode.Success)
{ {
CapabilityReader.ReadValue(cap).PopulateFromCapValues(list); return CapabilityReader.ReadValue(cap).EnumerateCapValues();
} }
} }
return list; return Enumerable.Empty<object>();
} }
/// <summary> /// <summary>

View File

@ -2,7 +2,9 @@
using NTwain.Properties; using NTwain.Properties;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization; using System.Globalization;
using System.Linq;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
namespace NTwain namespace NTwain
@ -75,7 +77,7 @@ namespace NTwain
ContainerType = capability.ContainerType, ContainerType = capability.ContainerType,
}.ReadRangeValue(baseAddr); }.ReadRangeValue(baseAddr);
default: default:
throw new ArgumentException(string.Format(CultureInfo.InvariantCulture, throw new ArgumentException(string.Format(CultureInfo.InvariantCulture,
Resources.CapHasBadContainer, capability.Capability, capability.ContainerType), "capability"); Resources.CapHasBadContainer, capability.Capability, capability.ContainerType), "capability");
} }
} }
@ -94,6 +96,14 @@ namespace NTwain
} }
} }
/// <summary>
/// Initializes a new instance of the <see cref="CapabilityReader"/> class.
/// </summary>
public CapabilityReader()
{
RangeCount = -1;
}
#region common prop #region common prop
/// <summary> /// <summary>
@ -121,7 +131,7 @@ namespace NTwain
public object OneValue { get; private set; } public object OneValue { get; private set; }
/// <summary> /// <summary>
/// Gets the collection values if container is <see cref="NTwain.Data.ContainerType.Enum"/> or <see cref="NTwain.Data.ContainerType.Range"/> . /// Gets the collection values if container is <see cref="NTwain.Data.ContainerType.Enum"/> or <see cref="NTwain.Data.ContainerType.Array"/> .
/// </summary> /// </summary>
/// <value> /// <value>
/// The collection values. /// The collection values.
@ -182,45 +192,52 @@ namespace NTwain
/// </value> /// </value>
public object RangeStepSize { get; private set; } public object RangeStepSize { get; private set; }
/// <summary>
/// Gets the number of range values if range is expanded.
/// You should check for this before expanding range type containers to prevent
/// possible <see cref="OutOfMemoryException"/>.
/// </summary>
/// <value>
/// The range count.
/// </value>
public int RangeCount { get; private set; }
#endregion #endregion
#region reader methods #region reader methods
/// <summary> /// <summary>
/// Don't care what contain it is, just populates the specified list with the capability values (count be one or many). /// Don't care what container it is, just enumerate the capability values.
/// </summary> /// </summary>
/// <param name="toPopulate">The list to populate the values.</param>
/// <returns></returns> /// <returns></returns>
public IList<object> PopulateFromCapValues(IList<object> toPopulate) public IEnumerable<object> EnumerateCapValues()
{ {
if (toPopulate == null) { toPopulate = new List<object>(); }
switch (ContainerType) switch (ContainerType)
{ {
case ContainerType.OneValue: case ContainerType.OneValue:
if (OneValue != null) return EnumerateOneValue();
{
toPopulate.Add(OneValue);
}
break;
case ContainerType.Array: case ContainerType.Array:
case ContainerType.Enum: case ContainerType.Enum:
if (CollectionValues != null) if (CollectionValues != null)
{ {
foreach (var o in CollectionValues) return CollectionValues;
{
toPopulate.Add(o);
}
} }
break; break;
case ContainerType.Range: case ContainerType.Range:
PopulateRange(toPopulate); return EnumerateRange();
break;
} }
return toPopulate; return Enumerable.Empty<object>();
} }
private void PopulateRange(IList<object> toPopulate) IEnumerable<object> EnumerateOneValue()
{
if (OneValue != null)
{
yield return OneValue;
}
}
IEnumerable<object> EnumerateRange()
{ {
// horrible cast but should work. // horrible cast but should work.
// in the for loop we also compare against min in case the step // in the for loop we also compare against min in case the step
@ -235,7 +252,7 @@ namespace NTwain
for (var i = min; i >= min && i <= max; i += step) for (var i = min; i >= min && i <= max; i += step)
{ {
toPopulate.Add(i); yield return i;
} }
} }
break; break;
@ -247,7 +264,7 @@ namespace NTwain
for (var i = min; i >= min && i <= max; i += step) for (var i = min; i >= min && i <= max; i += step)
{ {
toPopulate.Add(i); yield return i;
} }
} }
break; break;
@ -259,7 +276,7 @@ namespace NTwain
for (var i = min; i >= min && i <= max; i += step) for (var i = min; i >= min && i <= max; i += step)
{ {
toPopulate.Add(i); yield return i;
} }
} }
break; break;
@ -272,7 +289,7 @@ namespace NTwain
for (var i = min; i >= min && i <= max; i += step) for (var i = min; i >= min && i <= max; i += step)
{ {
toPopulate.Add(i); yield return i;
} }
} }
break; break;
@ -284,7 +301,7 @@ namespace NTwain
for (var i = min; i >= min && i <= max; i += step) for (var i = min; i >= min && i <= max; i += step)
{ {
toPopulate.Add(i); yield return i;
} }
} }
break; break;
@ -296,7 +313,7 @@ namespace NTwain
for (var i = min; i >= min && i <= max; i += step) for (var i = min; i >= min && i <= max; i += step)
{ {
toPopulate.Add(i); yield return i;
} }
} }
break; break;
@ -308,13 +325,27 @@ namespace NTwain
for (var i = min; i >= min && i <= max; i += step) for (var i = min; i >= min && i <= max; i += step)
{ {
toPopulate.Add(i); yield return i;
} }
} }
break; break;
} }
} }
///// <summary>
///// Don't care what container it is, just populate the specified list with the capability values (count be one or many).
///// </summary>
///// <param name="toPopulate">The list to populate the values.</param>
///// <returns></returns>
//public IList<object> PopulateFromCapValues(IList<object> toPopulate)
//{
// if (toPopulate == null) { toPopulate = new List<object>(); }
// foreach(var obj in EnumerateCapValues())
// {
// toPopulate.Add(obj);
// }
// return toPopulate;
//}
CapabilityReader ReadOneValue(IntPtr baseAddr) CapabilityReader ReadOneValue(IntPtr baseAddr)
{ {
@ -377,16 +408,75 @@ namespace NTwain
RangeDefaultValue = baseAddr.ReadValue(ref offset, ItemType); RangeDefaultValue = baseAddr.ReadValue(ref offset, ItemType);
RangeCurrentValue = baseAddr.ReadValue(ref offset, ItemType); RangeCurrentValue = baseAddr.ReadValue(ref offset, ItemType);
//RangeMinValue = (uint)Marshal.ReadInt32(baseAddr, offset);
//offset += 4;
//RangeMaxValue = (uint)Marshal.ReadInt32(baseAddr, offset);
//offset += 4;
//RangeStepSize = (uint)Marshal.ReadInt32(baseAddr, offset);
//offset += 4;
//RangeDefaultValue = (uint)Marshal.ReadInt32(baseAddr, offset);
//offset += 4;
//RangeCurrentValue = (uint)Marshal.ReadInt32(baseAddr, offset);
// do range count
switch (ItemType)
{
case Data.ItemType.Fix32:
{
var min = (TWFix32)RangeMinValue;
var max = (TWFix32)RangeMaxValue;
var step = (TWFix32)RangeStepSize;
RangeCount = (int)((max - min) / step) + 1;
}
break;
case Data.ItemType.UInt32:
{
var min = (uint)RangeMinValue;
var max = (uint)RangeMaxValue;
var step = (uint)RangeStepSize;
RangeCount = (int)((max - min) / step) + 1;
}
break;
case Data.ItemType.Int32:
{
var min = (int)RangeMinValue;
var max = (int)RangeMaxValue;
var step = (int)RangeStepSize;
RangeCount = ((max - min) / step) + 1;
}
break;
// these should never happen since TW_ENUM fields are 4 bytes but you never know
case Data.ItemType.UInt16:
{
var min = (ushort)RangeMinValue;
var max = (ushort)RangeMaxValue;
var step = (ushort)RangeStepSize;
RangeCount = ((max - min) / step) + 1;
}
break;
case Data.ItemType.Int16:
{
var min = (short)RangeMinValue;
var max = (short)RangeMaxValue;
var step = (short)RangeStepSize;
RangeCount = ((max - min) / step) + 1;
}
break;
case Data.ItemType.UInt8:
{
var min = (byte)RangeMinValue;
var max = (byte)RangeMaxValue;
var step = (byte)RangeStepSize;
RangeCount = ((max - min) / step) + 1;
}
break;
case Data.ItemType.Int8:
{
var min = (sbyte)RangeMinValue;
var max = (sbyte)RangeMaxValue;
var step = (sbyte)RangeStepSize;
RangeCount = ((max - min) / step) + 1;
}
break;
}
return this; return this;
} }

View File

@ -91,11 +91,27 @@ namespace NTwain
/// </value> /// </value>
CapabilityId Capability { get; } CapabilityId Capability { get; }
/// <summary>
/// Gets all the possible values of this capability without expanding.
/// This may be required to work with large range values that cannot be safely enumerated
/// with <see cref="GetValues"/>.
/// </summary>
/// <returns></returns>
CapabilityReader GetValuesRaw();
/// <summary>
/// Converts the object values into typed values using the conversion routine
/// for this capability.
/// </summary>
/// <param name="values">The values.</param>
/// <returns></returns>
IEnumerable<TValue> ConvertValues(IEnumerable<object> values);
/// <summary> /// <summary>
/// Gets all the possible values of this capability. /// Gets all the possible values of this capability.
/// </summary> /// </summary>
/// <returns></returns> /// <returns></returns>
IList<TValue> GetValues(); IEnumerable<TValue> GetValues();
/// <summary> /// <summary>
/// Gets the current value of this capability. /// Gets the current value of this capability.
@ -125,7 +141,7 @@ namespace NTwain
/// [Experimental] Gets the display names for possible values of this capability. /// [Experimental] Gets the display names for possible values of this capability.
/// </summary> /// </summary>
/// <returns></returns> /// <returns></returns>
IList<string> GetLabelEnum(); IEnumerable<string> GetLabelEnum();
/// <summary> /// <summary>
/// Gets a value indicating whether this capability is at all supported. /// Gets a value indicating whether this capability is at all supported.
@ -162,11 +178,11 @@ namespace NTwain
/// <param name="value">The value.</param> /// <param name="value">The value.</param>
/// <returns></returns> /// <returns></returns>
ReturnCode SetValue(TValue value);/// <summary> ReturnCode SetValue(TValue value);/// <summary>
/// ///
/// A version of Set that uses an array. /// A version of Set that uses an array.
/// </summary> /// </summary>
/// <param name="value">The value.</param> /// <param name="value">The value.</param>
/// <returns></returns> /// <returns></returns>
ReturnCode SetValue(TWArray value); ReturnCode SetValue(TWArray value);
/// <summary> /// <summary>

View File

@ -23,7 +23,7 @@ namespace NTwain
/// <summary> /// <summary>
/// The build release version number. /// The build release version number.
/// </summary> /// </summary>
public const string Build = "3.3.5"; // change this for each nuget release public const string Build = "3.3.6"; // change this for each nuget release
} }