using NTwain.Data; using NTwain.Properties; using System; using System.Collections.Generic; using System.Globalization; using System.Runtime.InteropServices; namespace NTwain { /// /// The one-stop class for reading raw TWAIN cap values from the cap container. /// This contains all the properties for the 4 container types. /// public class CapabilityReader { /// /// Reads the value from a that was returned /// from a TWAIN source. /// /// The capability. /// /// capability /// Capability contains no data.;capability /// or /// capability public static CapabilityReader ReadValue(TWCapability capability) { return ReadValue(capability, PlatformInfo.Current.MemoryManager); } /// /// Reads the value from a that was returned /// from a TWAIN source. /// /// The capability. /// The memory manager. /// /// capability /// or /// platformInfo /// Capability contains no data.;capability /// or /// capability public static CapabilityReader ReadValue(TWCapability capability, IMemoryManager memoryManager) { if (capability == null) { throw new ArgumentNullException("capability"); } if (capability.Container == IntPtr.Zero) { throw new ArgumentException(Resources.CapHasNoData, "capability"); } if (memoryManager == null) { throw new ArgumentNullException("memoryManager"); } IntPtr baseAddr = IntPtr.Zero; try { baseAddr = memoryManager.Lock(capability.Container); switch (capability.ContainerType) { case ContainerType.Array: return new CapabilityReader { ContainerType = capability.ContainerType, }.ReadArrayValue(baseAddr); case ContainerType.Enum: return new CapabilityReader { ContainerType = capability.ContainerType, }.ReadEnumValue(baseAddr); case ContainerType.OneValue: return new CapabilityReader { ContainerType = capability.ContainerType, }.ReadOneValue(baseAddr); case ContainerType.Range: return new CapabilityReader { ContainerType = capability.ContainerType, }.ReadRangeValue(baseAddr); default: throw new ArgumentException(string.Format(CultureInfo.InvariantCulture, Resources.CapHasBadContainer, capability.ContainerType), "capability"); } } finally { if (baseAddr != IntPtr.Zero) { //memoryManager.Unlock(baseAddr); memoryManager.Unlock(capability.Container); } } } #region common prop /// /// Gets the underlying container type. /// /// /// The container. /// public ContainerType ContainerType { get; private set; } /// /// Gets the type of the TWAIN value. /// /// /// The type of the value. /// public ItemType ItemType { get; private set; } /// /// Gets the one value if container is . /// /// /// The one value. /// public object OneValue { get; private set; } /// /// Gets the collection values if container is or . /// /// /// The collection values. /// public IList CollectionValues { get; private set; } #endregion #region enum prop /// /// Gets the current value index if container is . /// public int EnumCurrentIndex { get; private set; } /// /// Gets the default value index if container is . /// public int EnumDefaultIndex { get; private set; } #endregion #region range prop /// /// Gets the current value if container is . /// /// /// The range current value. /// public object RangeCurrentValue { get; private set; } /// /// Gets the default value if container is . /// /// /// The range default value. /// public object RangeDefaultValue { get; private set; } /// /// The least positive/most negative value of the range. /// /// /// The range minimum value. /// public uint RangeMinValue { get; private set; } /// /// The most positive/least negative value of the range. /// /// /// The range maximum value. /// public uint RangeMaxValue { get; private set; } /// /// The delta between two adjacent values of the range. /// e.g. Item2 - Item1 = StepSize; /// /// /// The size of the range step. /// public uint RangeStepSize { get; private set; } #endregion #region reader methods CapabilityReader ReadOneValue(IntPtr baseAddr) { int offset = 0; ItemType = (ItemType)(ushort)Marshal.ReadInt16(baseAddr, offset); offset += 2; OneValue = TypeReader.ReadValue(baseAddr, ref offset, ItemType); return this; } CapabilityReader ReadArrayValue(IntPtr baseAddr) { int offset = 0; ItemType = (ItemType)(ushort)Marshal.ReadInt16(baseAddr, offset); offset += 2; var count = Marshal.ReadInt32(baseAddr, offset); offset += 4; if (count > 0) { CollectionValues = new object[count]; for (int i = 0; i < count; i++) { CollectionValues[i] = TypeReader.ReadValue(baseAddr, ref offset, ItemType); } } return this; } CapabilityReader ReadEnumValue(IntPtr baseAddr) { int offset = 0; ItemType = (ItemType)(ushort)Marshal.ReadInt16(baseAddr, offset); offset += 2; int count = Marshal.ReadInt32(baseAddr, offset); offset += 4; EnumCurrentIndex = Marshal.ReadInt32(baseAddr, offset); offset += 4; EnumDefaultIndex = Marshal.ReadInt32(baseAddr, offset); offset += 4; if (count > 0) { CollectionValues = new object[count]; for (int i = 0; i < count; i++) { CollectionValues[i] = TypeReader.ReadValue(baseAddr, ref offset, ItemType); } } return this; } CapabilityReader ReadRangeValue(IntPtr baseAddr) { int offset = 0; ItemType = (ItemType)(ushort)Marshal.ReadInt16(baseAddr, offset); offset += 2; 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); return this; } #endregion } }