First attempt with TW_CAPABILITY generator with one value support.

This commit is contained in:
Eugene Wang 2018-11-25 06:42:12 -05:00
parent 60138217cd
commit b4e1435987
12 changed files with 465 additions and 83 deletions

199
src/NTwain/CapWriter.cs Normal file
View File

@ -0,0 +1,199 @@
using NTwain.Data;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
namespace NTwain
{
/// <summary>
/// CLass that can generate <see cref="TW_CAPABILITY"/> for use in capability negotiation.
/// </summary>
public class CapWriter
{
private readonly TwainConfig config;
/// <summary>
/// Creates a new <see cref="CapWriter"/>.
/// </summary>
/// <param name="config"></param>
internal CapWriter(TwainConfig config)
{
this.config = config;
}
/// <summary>
/// Generates a <see cref="TW_CAPABILITY"/> using single value (aka TW_ONEVALUE).
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="cap"></param>
/// <param name="type"></param>
/// <param name="value"></param>
/// <returns></returns>
public TW_CAPABILITY Generate<T>(CapabilityId cap, ItemType type, T value)
{
// size of data + uint16 item type
var valueSz = type.GetSize();
if (valueSz < 4) valueSz = 4; // onevalue container value minimum is 32bit
var memSz = valueSz + 2; // + item type field
var twCap = new TW_CAPABILITY
{
Capability = cap,
ContainerType = ContainerType.OneValue,
hContainer = config.MemoryManager.Allocate((uint)memSz)
};
if (twCap.hContainer != IntPtr.Zero)
{
IntPtr baseAddr = config.MemoryManager.Lock(twCap.hContainer);
try
{
int offset = 0;
// TODO: type size may be different on mac
baseAddr.WriteValue(ref offset, ItemType.UInt16, value);
// ONEVALUE is special in value can be uint32 or string
// if less than uint32 put it in lower word
// (string value seems undocumented but internet says put it as-is and not a pointer)
if (valueSz < 4)
{
Marshal.WriteInt16(baseAddr, offset, 0);
offset += 2;
}
baseAddr.WriteValue(ref offset, type, value);
}
finally
{
config.MemoryManager.Unlock(twCap.hContainer);
}
}
return twCap;
}
///// <summary>
///// Generates a <see cref="TW_CAPABILITY"/> for use in capability negotiation
///// using TWAIN's array value.
///// </summary>
///// <typeparam name="T"></typeparam>
///// <param name="cap"></param>
///// <param name="value"></param>
///// <returns></returns>
//public TW_CAPABILITY Generate<T>(CapabilityId cap, ArrayValue<T> value)
//{
// var twCap = new TW_CAPABILITY
// {
// Capability = cap,
// ContainerType = ContainerType.Array
// };
// SetOneValue()
// return twCap;
//}
///// <summary>
///// Generates a <see cref="TW_CAPABILITY"/> for use in capability negotiation
///// using TWAIN's enum value.
///// </summary>
///// <typeparam name="T"></typeparam>
///// <param name="cap"></param>
///// <param name="value"></param>
///// <returns></returns>
//public TW_CAPABILITY Generate<T>(CapabilityId cap, EnumValue<T> value)
//{
// var twCap = new TW_CAPABILITY
// {
// Capability = cap,
// ContainerType = ContainerType.Enum
// };
// return twCap;
//}
///// <summary>
///// Generates a <see cref="TW_CAPABILITY"/> for use in capability negotiation
///// using TWAIN's range value.
///// </summary>
///// <param name="cap"></param>
///// <param name="value"></param>
///// <returns></returns>
//public TW_CAPABILITY Generate(CapabilityId cap, RangeValue value)
//{
// var twCap = new TW_CAPABILITY
// {
// Capability = cap,
// ContainerType = ContainerType.Range
// };
// return twCap;
//}
//void SetEnumValue(TW_ENUMERATION value, IMemoryManager memoryManager)
//{
// if (value == null) { throw new ArgumentNullException("value"); }
// ContainerType = ContainerType.Enum;
// Int32 valueSize = TW_ENUMERATION.ItemOffset + value.ItemList.Length * TypeExtensions.GetItemTypeSize(value.ItemType);
// int offset = 0;
// _hContainer = memoryManager.Allocate((uint)valueSize);
// if (_hContainer != IntPtr.Zero)
// {
// IntPtr baseAddr = memoryManager.Lock(_hContainer);
// // can't safely use StructureToPtr here so write it our own
// baseAddr.WriteValue(ref offset, ItemType.UInt16, value.ItemType);
// baseAddr.WriteValue(ref offset, ItemType.UInt32, (uint)value.ItemList.Length);
// baseAddr.WriteValue(ref offset, ItemType.UInt32, value.CurrentIndex);
// baseAddr.WriteValue(ref offset, ItemType.UInt32, value.DefaultIndex);
// foreach (var item in value.ItemList)
// {
// baseAddr.WriteValue(ref offset, value.ItemType, item);
// }
// memoryManager.Unlock(_hContainer);
// }
//}
//void SetRangeValue(TW_RANGE value, IMemoryManager memoryManager)
//{
// if (value == null) { throw new ArgumentNullException("value"); }
// ContainerType = ContainerType.Range;
// // since range value can only house UInt32 we will not allow type size > 4
// if (TypeExtensions.GetItemTypeSize(value.ItemType) > 4) { throw new ArgumentException(string.Format(CultureInfo.InvariantCulture, Resources.BadValueType, "TW_RANGE")); }
// _hContainer = memoryManager.Allocate((uint)Marshal.SizeOf(value));
// if (_hContainer != IntPtr.Zero)
// {
// Marshal.StructureToPtr(value, _hContainer, false);
// }
//}
//void SetArrayValue(TW_ARRAY value, IMemoryManager memoryManager)
//{
// if (value == null) { throw new ArgumentNullException("value"); }
// ContainerType = ContainerType.Array;
// Int32 valueSize = 6 + value.ItemList.Length * TypeExtensions.GetItemTypeSize(value.ItemType);
// int offset = 0;
// _hContainer = memoryManager.Allocate((uint)valueSize);
// if (_hContainer != IntPtr.Zero)
// {
// IntPtr baseAddr = memoryManager.Lock(_hContainer);
// // can't safely use StructureToPtr here so write it our own
// baseAddr.WriteValue(ref offset, ItemType.UInt16, value.ItemType);
// baseAddr.WriteValue(ref offset, ItemType.UInt32, (uint)value.ItemList.Length);
// foreach (var item in value.ItemList)
// {
// baseAddr.WriteValue(ref offset, value.ItemType, item);
// }
// memoryManager.Unlock(_hContainer);
// }
//}
}
}

View File

@ -35,17 +35,17 @@ namespace NTwain.Data
[StructLayout(LayoutKind.Sequential, Pack = 2)] [StructLayout(LayoutKind.Sequential, Pack = 2)]
partial struct TW_FIX32 partial struct TW_FIX32
{ {
TW_INT16 _whole; internal TW_INT16 Whole;
TW_UINT16 _frac; internal TW_UINT16 Fraction;
} }
[StructLayout(LayoutKind.Sequential, Pack = 2)] [StructLayout(LayoutKind.Sequential, Pack = 2)]
partial struct TW_FRAME partial struct TW_FRAME
{ {
TW_FIX32 _left; internal TW_FIX32 _left;
TW_FIX32 _top; internal TW_FIX32 _top;
TW_FIX32 _right; internal TW_FIX32 _right;
TW_FIX32 _bottom; internal TW_FIX32 _bottom;
} }
[StructLayout(LayoutKind.Sequential, Pack = 2)] [StructLayout(LayoutKind.Sequential, Pack = 2)]
@ -111,7 +111,7 @@ namespace NTwain.Data
{ {
TW_UINT16 _cap; TW_UINT16 _cap;
TW_UINT16 _conType; TW_UINT16 _conType;
TW_HANDLE _hContainer; internal TW_HANDLE hContainer;
} }
[StructLayout(LayoutKind.Sequential, Pack = 2)] [StructLayout(LayoutKind.Sequential, Pack = 2)]
@ -427,13 +427,13 @@ namespace NTwain.Data
TW_UINT32 _sheetCount; TW_UINT32 _sheetCount;
} }
[StructLayout(LayoutKind.Sequential, Pack = 2)] //[StructLayout(LayoutKind.Sequential, Pack = 2)]
partial class TW_ONEVALUE //partial class TW_ONEVALUE
{ //{
// TODO: mac is different? // // TODO: mac is different?
public TW_UINT16 ItemType; // public TW_UINT16 ItemType;
public TW_UINT32 Item; // public TW_UINT32 Item;
} //}
[StructLayout(LayoutKind.Sequential, Pack = 2)] [StructLayout(LayoutKind.Sequential, Pack = 2)]
partial struct TW_PALETTE8 partial struct TW_PALETTE8

View File

@ -32,19 +32,19 @@ namespace NTwain.Data
float ToFloat() float ToFloat()
{ {
return (float)_whole + _frac / 65536f; return (float)Whole + Fraction / 65536f;
} }
TW_FIX32(float value) TW_FIX32(float value)
{ {
//int temp = (int)(value * 65536.0 + 0.5); //int temp = (int)(value * 65536.0 + 0.5);
//_whole = (short)(temp >> 16); //Whole = (short)(temp >> 16);
//_frac = (ushort)(temp & 0x0000ffff); //Fraction = (ushort)(temp & 0x0000ffff);
// different version from twain faq // different version from twain faq
bool sign = value < 0; bool sign = value < 0;
int temp = (int)(value * 65536.0 + (sign ? (-0.5) : 0.5)); int temp = (int)(value * 65536.0 + (sign ? (-0.5) : 0.5));
_whole = (short)(temp >> 16); Whole = (short)(temp >> 16);
_frac = (ushort)(temp & 0x0000ffff); Fraction = (ushort)(temp & 0x0000ffff);
} }
@ -59,33 +59,6 @@ namespace NTwain.Data
return ToFloat().ToString(CultureInfo.InvariantCulture); return ToFloat().ToString(CultureInfo.InvariantCulture);
} }
///// <summary>
///// Converts this to <see cref="TW_ONEVALUE"/> for capability set methods.
///// </summary>
///// <returns></returns>
//public TW_ONEVALUE ToOneValue()
//{
// // copy struct parts as-is.
// // probably has a faster way but can't think now
// byte[] array = new byte[4];
// var part = BitConverter.GetBytes(Whole);
// Buffer.BlockCopy(part, 0, array, 0, 2);
// part = BitConverter.GetBytes(Fraction);
// Buffer.BlockCopy(part, 0, array, 2, 2);
// var converted = BitConverter.ToUInt32(array, 0);
// return new TW_ONEVALUE
// {
// ItemType = ItemType.Fix32,
// Item = converted
// // old wrong conversion
// // (uint)this,// ((uint)dpi) << 16;
// };
//}
#region equals #region equals
/// <summary> /// <summary>
@ -109,7 +82,7 @@ namespace NTwain.Data
/// <returns></returns> /// <returns></returns>
public bool Equals(TW_FIX32 other) public bool Equals(TW_FIX32 other)
{ {
return _whole == other._whole && _frac == other._frac; return Whole == other.Whole && Fraction == other.Fraction;
} }
/// <summary> /// <summary>
/// Returns a hash code for this instance. /// Returns a hash code for this instance.
@ -119,7 +92,7 @@ namespace NTwain.Data
/// </returns> /// </returns>
public override int GetHashCode() public override int GetHashCode()
{ {
return _whole ^ _frac; return Whole ^ Fraction;
} }
#endregion #endregion
@ -621,16 +594,14 @@ namespace NTwain.Data
// #region properties // #region properties
// /// <summary> /// <summary>
// /// Id of capability to set or get. /// Id of capability to set or get.
// /// </summary> /// </summary>
// public CapabilityId Capability { get { return (CapabilityId)_cap; } set { _cap = (ushort)value; } } public CapabilityId Capability { get { return (CapabilityId)_cap; } internal set { _cap = (ushort)value; } }
// /// <summary> /// <summary>
// /// The type of the container structure referenced by the pointer internally. The container /// The type of the container structure referenced by the pointer internally.
// /// will be one of four types: <see cref="TW_ARRAY"/>, <see cref="TW_ENUMERATION"/>, /// </summary>
// /// <see cref="TW_ONEVALUE"/>, or <see cref="TW_RANGE"/>. public ContainerType ContainerType { get { return (ContainerType)_conType; } internal set { _conType = (ushort)value; } }
// /// </summary>
// public ContainerType ContainerType { get { return (ContainerType)_conType; } set { _conType = (ushort)value; } }
// internal IntPtr Container { get { return _hContainer; } } // internal IntPtr Container { get { return _hContainer; } }

View File

@ -84,19 +84,19 @@ namespace NTwain.Data
/// </summary> /// </summary>
Invalid = 0, Invalid = 0,
/// <summary> /// <summary>
/// The container is <see cref="TW_ARRAY"/>. /// The container is TW_ARRAY.
/// </summary> /// </summary>
Array = 3, Array = 3,
/// <summary> /// <summary>
/// The container is <see cref="TW_ENUMERATION"/>. /// The container is TW_ENUMERATION.
/// </summary> /// </summary>
Enum = 4, Enum = 4,
/// <summary> /// <summary>
/// The container is <see cref="TW_ONEVALUE"/>. /// The container is TW_ONEVALUE.
/// </summary> /// </summary>
OneValue = 5, OneValue = 5,
/// <summary> /// <summary>
/// The container is <see cref="TW_RANGE"/>. /// The container is TW_RANGE.
/// </summary> /// </summary>
Range = 6, Range = 6,
/// <summary> /// <summary>

View File

@ -0,0 +1,190 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
namespace NTwain.Data
{
/// <summary>
/// Contains extension methods for reading/writing primitive
/// TWAIN data types.
/// </summary>
static class TypeExtensions
{
static readonly Dictionary<ItemType, int> _sizes = new Dictionary<ItemType, int>
{
{ ItemType.Int8, 1 },
{ ItemType.UInt8, 1 },
{ ItemType.Int16, 2 },
{ ItemType.UInt16, 2 },
{ ItemType.Int32, 4 },
{ ItemType.UInt32, 4 },
{ ItemType.Bool, 2 },
{ ItemType.Fix32, Marshal.SizeOf(typeof(TW_FIX32)) },
{ ItemType.Frame, Marshal.SizeOf(typeof(TW_FRAME)) },
{ ItemType.String128, TwainConst.String128 },
{ ItemType.String255, TwainConst.String255 },
{ ItemType.String32, TwainConst.String32 },
{ ItemType.String64, TwainConst.String64 },
// TODO: find out if it should be fixed 4 bytes or intptr size
{ ItemType.Handle, IntPtr.Size },
};
public static int GetSize(this ItemType type)
{
if(_sizes.TryGetValue(type, out int size)) return size;
throw new NotSupportedException($"Unsupported item type {type}.");
}
#region writes
/// <summary>
/// Writes a TWAIN value.
/// </summary>
/// <param name="baseAddr">The base addr.</param>
/// <param name="offset">The offset.</param>
/// <param name="type">The TWAIN type.</param>
/// <param name="value">The value.</param>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1045:DoNotPassTypesByReference", MessageId = "1#"), System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1800:DoNotCastUnnecessarily")]
public static void WriteValue(this IntPtr baseAddr, ref int offset, ItemType type, object value)
{
switch (type)
{
case ItemType.Int8:
case ItemType.UInt8:
Marshal.WriteByte(baseAddr, offset, Convert.ToByte(value, CultureInfo.InvariantCulture));// (byte)value);
break;
case ItemType.Bool:
case ItemType.Int16:
case ItemType.UInt16:
Marshal.WriteInt16(baseAddr, offset, Convert.ToInt16(value, CultureInfo.InvariantCulture));//(short)value);
break;
case ItemType.UInt32:
case ItemType.Int32:
Marshal.WriteInt32(baseAddr, offset, Convert.ToInt32(value, CultureInfo.InvariantCulture));//(int)value);
break;
case ItemType.Fix32:
TW_FIX32 f32 = (TW_FIX32)value;
WriteFix32(baseAddr, ref offset, f32);
return; // no need to update offset for this
case ItemType.Frame:
TW_FRAME frame = (TW_FRAME)value;
WriteFix32(baseAddr, ref offset, frame._left);
WriteFix32(baseAddr, ref offset, frame._top);
WriteFix32(baseAddr, ref offset, frame._right);
WriteFix32(baseAddr, ref offset, frame._bottom);
return; // no need to update offset for this
//case ItemType.String1024:
// WriteString(baseAddr, offset, value as string, 1024);
// break;
case ItemType.String128:
WriteString(baseAddr, offset, (string)value, 128);
break;
case ItemType.String255:
WriteString(baseAddr, offset, (string)value, 255);
break;
case ItemType.String32:
WriteString(baseAddr, offset, (string)value, 32);
break;
case ItemType.String64:
WriteString(baseAddr, offset, (string)value, 64);
break;
//case ItemType.Unicode512:
// WriteUString(baseAddr, offset, value as string, 512);
// break;
}
offset += type.GetSize();
}
private static void WriteFix32(IntPtr baseAddr, ref int offset, TW_FIX32 f32)
{
Marshal.WriteInt16(baseAddr, offset, f32.Whole);
if (f32.Fraction > Int16.MaxValue)
{
Marshal.WriteInt16(baseAddr, offset + 2, (Int16)(f32.Fraction - 32768));
}
else
{
Marshal.WriteInt16(baseAddr, offset + 2, (Int16)f32.Fraction);
}
offset += _sizes[ItemType.Fix32];
}
/// <summary>
/// Writes string value. THIS MAY BE WRONG.
/// </summary>
/// <param name="baseAddr"></param>
/// <param name="offset"></param>
/// <param name="value"></param>
/// <param name="maxLength"></param>
static void WriteString(IntPtr baseAddr, int offset, string value, int maxLength)
{
if (string.IsNullOrEmpty(value))
{
// write zero
Marshal.WriteByte(baseAddr, offset, 0);
}
else
{
for (int i = 0; i < maxLength; i++)
{
if (i == value.Length)
{
// string end reached, so write \0 and quit
Marshal.WriteByte(baseAddr, offset, 0);
return;
}
else
{
Marshal.WriteByte(baseAddr, offset, (byte)value[i]);
offset++;
}
}
// when ended normally also write \0
Marshal.WriteByte(baseAddr, offset, 0);
}
}
///// <summary>
///// Writes unicode string value.
///// </summary>
///// <param name="baseAddr"></param>
///// <param name="offset"></param>
///// <param name="item"></param>
///// <param name="maxLength"></param>
//[EnvironmentPermissionAttribute(SecurityAction.LinkDemand)]
//private void WriteUString(IntPtr baseAddr, int offset, string item, int maxLength)
//{
// if (string.IsNullOrEmpty(item))
// {
// // write zero
// Marshal.WriteInt16(baseAddr, offset, (char)0);
// }
// else
// {
// // use 2 bytes per char
// for (int i = 0; i < maxLength; i++)
// {
// if (i == item.Length)
// {
// // string end reached, so write \0 and quit
// Marshal.WriteInt16(baseAddr, offset, (char)0);
// return;
// }
// else
// {
// Marshal.WriteInt16(baseAddr, offset, item[i]);
// offset += 2;
// }
// }
// // when ended normally also write \0
// Marshal.WriteByte(baseAddr, offset, 0);
// }
//}
#endregion
}
}

View File

@ -8,7 +8,7 @@ namespace NTwain.Internals
{ {
// probably wrong // probably wrong
class LinuxMemoryManager : IMemoryManager class MarshalMemoryManager : IMemoryManager
{ {
public IntPtr Allocate(uint size) public IntPtr Allocate(uint size)
{ {
@ -22,6 +22,7 @@ namespace NTwain.Internals
public IntPtr Lock(IntPtr handle) public IntPtr Lock(IntPtr handle)
{ {
// no op
return handle; return handle;
} }

View File

@ -41,7 +41,7 @@ namespace NTwain.Threading
{ {
action(); action();
} }
catch (Exception ex) catch
{ {
// TODO: do something // TODO: do something
} }

View File

@ -99,7 +99,7 @@ namespace NTwain.Triplets.Control
} }
/// <summary> /// <summary>
/// Return all of the labels for a capability of type <see cref="TW_ARRAY"/> or <see cref="TW_ENUMERATION"/>, for example /// Return all of the labels for a capability of type TW_ARRAY or TW_ENUMERATION, for example
/// "US Letter" for ICapSupportedSizes TWSS_USLETTER. /// "US Letter" for ICapSupportedSizes TWSS_USLETTER.
/// </summary> /// </summary>
/// <param name="capability">The capability.</param> /// <param name="capability">The capability.</param>
@ -145,8 +145,8 @@ namespace NTwain.Triplets.Control
/// Changes the Current Value(s) and Available Values of the specified capability to those specified /// Changes the Current Value(s) and Available Values of the specified capability to those specified
/// by the application. As of TWAIN 2.2 this only modifies the Current Value of the specified capability, constraints cannot be /// by the application. As of TWAIN 2.2 this only modifies the Current Value of the specified capability, constraints cannot be
/// changed with this. /// changed with this.
/// Current Values are set when the container is a <see cref="TW_ONEVALUE"/> or <see cref="TW_ARRAY"/>. Available and /// Current Values are set when the container is a TW_ONEVALUE or TW_ARRAY. Available and
/// Current Values are set when the container is a <see cref="TW_ENUMERATION"/> or <see cref="TW_RANGE"/>. /// Current Values are set when the container is a TW_ENUMERATION or TW_RANGE.
/// </summary> /// </summary>
/// <param name="capability">The capability.</param> /// <param name="capability">The capability.</param>
/// <returns></returns> /// <returns></returns>
@ -159,8 +159,8 @@ namespace NTwain.Triplets.Control
/// Changes the Current Value(s) and Available Value(s) of the specified capability to those specified /// Changes the Current Value(s) and Available Value(s) of the specified capability to those specified
/// by the application. /// by the application.
/// </summary> /// </summary>
/// Current Values are set when the container is a <see cref="TW_ONEVALUE"/> or <see cref="TW_ARRAY"/>. Available and /// Current Values are set when the container is a TW_ONEVALUE or TW_ARRAY. Available and
/// Current Values are set when the container is a <see cref="TW_ENUMERATION"/> or <see cref="TW_RANGE"/>. /// Current Values are set when the container is a TW_ENUMERATION or TW_RANGE.
/// <param name="capability">The capability.</param> /// <param name="capability">The capability.</param>
/// <returns></returns> /// <returns></returns>
public ReturnCode SetConstraint(ref TW_CAPABILITY capability) public ReturnCode SetConstraint(ref TW_CAPABILITY capability)

View File

@ -14,17 +14,34 @@ namespace NTwain
/// </summary> /// </summary>
public class TwainConfig public class TwainConfig
{ {
internal TwainConfig() { } internal TwainConfig(PlatformID platform, bool is32Bit)
{
Platform = platform;
Is32Bit = is32Bit;
// initial default until twain entry is available
switch (platform)
{
case PlatformID.Win32NT:
_defaultMemoryManager = new WinMemoryManager();
break;
default:
_defaultMemoryManager = new MarshalMemoryManager();
break;
}
}
readonly IMemoryManager _defaultMemoryManager;
/// <summary> /// <summary>
/// Gets whether the app is running in 32bit. /// Gets whether the app is running in 32bit.
/// </summary> /// </summary>
public bool Is32Bit { get; internal set; } public bool Is32Bit { get; private set; }
/// <summary> /// <summary>
/// Gets the platform the app is running on. /// Gets the platform the app is running on.
/// </summary> /// </summary>
public PlatformID Platform { get; internal set; } public PlatformID Platform { get; private set; }
//public bool PreferLegacyDsm { get; internal set; } //public bool PreferLegacyDsm { get; internal set; }
@ -43,11 +60,9 @@ namespace NTwain
{ {
get get
{ {
return _memMgr ?? DefaultMemoryManager; return _memMgr ?? _defaultMemoryManager;
} }
internal set { _memMgr = value; } internal set { _memMgr = value; }
} }
internal IMemoryManager DefaultMemoryManager { get; set; }
} }
} }

View File

@ -18,8 +18,8 @@ namespace NTwain
private string _companyName; private string _companyName;
private Language _lang; private Language _lang;
private DataGroups _dg = DataGroups.Image; private DataGroups _dg = DataGroups.Image;
private bool _32bit; readonly bool _32bit;
private PlatformID _platform; readonly PlatformID _platform;
private Country _country; private Country _country;
/// <summary> /// <summary>
@ -106,17 +106,12 @@ namespace NTwain
/// <returns></returns> /// <returns></returns>
public TwainConfig Build() public TwainConfig Build()
{ {
var config = new TwainConfig var config = new TwainConfig(_platform, _32bit);
{
Platform = _platform,
Is32Bit = _32bit
};
// todo: change id based on platform // todo: change id based on platform
switch (_platform) switch (_platform)
{ {
case PlatformID.Win32NT: case PlatformID.Win32NT:
config.DefaultMemoryManager = new WinMemoryManager(); // initial default
config.App32 = new TW_IDENTITY config.App32 = new TW_IDENTITY
{ {
DataFlags = DataFlags.App2, DataFlags = DataFlags.App2,

View File

@ -43,6 +43,15 @@ namespace NTwain
/// </summary> /// </summary>
internal DGAudio DGAudio => dgAudio ?? (dgAudio = new DGAudio(this)); internal DGAudio DGAudio => dgAudio ?? (dgAudio = new DGAudio(this));
//public CapReader CapReader { get; }
/// <summary>
/// Gets the <see cref="TW_CAPABILITY"/> generator.
/// </summary>
public CapWriter CapWriter { get; }
/// <summary> /// <summary>
/// Occurs when an enabled source has been disabled (back to state 4). /// Occurs when an enabled source has been disabled (back to state 4).
/// </summary> /// </summary>

View File

@ -51,6 +51,8 @@ namespace NTwain
_callback32Delegate = new Callback32(Handle32BitCallback); _callback32Delegate = new Callback32(Handle32BitCallback);
break; break;
} }
//CapReader = new CapReader(this);
CapWriter = new CapWriter(config);
} }
/// <summary> /// <summary>