mirror of
https://github.com/soukoku/ntwain.git
synced 2025-06-28 15:28:06 +08:00
Refactoring xfer logic from twainsession out.
This commit is contained in:
parent
1743b8379b
commit
4b08d3bc29
@ -79,8 +79,8 @@
|
|||||||
<Compile Include="..\NTwain\Internals\ICommittable.cs">
|
<Compile Include="..\NTwain\Internals\ICommittable.cs">
|
||||||
<Link>Internals\ICommittable.cs</Link>
|
<Link>Internals\ICommittable.cs</Link>
|
||||||
</Compile>
|
</Compile>
|
||||||
<Compile Include="..\NTwain\Internals\ITwainStateInternal.cs">
|
<Compile Include="..\NTwain\Internals\ITwainSessionInternal.cs">
|
||||||
<Link>Internals\ITwainStateInternal.cs</Link>
|
<Link>Internals\ITwainSessionInternal.cs</Link>
|
||||||
</Compile>
|
</Compile>
|
||||||
<Compile Include="..\NTwain\Internals\MessageLoop.cs">
|
<Compile Include="..\NTwain\Internals\MessageLoop.cs">
|
||||||
<Link>Internals\MessageLoop.cs</Link>
|
<Link>Internals\MessageLoop.cs</Link>
|
||||||
@ -91,6 +91,9 @@
|
|||||||
<Compile Include="..\NTwain\Internals\TentativeStateCommitable.cs">
|
<Compile Include="..\NTwain\Internals\TentativeStateCommitable.cs">
|
||||||
<Link>Internals\TentativeStateCommitable.cs</Link>
|
<Link>Internals\TentativeStateCommitable.cs</Link>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
<Compile Include="..\NTwain\Internals\TransferLogic.cs">
|
||||||
|
<Link>Internals\TransferLogic.cs</Link>
|
||||||
|
</Compile>
|
||||||
<Compile Include="..\NTwain\Internals\WindowsHook.cs">
|
<Compile Include="..\NTwain\Internals\WindowsHook.cs">
|
||||||
<Link>Internals\WindowsHook.cs</Link>
|
<Link>Internals\WindowsHook.cs</Link>
|
||||||
</Compile>
|
</Compile>
|
||||||
@ -103,6 +106,9 @@
|
|||||||
<Compile Include="..\NTwain\ITwainOperation.cs">
|
<Compile Include="..\NTwain\ITwainOperation.cs">
|
||||||
<Link>ITwainOperation.cs</Link>
|
<Link>ITwainOperation.cs</Link>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
<Compile Include="..\NTwain\ITwainSession.cs">
|
||||||
|
<Link>ITwainSession.cs</Link>
|
||||||
|
</Compile>
|
||||||
<Compile Include="..\NTwain\ITwainState.cs">
|
<Compile Include="..\NTwain\ITwainState.cs">
|
||||||
<Link>ITwainState.cs</Link>
|
<Link>ITwainState.cs</Link>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
using NTwain.Properties;
|
using NTwain.Properties;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Globalization;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
namespace NTwain.Data
|
namespace NTwain.Data
|
||||||
@ -55,7 +56,7 @@ namespace NTwain.Data
|
|||||||
ContainerType = capability.ContainerType,
|
ContainerType = capability.ContainerType,
|
||||||
}.ReadRangeValue(baseAddr);
|
}.ReadRangeValue(baseAddr);
|
||||||
default:
|
default:
|
||||||
throw new ArgumentException(string.Format(Resources.CapHasBadContainer, capability.ContainerType), "capability");
|
throw new ArgumentException(string.Format(CultureInfo.InvariantCulture, Resources.CapHasBadContainer, capability.ContainerType), "capability");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
|
@ -234,7 +234,7 @@ namespace NTwain.Data
|
|||||||
|
|
||||||
object IConvertible.ToType(Type conversionType, IFormatProvider provider)
|
object IConvertible.ToType(Type conversionType, IFormatProvider provider)
|
||||||
{
|
{
|
||||||
return Convert.ChangeType((float)this, conversionType);
|
return Convert.ChangeType((float)this, conversionType, CultureInfo.InvariantCulture);
|
||||||
}
|
}
|
||||||
|
|
||||||
ushort IConvertible.ToUInt16(IFormatProvider provider)
|
ushort IConvertible.ToUInt16(IFormatProvider provider)
|
||||||
@ -632,7 +632,6 @@ namespace NTwain.Data
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="capability">The capability.</param>
|
/// <param name="capability">The capability.</param>
|
||||||
/// <param name="value">The value.</param>
|
/// <param name="value">The value.</param>
|
||||||
[EnvironmentPermissionAttribute(SecurityAction.LinkDemand)]
|
|
||||||
public TWCapability(CapabilityId capability, TWOneValue value)
|
public TWCapability(CapabilityId capability, TWOneValue value)
|
||||||
{
|
{
|
||||||
Capability = capability;
|
Capability = capability;
|
||||||
@ -644,7 +643,6 @@ namespace NTwain.Data
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="capability">The capability.</param>
|
/// <param name="capability">The capability.</param>
|
||||||
/// <param name="value">The value.</param>
|
/// <param name="value">The value.</param>
|
||||||
[EnvironmentPermissionAttribute(SecurityAction.LinkDemand)]
|
|
||||||
public TWCapability(CapabilityId capability, TWEnumeration value)
|
public TWCapability(CapabilityId capability, TWEnumeration value)
|
||||||
{
|
{
|
||||||
Capability = capability;
|
Capability = capability;
|
||||||
@ -656,7 +654,6 @@ namespace NTwain.Data
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="capability">The capability.</param>
|
/// <param name="capability">The capability.</param>
|
||||||
/// <param name="value">The value.</param>
|
/// <param name="value">The value.</param>
|
||||||
[EnvironmentPermissionAttribute(SecurityAction.LinkDemand)]
|
|
||||||
public TWCapability(CapabilityId capability, TWRange value)
|
public TWCapability(CapabilityId capability, TWRange value)
|
||||||
{
|
{
|
||||||
Capability = capability;
|
Capability = capability;
|
||||||
@ -684,14 +681,13 @@ namespace NTwain.Data
|
|||||||
|
|
||||||
#region value functions
|
#region value functions
|
||||||
|
|
||||||
[EnvironmentPermissionAttribute(SecurityAction.LinkDemand)]
|
|
||||||
void SetOneValue(TWOneValue value)
|
void SetOneValue(TWOneValue value)
|
||||||
{
|
{
|
||||||
if (value == null) { throw new ArgumentNullException("value"); }
|
if (value == null) { throw new ArgumentNullException("value"); }
|
||||||
ContainerType = ContainerType.OneValue;
|
ContainerType = ContainerType.OneValue;
|
||||||
|
|
||||||
// since one value can only house UInt32 we will not allow type size > 4
|
// since one value can only house UInt32 we will not allow type size > 4
|
||||||
if (TypeReader.GetItemTypeSize(value.ItemType) > 4) { throw new ArgumentException(string.Format(Resources.BadValueType, "TWOneValue")); }
|
if (TypeReader.GetItemTypeSize(value.ItemType) > 4) { throw new ArgumentException(string.Format(CultureInfo.InvariantCulture, Resources.BadValueType, "TWOneValue")); }
|
||||||
|
|
||||||
_hContainer = Platform.MemoryManager.Allocate((uint)Marshal.SizeOf(value));
|
_hContainer = Platform.MemoryManager.Allocate((uint)Marshal.SizeOf(value));
|
||||||
if (_hContainer != IntPtr.Zero)
|
if (_hContainer != IntPtr.Zero)
|
||||||
@ -700,7 +696,6 @@ namespace NTwain.Data
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[EnvironmentPermissionAttribute(SecurityAction.LinkDemand)]
|
|
||||||
void SetEnumValue(TWEnumeration value)
|
void SetEnumValue(TWEnumeration value)
|
||||||
{
|
{
|
||||||
if (value == null) { throw new ArgumentNullException("value"); }
|
if (value == null) { throw new ArgumentNullException("value"); }
|
||||||
@ -726,14 +721,13 @@ namespace NTwain.Data
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
[EnvironmentPermissionAttribute(SecurityAction.LinkDemand)]
|
|
||||||
void SetRangeValue(TWRange value)
|
void SetRangeValue(TWRange value)
|
||||||
{
|
{
|
||||||
if (value == null) { throw new ArgumentNullException("value"); }
|
if (value == null) { throw new ArgumentNullException("value"); }
|
||||||
ContainerType = ContainerType.Range;
|
ContainerType = ContainerType.Range;
|
||||||
|
|
||||||
// since range value can only house UInt32 we will not allow type size > 4
|
// since range value can only house UInt32 we will not allow type size > 4
|
||||||
if (TypeReader.GetItemTypeSize(value.ItemType) > 4) { throw new ArgumentException(string.Format(Resources.BadValueType, "TWRange")); }
|
if (TypeReader.GetItemTypeSize(value.ItemType) > 4) { throw new ArgumentException(string.Format(CultureInfo.InvariantCulture, Resources.BadValueType, "TWRange")); }
|
||||||
|
|
||||||
_hContainer = Platform.MemoryManager.Allocate((uint)Marshal.SizeOf(value));
|
_hContainer = Platform.MemoryManager.Allocate((uint)Marshal.SizeOf(value));
|
||||||
if (_hContainer != IntPtr.Zero)
|
if (_hContainer != IntPtr.Zero)
|
||||||
@ -752,23 +746,22 @@ namespace NTwain.Data
|
|||||||
/// <param name="offset"></param>
|
/// <param name="offset"></param>
|
||||||
/// <param name="type"></param>
|
/// <param name="type"></param>
|
||||||
/// <param name="value"></param>
|
/// <param name="value"></param>
|
||||||
[EnvironmentPermissionAttribute(SecurityAction.LinkDemand)]
|
|
||||||
void WriteValue(IntPtr baseAddr, ref int offset, ItemType type, object value)
|
void WriteValue(IntPtr baseAddr, ref int offset, ItemType type, object value)
|
||||||
{
|
{
|
||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
case ItemType.Int8:
|
case ItemType.Int8:
|
||||||
case ItemType.UInt8:
|
case ItemType.UInt8:
|
||||||
Marshal.WriteByte(baseAddr, offset, Convert.ToByte(value));// (byte)value);
|
Marshal.WriteByte(baseAddr, offset, Convert.ToByte(value, CultureInfo.InvariantCulture));// (byte)value);
|
||||||
break;
|
break;
|
||||||
case ItemType.Bool:
|
case ItemType.Bool:
|
||||||
case ItemType.Int16:
|
case ItemType.Int16:
|
||||||
case ItemType.UInt16:
|
case ItemType.UInt16:
|
||||||
Marshal.WriteInt16(baseAddr, offset, Convert.ToInt16(value));//(short)value);
|
Marshal.WriteInt16(baseAddr, offset, Convert.ToInt16(value, CultureInfo.InvariantCulture));//(short)value);
|
||||||
break;
|
break;
|
||||||
case ItemType.UInt32:
|
case ItemType.UInt32:
|
||||||
case ItemType.Int32:
|
case ItemType.Int32:
|
||||||
Marshal.WriteInt32(baseAddr, offset, Convert.ToInt32(value));//(int)value);
|
Marshal.WriteInt32(baseAddr, offset, Convert.ToInt32(value, CultureInfo.InvariantCulture));//(int)value);
|
||||||
break;
|
break;
|
||||||
case ItemType.Fix32:
|
case ItemType.Fix32:
|
||||||
TWFix32 f32 = (TWFix32)value;
|
TWFix32 f32 = (TWFix32)value;
|
||||||
@ -2188,15 +2181,24 @@ namespace NTwain.Data
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public partial class TWStatus
|
public partial class TWStatus
|
||||||
{
|
{
|
||||||
|
public TWStatus()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
internal TWStatus(ushort code, ushort data)
|
||||||
|
{
|
||||||
|
_conditionCode = code;
|
||||||
|
_data = data;
|
||||||
|
}
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Condition Code describing the status.
|
/// Condition Code describing the status.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public ConditionCode ConditionCode { get { return (ConditionCode)_conditionCode; } internal set { _conditionCode = (ushort)value; } }
|
public ConditionCode ConditionCode { get { return (ConditionCode)_conditionCode; } }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Valid for TWAIN 2.1 and later. This field contains additional
|
/// Valid for TWAIN 2.1 and later. This field contains additional
|
||||||
/// scanner-specific data. If there is no data, then this value must be zero.
|
/// scanner-specific data. If there is no data, then this value must be zero.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public ushort Data { get { return _data; } internal set { _data = Data; } }
|
public ushort Data { get { return _data; } }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -2210,7 +2212,7 @@ namespace NTwain.Data
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public TWStatus Status
|
public TWStatus Status
|
||||||
{
|
{
|
||||||
get { return new TWStatus { ConditionCode = (ConditionCode)_conditionCode, Data = _data }; }
|
get { return new TWStatus(_conditionCode, _data); }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -1467,7 +1467,7 @@ namespace NTwain.Data
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Corresponds to DG_*.
|
/// Corresponds to DG_*.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Flags]
|
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2217:DoNotMarkEnumsWithFlags"), Flags]
|
||||||
public enum DataGroups : uint
|
public enum DataGroups : uint
|
||||||
{
|
{
|
||||||
None = 0,
|
None = 0,
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Globalization;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
|
||||||
namespace NTwain.Data
|
namespace NTwain.Data
|
||||||
@ -36,7 +37,7 @@ namespace NTwain.Data
|
|||||||
var rawType = Enum.GetUnderlyingType(returnType);
|
var rawType = Enum.GetUnderlyingType(returnType);
|
||||||
if (typeof(ushort).IsAssignableFrom(rawType))
|
if (typeof(ushort).IsAssignableFrom(rawType))
|
||||||
{
|
{
|
||||||
var intVal = Convert.ToUInt32(value);
|
var intVal = Convert.ToUInt32(value, CultureInfo.InvariantCulture);
|
||||||
var enumVal = GetLowerWord(intVal);
|
var enumVal = GetLowerWord(intVal);
|
||||||
if (!Enum.IsDefined(returnType, enumVal))
|
if (!Enum.IsDefined(returnType, enumVal))
|
||||||
{
|
{
|
||||||
@ -52,7 +53,7 @@ namespace NTwain.Data
|
|||||||
else if (typeof(IConvertible).IsAssignableFrom(returnType))
|
else if (typeof(IConvertible).IsAssignableFrom(returnType))
|
||||||
{
|
{
|
||||||
// for regular integers and whatnot
|
// for regular integers and whatnot
|
||||||
return (T)Convert.ChangeType(value, returnType);
|
return (T)Convert.ChangeType(value, returnType, CultureInfo.InvariantCulture);
|
||||||
}
|
}
|
||||||
// return as-is from cap. if caller made a mistake then there should be exceptions
|
// return as-is from cap. if caller made a mistake then there should be exceptions
|
||||||
return (T)value;
|
return (T)value;
|
||||||
@ -78,7 +79,7 @@ namespace NTwain.Data
|
|||||||
{
|
{
|
||||||
return (TWFix32)value;
|
return (TWFix32)value;
|
||||||
}
|
}
|
||||||
return (TWFix32)Convert.ToSingle(value);
|
return (TWFix32)Convert.ToSingle(value, CultureInfo.InvariantCulture);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
22
NTwain/ITwainSession.cs
Normal file
22
NTwain/ITwainSession.cs
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
using NTwain.Data;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace NTwain
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// General interface for a TWAIN session.
|
||||||
|
/// </summary>
|
||||||
|
public interface ITwainSession : ITwainState, ITwainOperation
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the supported caps for the currently open source.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>
|
||||||
|
/// The supported caps.
|
||||||
|
/// </value>
|
||||||
|
IList<CapabilityId> SupportedCaps { get; }
|
||||||
|
}
|
||||||
|
}
|
@ -1,6 +1,8 @@
|
|||||||
using NTwain.Data;
|
using NTwain.Data;
|
||||||
using NTwain.Properties;
|
using NTwain.Properties;
|
||||||
using System;
|
using System;
|
||||||
|
using System.Globalization;
|
||||||
|
using System.IO;
|
||||||
|
|
||||||
namespace NTwain.Internals
|
namespace NTwain.Internals
|
||||||
{
|
{
|
||||||
@ -30,14 +32,70 @@ namespace NTwain.Internals
|
|||||||
/// <param name="dataArgumentType">The triplet data argument type.</param>
|
/// <param name="dataArgumentType">The triplet data argument type.</param>
|
||||||
/// <param name="message">The triplet message.</param>
|
/// <param name="message">The triplet message.</param>
|
||||||
/// <exception cref="TwainStateException"></exception>
|
/// <exception cref="TwainStateException"></exception>
|
||||||
public static void VerifyState(this ITwainStateInternal session, int allowedMinimum, int allowedMaximum, DataGroups group, DataArgumentType dataArgumentType, Message message)
|
public static void VerifyState(this ITwainSessionInternal session, int allowedMinimum, int allowedMaximum, DataGroups group, DataArgumentType dataArgumentType, Message message)
|
||||||
{
|
{
|
||||||
if (session.EnforceState && (session.State < allowedMinimum || session.State > allowedMaximum))
|
if (session.EnforceState && (session.State < allowedMinimum || session.State > allowedMaximum))
|
||||||
{
|
{
|
||||||
throw new TwainStateException(session.State, allowedMinimum, allowedMaximum, group, dataArgumentType, message,
|
throw new TwainStateException(session.State, allowedMinimum, allowedMaximum, group, dataArgumentType, message,
|
||||||
string.Format("TWAIN state {0} does not match required range {1}-{2} for operation {3}-{4}-{5}.",
|
string.Format(CultureInfo.InvariantCulture, "TWAIN state {0} does not match required range {1}-{2} for operation {3}-{4}-{5}.",
|
||||||
session.State, allowedMinimum, allowedMaximum, group, dataArgumentType, message));
|
session.State, allowedMinimum, allowedMaximum, group, dataArgumentType, message));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static string ChangeExtensionByFormat(this TWSetupFileXfer fileInfo, string currentFilePath)
|
||||||
|
{
|
||||||
|
string finalFile = null;
|
||||||
|
switch (fileInfo.Format)
|
||||||
|
{
|
||||||
|
case FileFormat.Bmp:
|
||||||
|
finalFile = Path.ChangeExtension(currentFilePath, ".bmp");
|
||||||
|
break;
|
||||||
|
case FileFormat.Dejavu:
|
||||||
|
finalFile = Path.ChangeExtension(currentFilePath, ".dejavu");
|
||||||
|
break;
|
||||||
|
case FileFormat.Exif:
|
||||||
|
finalFile = Path.ChangeExtension(currentFilePath, ".exit");
|
||||||
|
break;
|
||||||
|
case FileFormat.Fpx:
|
||||||
|
finalFile = Path.ChangeExtension(currentFilePath, ".fpx");
|
||||||
|
break;
|
||||||
|
case FileFormat.Jfif:
|
||||||
|
finalFile = Path.ChangeExtension(currentFilePath, ".jpg");
|
||||||
|
break;
|
||||||
|
case FileFormat.Jp2:
|
||||||
|
finalFile = Path.ChangeExtension(currentFilePath, ".jp2");
|
||||||
|
break;
|
||||||
|
case FileFormat.Jpx:
|
||||||
|
finalFile = Path.ChangeExtension(currentFilePath, ".jpx");
|
||||||
|
break;
|
||||||
|
case FileFormat.Pdf:
|
||||||
|
case FileFormat.PdfA:
|
||||||
|
case FileFormat.PdfA2:
|
||||||
|
finalFile = Path.ChangeExtension(currentFilePath, ".pdf");
|
||||||
|
break;
|
||||||
|
case FileFormat.Pict:
|
||||||
|
finalFile = Path.ChangeExtension(currentFilePath, ".pict");
|
||||||
|
break;
|
||||||
|
case FileFormat.Png:
|
||||||
|
finalFile = Path.ChangeExtension(currentFilePath, ".png");
|
||||||
|
break;
|
||||||
|
case FileFormat.Spiff:
|
||||||
|
finalFile = Path.ChangeExtension(currentFilePath, ".spiff");
|
||||||
|
break;
|
||||||
|
case FileFormat.Tiff:
|
||||||
|
case FileFormat.TiffMulti:
|
||||||
|
finalFile = Path.ChangeExtension(currentFilePath, ".tif");
|
||||||
|
break;
|
||||||
|
case FileFormat.Xbm:
|
||||||
|
finalFile = Path.ChangeExtension(currentFilePath, ".xbm");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
finalFile = Path.ChangeExtension(currentFilePath, ".unknown");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return finalFile;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,12 @@
|
|||||||
using NTwain.Data;
|
using NTwain.Data;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace NTwain.Internals
|
namespace NTwain.Internals
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Internal interface for state management.
|
/// Internal interface for state management.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
interface ITwainStateInternal : ITwainState
|
interface ITwainSessionInternal : ITwainSession
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the app id used for the session.
|
/// Gets the app id used for the session.
|
||||||
@ -37,5 +38,11 @@ namespace NTwain.Internals
|
|||||||
ICommittable GetPendingStateChanger(int newState);
|
ICommittable GetPendingStateChanger(int newState);
|
||||||
|
|
||||||
void ChangeSourceId(TWIdentity sourceId);
|
void ChangeSourceId(TWIdentity sourceId);
|
||||||
|
|
||||||
|
ReturnCode DisableSource();
|
||||||
|
|
||||||
|
void SafeSyncableRaiseEvent(DataTransferredEventArgs e);
|
||||||
|
void SafeSyncableRaiseEvent(TransferErrorEventArgs e);
|
||||||
|
void SafeSyncableRaiseEvent(TransferReadyEventArgs e);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -10,17 +10,17 @@ namespace NTwain.Internals
|
|||||||
#region mem stuff for twain 1.x
|
#region mem stuff for twain 1.x
|
||||||
|
|
||||||
[DllImport("kernel32", SetLastError = true, EntryPoint = "GlobalAlloc")]
|
[DllImport("kernel32", SetLastError = true, EntryPoint = "GlobalAlloc")]
|
||||||
internal static extern IntPtr WinGlobalAlloc(uint uFlags, UIntPtr dwBytes);
|
public static extern IntPtr WinGlobalAlloc(uint uFlags, UIntPtr dwBytes);
|
||||||
|
|
||||||
[DllImport("kernel32", SetLastError = true, EntryPoint = "GlobalFree")]
|
[DllImport("kernel32", SetLastError = true, EntryPoint = "GlobalFree")]
|
||||||
internal static extern IntPtr WinGlobalFree(IntPtr hMem);
|
public static extern IntPtr WinGlobalFree(IntPtr hMem);
|
||||||
|
|
||||||
[DllImport("kernel32", SetLastError = true, EntryPoint = "GlobalLock")]
|
[DllImport("kernel32", SetLastError = true, EntryPoint = "GlobalLock")]
|
||||||
internal static extern IntPtr WinGlobalLock(IntPtr handle);
|
public static extern IntPtr WinGlobalLock(IntPtr handle);
|
||||||
|
|
||||||
[DllImport("kernel32", SetLastError = true, EntryPoint = "GlobalUnlock")]
|
[DllImport("kernel32", SetLastError = true, EntryPoint = "GlobalUnlock")]
|
||||||
[return: MarshalAs(UnmanagedType.Bool)]
|
[return: MarshalAs(UnmanagedType.Bool)]
|
||||||
internal static extern bool WinGlobalUnlock(IntPtr handle);
|
public static extern bool WinGlobalUnlock(IntPtr handle);
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
|
@ -3,10 +3,10 @@
|
|||||||
class TentativeStateCommitable : ICommittable
|
class TentativeStateCommitable : ICommittable
|
||||||
{
|
{
|
||||||
bool _commit;
|
bool _commit;
|
||||||
ITwainStateInternal _session;
|
ITwainSessionInternal _session;
|
||||||
int _origState;
|
int _origState;
|
||||||
int _newState;
|
int _newState;
|
||||||
public TentativeStateCommitable(ITwainStateInternal session, int newState)
|
public TentativeStateCommitable(ITwainSessionInternal session, int newState)
|
||||||
{
|
{
|
||||||
_session = session;
|
_session = session;
|
||||||
_origState = session.State;
|
_origState = session.State;
|
||||||
|
436
NTwain/Internals/TransferLogic.cs
Normal file
436
NTwain/Internals/TransferLogic.cs
Normal file
@ -0,0 +1,436 @@
|
|||||||
|
using NTwain.Data;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace NTwain.Internals
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Contains the actual data transfer logic since TwainSession is getting too large.
|
||||||
|
/// </summary>
|
||||||
|
static class TransferLogic
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Performs the TWAIN transfer routine at state 6.
|
||||||
|
/// </summary>
|
||||||
|
public static void DoTransferRoutine(ITwainSessionInternal session)
|
||||||
|
{
|
||||||
|
var pending = new TWPendingXfers();
|
||||||
|
var rc = ReturnCode.Success;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
#region build and raise xfer ready
|
||||||
|
|
||||||
|
TWAudioInfo audInfo;
|
||||||
|
if (session.DGAudio.AudioInfo.Get(out audInfo) != ReturnCode.Success)
|
||||||
|
{
|
||||||
|
audInfo = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
TWImageInfo imgInfo;
|
||||||
|
if (session.DGImage.ImageInfo.Get(out imgInfo) != ReturnCode.Success)
|
||||||
|
{
|
||||||
|
imgInfo = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ask consumer for xfer details
|
||||||
|
var preXferArgs = new TransferReadyEventArgs
|
||||||
|
{
|
||||||
|
AudioInfo = audInfo,
|
||||||
|
PendingImageInfo = imgInfo,
|
||||||
|
PendingTransferCount = pending.Count,
|
||||||
|
EndOfJob = pending.EndOfJob == 0
|
||||||
|
};
|
||||||
|
|
||||||
|
session.SafeSyncableRaiseEvent(preXferArgs);
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region actually handle xfer
|
||||||
|
|
||||||
|
if (preXferArgs.CancelAll)
|
||||||
|
{
|
||||||
|
rc = session.DGControl.PendingXfers.Reset(pending);
|
||||||
|
}
|
||||||
|
else if (!preXferArgs.CancelCurrent)
|
||||||
|
{
|
||||||
|
DataGroups xferGroup = DataGroups.None;
|
||||||
|
|
||||||
|
if (session.DGControl.XferGroup.Get(ref xferGroup) != ReturnCode.Success)
|
||||||
|
{
|
||||||
|
xferGroup = DataGroups.None;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((xferGroup & DataGroups.Image) == DataGroups.Image)
|
||||||
|
{
|
||||||
|
var mech = session.GetCurrentCap(CapabilityId.ICapXferMech).ConvertToEnum<XferMech>();
|
||||||
|
switch (mech)
|
||||||
|
{
|
||||||
|
case XferMech.Native:
|
||||||
|
DoImageNativeXfer(session);
|
||||||
|
break;
|
||||||
|
case XferMech.Memory:
|
||||||
|
DoImageMemoryXfer(session);
|
||||||
|
break;
|
||||||
|
case XferMech.File:
|
||||||
|
DoImageFileXfer(session);
|
||||||
|
break;
|
||||||
|
case XferMech.MemFile:
|
||||||
|
DoImageMemoryFileXfer(session);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ((xferGroup & DataGroups.Audio) == DataGroups.Audio)
|
||||||
|
{
|
||||||
|
var mech = session.GetCurrentCap(CapabilityId.ACapXferMech).ConvertToEnum<XferMech>();
|
||||||
|
switch (mech)
|
||||||
|
{
|
||||||
|
case XferMech.Native:
|
||||||
|
DoAudioNativeXfer(session);
|
||||||
|
break;
|
||||||
|
case XferMech.File:
|
||||||
|
DoAudioFileXfer(session);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
rc = session.DGControl.PendingXfers.EndXfer(pending);
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
} while (rc == ReturnCode.Success && pending.Count != 0);
|
||||||
|
|
||||||
|
session.ChangeState(5, true);
|
||||||
|
session.DisableSource();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#region audio xfers
|
||||||
|
|
||||||
|
static void DoAudioNativeXfer(ITwainSessionInternal session)
|
||||||
|
{
|
||||||
|
IntPtr dataPtr = IntPtr.Zero;
|
||||||
|
IntPtr lockedPtr = IntPtr.Zero;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var xrc = session.DGAudio.AudioNativeXfer.Get(ref dataPtr);
|
||||||
|
if (xrc == ReturnCode.XferDone)
|
||||||
|
{
|
||||||
|
session.ChangeState(7, true);
|
||||||
|
if (dataPtr != IntPtr.Zero)
|
||||||
|
{
|
||||||
|
lockedPtr = Platform.MemoryManager.Lock(dataPtr);
|
||||||
|
}
|
||||||
|
|
||||||
|
session.SafeSyncableRaiseEvent(new DataTransferredEventArgs { NativeData = lockedPtr });
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
session.SafeSyncableRaiseEvent(new TransferErrorEventArgs { ReturnCode = xrc, SourceStatus = session.GetSourceStatus() });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
session.SafeSyncableRaiseEvent(new TransferErrorEventArgs { Exception = ex });
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
session.ChangeState(6, true);
|
||||||
|
// data here is allocated by source so needs to use shared mem calls
|
||||||
|
if (lockedPtr != IntPtr.Zero)
|
||||||
|
{
|
||||||
|
Platform.MemoryManager.Unlock(lockedPtr);
|
||||||
|
lockedPtr = IntPtr.Zero;
|
||||||
|
}
|
||||||
|
if (dataPtr != IntPtr.Zero)
|
||||||
|
{
|
||||||
|
Platform.MemoryManager.Free(dataPtr);
|
||||||
|
dataPtr = IntPtr.Zero;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void DoAudioFileXfer(ITwainSessionInternal session)
|
||||||
|
{
|
||||||
|
string filePath = null;
|
||||||
|
TWSetupFileXfer setupInfo;
|
||||||
|
if (session.DGControl.SetupFileXfer.Get(out setupInfo) == ReturnCode.Success)
|
||||||
|
{
|
||||||
|
filePath = setupInfo.FileName;
|
||||||
|
}
|
||||||
|
|
||||||
|
var xrc = session.DGAudio.AudioFileXfer.Get();
|
||||||
|
if (xrc == ReturnCode.XferDone)
|
||||||
|
{
|
||||||
|
session.SafeSyncableRaiseEvent(new DataTransferredEventArgs { FileDataPath = filePath });
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
session.SafeSyncableRaiseEvent(new TransferErrorEventArgs { ReturnCode = xrc, SourceStatus = session.GetSourceStatus() });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region image xfers
|
||||||
|
|
||||||
|
static void DoImageNativeXfer(ITwainSessionInternal session)
|
||||||
|
{
|
||||||
|
IntPtr dataPtr = IntPtr.Zero;
|
||||||
|
IntPtr lockedPtr = IntPtr.Zero;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var xrc = session.DGImage.ImageNativeXfer.Get(ref dataPtr);
|
||||||
|
if (xrc == ReturnCode.XferDone)
|
||||||
|
{
|
||||||
|
session.ChangeState(7, true);
|
||||||
|
if (dataPtr != IntPtr.Zero)
|
||||||
|
{
|
||||||
|
lockedPtr = Platform.MemoryManager.Lock(dataPtr);
|
||||||
|
}
|
||||||
|
DoImageXferredEventRoutine(session, lockedPtr, null, null);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
session.SafeSyncableRaiseEvent(new TransferErrorEventArgs { ReturnCode = xrc, SourceStatus = session.GetSourceStatus() });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
session.SafeSyncableRaiseEvent(new TransferErrorEventArgs { Exception = ex });
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
session.ChangeState(6, true);
|
||||||
|
// data here is allocated by source so needs to use shared mem calls
|
||||||
|
if (lockedPtr != IntPtr.Zero)
|
||||||
|
{
|
||||||
|
Platform.MemoryManager.Unlock(lockedPtr);
|
||||||
|
lockedPtr = IntPtr.Zero;
|
||||||
|
}
|
||||||
|
if (dataPtr != IntPtr.Zero)
|
||||||
|
{
|
||||||
|
Platform.MemoryManager.Free(dataPtr);
|
||||||
|
dataPtr = IntPtr.Zero;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void DoImageFileXfer(ITwainSessionInternal session)
|
||||||
|
{
|
||||||
|
string filePath = null;
|
||||||
|
TWSetupFileXfer setupInfo;
|
||||||
|
if (session.DGControl.SetupFileXfer.Get(out setupInfo) == ReturnCode.Success)
|
||||||
|
{
|
||||||
|
filePath = setupInfo.FileName;
|
||||||
|
}
|
||||||
|
|
||||||
|
var xrc = session.DGImage.ImageFileXfer.Get();
|
||||||
|
if (xrc == ReturnCode.XferDone)
|
||||||
|
{
|
||||||
|
DoImageXferredEventRoutine(session, IntPtr.Zero, null, filePath);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
session.SafeSyncableRaiseEvent(new TransferErrorEventArgs { ReturnCode = xrc, SourceStatus = session.GetSourceStatus() });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void DoImageMemoryXfer(ITwainSessionInternal session)
|
||||||
|
{
|
||||||
|
TWSetupMemXfer memInfo;
|
||||||
|
if (session.DGControl.SetupMemXfer.Get(out memInfo) == ReturnCode.Success)
|
||||||
|
{
|
||||||
|
TWImageMemXfer xferInfo = new TWImageMemXfer();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// how to tell if going to xfer in strip vs tile?
|
||||||
|
// if tile don't allocate memory in app?
|
||||||
|
|
||||||
|
xferInfo.Memory = new TWMemory
|
||||||
|
{
|
||||||
|
Flags = MemoryFlags.AppOwns | MemoryFlags.Pointer,
|
||||||
|
Length = memInfo.Preferred,
|
||||||
|
TheMem = Platform.MemoryManager.Allocate(memInfo.Preferred)
|
||||||
|
};
|
||||||
|
|
||||||
|
// do the unthinkable and keep all xferred batches in memory,
|
||||||
|
// possibly defeating the purpose of mem xfer
|
||||||
|
// unless compression is used.
|
||||||
|
// todo: use array instead of memory stream?
|
||||||
|
using (MemoryStream xferredData = new MemoryStream())
|
||||||
|
{
|
||||||
|
var xrc = ReturnCode.Success;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
xrc = session.DGImage.ImageMemFileXfer.Get(xferInfo);
|
||||||
|
|
||||||
|
if (xrc == ReturnCode.Success ||
|
||||||
|
xrc == ReturnCode.XferDone)
|
||||||
|
{
|
||||||
|
session.ChangeState(7, true);
|
||||||
|
// optimize and allocate buffer only once instead of inside the loop?
|
||||||
|
byte[] buffer = new byte[(int)xferInfo.BytesWritten];
|
||||||
|
|
||||||
|
IntPtr lockPtr = IntPtr.Zero;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
lockPtr = Platform.MemoryManager.Lock(xferInfo.Memory.TheMem);
|
||||||
|
Marshal.Copy(lockPtr, buffer, 0, buffer.Length);
|
||||||
|
xferredData.Write(buffer, 0, buffer.Length);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
if (lockPtr != IntPtr.Zero)
|
||||||
|
{
|
||||||
|
Platform.MemoryManager.Unlock(lockPtr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} while (xrc == ReturnCode.Success);
|
||||||
|
|
||||||
|
if (xrc == ReturnCode.XferDone)
|
||||||
|
{
|
||||||
|
DoImageXferredEventRoutine(session, IntPtr.Zero, xferredData.ToArray(), null);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
session.SafeSyncableRaiseEvent(new TransferErrorEventArgs { ReturnCode = xrc, SourceStatus = session.GetSourceStatus() });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
session.SafeSyncableRaiseEvent(new TransferErrorEventArgs { Exception = ex });
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
session.ChangeState(6, true);
|
||||||
|
if (xferInfo.Memory.TheMem != IntPtr.Zero)
|
||||||
|
{
|
||||||
|
Platform.MemoryManager.Free(xferInfo.Memory.TheMem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void DoImageMemoryFileXfer(ITwainSessionInternal session)
|
||||||
|
{
|
||||||
|
// since it's memory-file xfer need info from both (maybe)
|
||||||
|
TWSetupMemXfer memInfo;
|
||||||
|
TWSetupFileXfer fileInfo;
|
||||||
|
if (session.DGControl.SetupMemXfer.Get(out memInfo) == ReturnCode.Success &&
|
||||||
|
session.DGControl.SetupFileXfer.Get(out fileInfo) == ReturnCode.Success)
|
||||||
|
{
|
||||||
|
TWImageMemXfer xferInfo = new TWImageMemXfer();
|
||||||
|
var tempFile = Path.GetTempFileName();
|
||||||
|
string finalFile = null;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// no strip or tile here, just chunks
|
||||||
|
xferInfo.Memory = new TWMemory
|
||||||
|
{
|
||||||
|
Flags = MemoryFlags.AppOwns | MemoryFlags.Pointer,
|
||||||
|
Length = memInfo.Preferred,
|
||||||
|
TheMem = Platform.MemoryManager.Allocate(memInfo.Preferred)
|
||||||
|
};
|
||||||
|
|
||||||
|
var xrc = ReturnCode.Success;
|
||||||
|
using (var outStream = File.OpenWrite(tempFile))
|
||||||
|
{
|
||||||
|
do
|
||||||
|
{
|
||||||
|
xrc = session.DGImage.ImageMemFileXfer.Get(xferInfo);
|
||||||
|
|
||||||
|
if (xrc == ReturnCode.Success ||
|
||||||
|
xrc == ReturnCode.XferDone)
|
||||||
|
{
|
||||||
|
session.ChangeState(7, true);
|
||||||
|
byte[] buffer = new byte[(int)xferInfo.BytesWritten];
|
||||||
|
|
||||||
|
IntPtr lockPtr = IntPtr.Zero;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
lockPtr = Platform.MemoryManager.Lock(xferInfo.Memory.TheMem);
|
||||||
|
Marshal.Copy(lockPtr, buffer, 0, buffer.Length);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
if (lockPtr != IntPtr.Zero)
|
||||||
|
{
|
||||||
|
Platform.MemoryManager.Unlock(lockPtr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
outStream.Write(buffer, 0, buffer.Length);
|
||||||
|
}
|
||||||
|
} while (xrc == ReturnCode.Success);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (xrc == ReturnCode.XferDone)
|
||||||
|
{
|
||||||
|
finalFile = fileInfo.ChangeExtensionByFormat(tempFile);
|
||||||
|
File.Move(tempFile, finalFile);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
session.SafeSyncableRaiseEvent(new TransferErrorEventArgs { ReturnCode = xrc, SourceStatus = session.GetSourceStatus() });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
session.SafeSyncableRaiseEvent(new TransferErrorEventArgs { Exception = ex });
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
session.ChangeState(6, true);
|
||||||
|
if (xferInfo.Memory.TheMem != IntPtr.Zero)
|
||||||
|
{
|
||||||
|
Platform.MemoryManager.Free(xferInfo.Memory.TheMem);
|
||||||
|
}
|
||||||
|
if (File.Exists(tempFile))
|
||||||
|
{
|
||||||
|
File.Delete(tempFile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (File.Exists(finalFile))
|
||||||
|
{
|
||||||
|
DoImageXferredEventRoutine(session, IntPtr.Zero, null, finalFile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void DoImageXferredEventRoutine(ITwainSessionInternal session, IntPtr dataPtr, byte[] dataArray, string filePath)
|
||||||
|
{
|
||||||
|
TWImageInfo imgInfo;
|
||||||
|
TWExtImageInfo extInfo = null;
|
||||||
|
if (session.SupportedCaps.Contains(CapabilityId.ICapExtImageInfo))
|
||||||
|
{
|
||||||
|
if (session.DGImage.ExtImageInfo.Get(out extInfo) != ReturnCode.Success)
|
||||||
|
{
|
||||||
|
extInfo = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (session.DGImage.ImageInfo.Get(out imgInfo) != ReturnCode.Success)
|
||||||
|
{
|
||||||
|
imgInfo = null;
|
||||||
|
}
|
||||||
|
session.SafeSyncableRaiseEvent(new DataTransferredEventArgs
|
||||||
|
{
|
||||||
|
NativeData = dataPtr,
|
||||||
|
MemData = dataArray,
|
||||||
|
FileDataPath = filePath,
|
||||||
|
ImageInfo = imgInfo,
|
||||||
|
ExImageInfo = extInfo
|
||||||
|
});
|
||||||
|
if (extInfo != null) { extInfo.Dispose(); }
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
@ -1,6 +1,7 @@
|
|||||||
using NTwain.Data;
|
using NTwain.Data;
|
||||||
using NTwain.Internals;
|
using NTwain.Internals;
|
||||||
using System;
|
using System;
|
||||||
|
using System.ComponentModel;
|
||||||
|
|
||||||
namespace NTwain
|
namespace NTwain
|
||||||
{
|
{
|
||||||
@ -16,7 +17,7 @@ namespace NTwain
|
|||||||
|
|
||||||
if (retVal == IntPtr.Zero)
|
if (retVal == IntPtr.Zero)
|
||||||
{
|
{
|
||||||
throw new OutOfMemoryException();
|
throw new Win32Exception();
|
||||||
}
|
}
|
||||||
return retVal;
|
return retVal;
|
||||||
}
|
}
|
||||||
|
@ -27,7 +27,7 @@
|
|||||||
<DocumentationFile>
|
<DocumentationFile>
|
||||||
</DocumentationFile>
|
</DocumentationFile>
|
||||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||||
<DebugType>pdbonly</DebugType>
|
<DebugType>pdbonly</DebugType>
|
||||||
@ -60,10 +60,12 @@
|
|||||||
<Compile Include="DataTransferredEventArgs.cs" />
|
<Compile Include="DataTransferredEventArgs.cs" />
|
||||||
<Compile Include="IMemoryManager.cs" />
|
<Compile Include="IMemoryManager.cs" />
|
||||||
<Compile Include="Internals\ICommittable.cs" />
|
<Compile Include="Internals\ICommittable.cs" />
|
||||||
<Compile Include="Internals\ITwainStateInternal.cs" />
|
<Compile Include="Internals\ITwainSessionInternal.cs" />
|
||||||
|
<Compile Include="Internals\TransferLogic.cs" />
|
||||||
<Compile Include="Internals\WindowsHook.cs" />
|
<Compile Include="Internals\WindowsHook.cs" />
|
||||||
<Compile Include="Internals\WrappedManualResetEvent.cs" />
|
<Compile Include="Internals\WrappedManualResetEvent.cs" />
|
||||||
<Compile Include="ITwainOperation.cs" />
|
<Compile Include="ITwainOperation.cs" />
|
||||||
|
<Compile Include="ITwainSession.cs" />
|
||||||
<Compile Include="ITwainState.cs" />
|
<Compile Include="ITwainState.cs" />
|
||||||
<Compile Include="Internals\WinMemoryManager.cs" />
|
<Compile Include="Internals\WinMemoryManager.cs" />
|
||||||
<Compile Include="Internals\MessageLoop.cs" />
|
<Compile Include="Internals\MessageLoop.cs" />
|
||||||
|
@ -9,7 +9,7 @@ namespace NTwain.Triplets
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
sealed class AudioFileXfer : OpBase
|
sealed class AudioFileXfer : OpBase
|
||||||
{
|
{
|
||||||
internal AudioFileXfer(ITwainStateInternal session) : base(session) { }
|
internal AudioFileXfer(ITwainSessionInternal session) : base(session) { }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// This operation is used to initiate the transfer of audio from the Source to the application via the
|
/// This operation is used to initiate the transfer of audio from the Source to the application via the
|
||||||
/// disk-file transfer mechanism. It causes the transfer to begin.
|
/// disk-file transfer mechanism. It causes the transfer to begin.
|
||||||
|
@ -8,7 +8,7 @@ namespace NTwain.Triplets
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed class AudioInfo : OpBase
|
public sealed class AudioInfo : OpBase
|
||||||
{
|
{
|
||||||
internal AudioInfo(ITwainStateInternal session) : base(session) { }
|
internal AudioInfo(ITwainSessionInternal session) : base(session) { }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Used to get the information of the current audio data ready to transfer.
|
/// Used to get the information of the current audio data ready to transfer.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -9,7 +9,7 @@ namespace NTwain.Triplets
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
sealed class AudioNativeXfer : OpBase
|
sealed class AudioNativeXfer : OpBase
|
||||||
{
|
{
|
||||||
internal AudioNativeXfer(ITwainStateInternal session) : base(session) { }
|
internal AudioNativeXfer(ITwainSessionInternal session) : base(session) { }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Causes the transfer of an audio data from the Source to the application, via the Native
|
/// Causes the transfer of an audio data from the Source to the application, via the Native
|
||||||
/// transfer mechanism, to begin. The resulting data is stored in main memory in a single block.
|
/// transfer mechanism, to begin. The resulting data is stored in main memory in a single block.
|
||||||
|
@ -8,8 +8,8 @@ namespace NTwain.Triplets
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed class DGAudio
|
public sealed class DGAudio
|
||||||
{
|
{
|
||||||
ITwainStateInternal _session;
|
ITwainSessionInternal _session;
|
||||||
internal DGAudio(ITwainStateInternal session)
|
internal DGAudio(ITwainSessionInternal session)
|
||||||
{
|
{
|
||||||
if (session == null) { throw new ArgumentNullException("session"); }
|
if (session == null) { throw new ArgumentNullException("session"); }
|
||||||
_session = session;
|
_session = session;
|
||||||
|
@ -5,7 +5,7 @@ namespace NTwain.Triplets
|
|||||||
{
|
{
|
||||||
sealed class Callback : OpBase
|
sealed class Callback : OpBase
|
||||||
{
|
{
|
||||||
internal Callback(ITwainStateInternal session) : base(session) { }
|
internal Callback(ITwainSessionInternal session) : base(session) { }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// This triplet is sent to the DSM by the Application to register the application’s entry point with
|
/// This triplet is sent to the DSM by the Application to register the application’s entry point with
|
||||||
/// the DSM, so that the DSM can use callbacks to inform the application of events generated by the
|
/// the DSM, so that the DSM can use callbacks to inform the application of events generated by the
|
||||||
|
@ -5,7 +5,7 @@ namespace NTwain.Triplets
|
|||||||
{
|
{
|
||||||
sealed class Callback2 : OpBase
|
sealed class Callback2 : OpBase
|
||||||
{
|
{
|
||||||
internal Callback2(ITwainStateInternal session) : base(session) { }
|
internal Callback2(ITwainSessionInternal session) : base(session) { }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// This triplet is sent to the DSM by the Application to register the application’s entry point with
|
/// This triplet is sent to the DSM by the Application to register the application’s entry point with
|
||||||
/// the DSM, so that the DSM can use callbacks to inform the application of events generated by the
|
/// the DSM, so that the DSM can use callbacks to inform the application of events generated by the
|
||||||
|
@ -8,7 +8,7 @@ namespace NTwain.Triplets
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed class Capability : OpBase
|
public sealed class Capability : OpBase
|
||||||
{
|
{
|
||||||
internal Capability(ITwainStateInternal session) : base(session) { }
|
internal Capability(ITwainSessionInternal session) : base(session) { }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns the Source’s Current, Default and Available Values for a specified capability.
|
/// Returns the Source’s Current, Default and Available Values for a specified capability.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -8,7 +8,7 @@ namespace NTwain.Triplets
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed class CustomDSData : OpBase
|
public sealed class CustomDSData : OpBase
|
||||||
{
|
{
|
||||||
internal CustomDSData(ITwainStateInternal session) : base(session) { }
|
internal CustomDSData(ITwainSessionInternal session) : base(session) { }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// This operation is used by the application to query the data source for its current settings, e.g.
|
/// This operation is used by the application to query the data source for its current settings, e.g.
|
||||||
/// DPI, paper size, color format. The actual format of the data is data source dependent and not
|
/// DPI, paper size, color format. The actual format of the data is data source dependent and not
|
||||||
|
@ -8,7 +8,7 @@ namespace NTwain.Triplets
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed class DeviceEvent : OpBase
|
public sealed class DeviceEvent : OpBase
|
||||||
{
|
{
|
||||||
internal DeviceEvent(ITwainStateInternal session) : base(session) { }
|
internal DeviceEvent(ITwainSessionInternal session) : base(session) { }
|
||||||
public ReturnCode Get(out TWDeviceEvent sourceDeviceEvent)
|
public ReturnCode Get(out TWDeviceEvent sourceDeviceEvent)
|
||||||
{
|
{
|
||||||
Session.VerifyState(4, 7, DataGroups.Control, DataArgumentType.DeviceEvent, Message.Get);
|
Session.VerifyState(4, 7, DataGroups.Control, DataArgumentType.DeviceEvent, Message.Get);
|
||||||
|
@ -8,7 +8,7 @@ namespace NTwain.Triplets
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
sealed class EntryPoint : OpBase
|
sealed class EntryPoint : OpBase
|
||||||
{
|
{
|
||||||
internal EntryPoint(ITwainStateInternal session) : base(session) { }
|
internal EntryPoint(ITwainSessionInternal session) : base(session) { }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the function entry points for twain 2.0 or higher.
|
/// Gets the function entry points for twain 2.0 or higher.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -5,7 +5,7 @@ namespace NTwain.Triplets
|
|||||||
{
|
{
|
||||||
sealed class Event : OpBase
|
sealed class Event : OpBase
|
||||||
{
|
{
|
||||||
internal Event(ITwainStateInternal session) : base(session) { }
|
internal Event(ITwainSessionInternal session) : base(session) { }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// This operation supports the distribution of events from the application to Sources so that the
|
/// This operation supports the distribution of events from the application to Sources so that the
|
||||||
|
@ -8,7 +8,7 @@ namespace NTwain.Triplets
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed class FileSystem : OpBase
|
public sealed class FileSystem : OpBase
|
||||||
{
|
{
|
||||||
internal FileSystem(ITwainStateInternal session) : base(session) { }
|
internal FileSystem(ITwainSessionInternal session) : base(session) { }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// This operation selects the destination directory within the Source (camera, storage, etc), where
|
/// This operation selects the destination directory within the Source (camera, storage, etc), where
|
||||||
/// images captured using CapAutomaticCapture will be stored. This command only selects
|
/// images captured using CapAutomaticCapture will be stored. This command only selects
|
||||||
|
@ -8,7 +8,7 @@ namespace NTwain.Triplets
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed class Identity : OpBase
|
public sealed class Identity : OpBase
|
||||||
{
|
{
|
||||||
internal Identity(ITwainStateInternal session) : base(session) { }
|
internal Identity(ITwainSessionInternal session) : base(session) { }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// When an application is finished with a Source, it must formally close the session between them
|
/// When an application is finished with a Source, it must formally close the session between them
|
||||||
/// using this operation. This is necessary in case the Source only supports connection with a single
|
/// using this operation. This is necessary in case the Source only supports connection with a single
|
||||||
|
@ -9,7 +9,7 @@ namespace NTwain.Triplets
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
sealed class Parent : OpBase
|
sealed class Parent : OpBase
|
||||||
{
|
{
|
||||||
internal Parent(ITwainStateInternal session) : base(session) { }
|
internal Parent(ITwainSessionInternal session) : base(session) { }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// When the application has closed all the Sources it had previously opened, and is finished with
|
/// When the application has closed all the Sources it had previously opened, and is finished with
|
||||||
|
@ -8,7 +8,7 @@ namespace NTwain.Triplets
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed class PassThru : OpBase
|
public sealed class PassThru : OpBase
|
||||||
{
|
{
|
||||||
internal PassThru(ITwainStateInternal session) : base(session) { }
|
internal PassThru(ITwainSessionInternal session) : base(session) { }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// PASSTHRU is intended for the use of Source writers writing diagnostic applications. It allows
|
/// PASSTHRU is intended for the use of Source writers writing diagnostic applications. It allows
|
||||||
/// raw communication with the currently selected device in the Source.
|
/// raw communication with the currently selected device in the Source.
|
||||||
|
@ -8,7 +8,7 @@ namespace NTwain.Triplets
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
sealed class PendingXfers : OpBase
|
sealed class PendingXfers : OpBase
|
||||||
{
|
{
|
||||||
internal PendingXfers(ITwainStateInternal session) : base(session) { }
|
internal PendingXfers(ITwainSessionInternal session) : base(session) { }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// This triplet is used to cancel or terminate a transfer. Issued in state 6, this triplet cancels the next
|
/// This triplet is used to cancel or terminate a transfer. Issued in state 6, this triplet cancels the next
|
||||||
/// pending transfer, discards the transfer data, and decrements the pending transfers count. In
|
/// pending transfer, discards the transfer data, and decrements the pending transfers count. In
|
||||||
|
@ -8,7 +8,7 @@ namespace NTwain.Triplets
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed class SetupFileXfer : OpBase
|
public sealed class SetupFileXfer : OpBase
|
||||||
{
|
{
|
||||||
internal SetupFileXfer(ITwainStateInternal session) : base(session) { }
|
internal SetupFileXfer(ITwainSessionInternal session) : base(session) { }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns information about the file into which the Source has or will put the acquired image
|
/// Returns information about the file into which the Source has or will put the acquired image
|
||||||
/// or audio data.
|
/// or audio data.
|
||||||
|
@ -8,7 +8,7 @@ namespace NTwain.Triplets
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed class SetupMemXfer : OpBase
|
public sealed class SetupMemXfer : OpBase
|
||||||
{
|
{
|
||||||
internal SetupMemXfer(ITwainStateInternal session) : base(session) { }
|
internal SetupMemXfer(ITwainSessionInternal session) : base(session) { }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns the Source’s preferred, minimum, and maximum allocation sizes for transfer memory
|
/// Returns the Source’s preferred, minimum, and maximum allocation sizes for transfer memory
|
||||||
/// buffers.
|
/// buffers.
|
||||||
|
@ -8,7 +8,7 @@ namespace NTwain.Triplets
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed class Status : OpBase
|
public sealed class Status : OpBase
|
||||||
{
|
{
|
||||||
internal Status(ITwainStateInternal session) : base(session) { }
|
internal Status(ITwainSessionInternal session) : base(session) { }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns the current Condition Code for the Source Manager.
|
/// Returns the current Condition Code for the Source Manager.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -8,7 +8,7 @@ namespace NTwain.Triplets
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed class StatusUtf8 : OpBase
|
public sealed class StatusUtf8 : OpBase
|
||||||
{
|
{
|
||||||
internal StatusUtf8(ITwainStateInternal session) : base(session) { }
|
internal StatusUtf8(ITwainSessionInternal session) : base(session) { }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Translate the contents of a TW_STATUS structure received from a Source into a localized UTF-8
|
/// Translate the contents of a TW_STATUS structure received from a Source into a localized UTF-8
|
||||||
/// encoded string.
|
/// encoded string.
|
||||||
|
@ -8,7 +8,7 @@ namespace NTwain.Triplets
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
sealed class UserInterface : OpBase
|
sealed class UserInterface : OpBase
|
||||||
{
|
{
|
||||||
internal UserInterface(ITwainStateInternal session) : base(session) { }
|
internal UserInterface(ITwainSessionInternal session) : base(session) { }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// This operation causes the Source’s user interface, if displayed during the
|
/// This operation causes the Source’s user interface, if displayed during the
|
||||||
/// EnableDS operation, to be lowered. The Source is returned to
|
/// EnableDS operation, to be lowered. The Source is returned to
|
||||||
|
@ -8,7 +8,7 @@ namespace NTwain.Triplets
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed class XferGroup : OpBase
|
public sealed class XferGroup : OpBase
|
||||||
{
|
{
|
||||||
internal XferGroup(ITwainStateInternal session) : base(session) { }
|
internal XferGroup(ITwainSessionInternal session) : base(session) { }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns the Data Group (the type of data) for the upcoming transfer. The Source is required to
|
/// Returns the Data Group (the type of data) for the upcoming transfer. The Source is required to
|
||||||
|
@ -8,8 +8,8 @@ namespace NTwain.Triplets
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed class DGControl
|
public sealed class DGControl
|
||||||
{
|
{
|
||||||
ITwainStateInternal _session;
|
ITwainSessionInternal _session;
|
||||||
internal DGControl(ITwainStateInternal session)
|
internal DGControl(ITwainSessionInternal session)
|
||||||
{
|
{
|
||||||
if (session == null) { throw new ArgumentNullException("session"); }
|
if (session == null) { throw new ArgumentNullException("session"); }
|
||||||
_session = session;
|
_session = session;
|
||||||
|
@ -8,7 +8,7 @@ namespace NTwain.Triplets
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed class CieColor : OpBase
|
public sealed class CieColor : OpBase
|
||||||
{
|
{
|
||||||
internal CieColor(ITwainStateInternal session) : base(session) { }
|
internal CieColor(ITwainSessionInternal session) : base(session) { }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// This operation causes the Source to report the currently active parameters to be used in
|
/// This operation causes the Source to report the currently active parameters to be used in
|
||||||
|
@ -8,7 +8,7 @@ namespace NTwain.Triplets
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed class ExtImageInfo : OpBase
|
public sealed class ExtImageInfo : OpBase
|
||||||
{
|
{
|
||||||
internal ExtImageInfo(ITwainStateInternal session) : base(session) { }
|
internal ExtImageInfo(ITwainSessionInternal session) : base(session) { }
|
||||||
|
|
||||||
public ReturnCode Get(out TWExtImageInfo info)
|
public ReturnCode Get(out TWExtImageInfo info)
|
||||||
{
|
{
|
||||||
|
@ -8,7 +8,7 @@ namespace NTwain.Triplets
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed class Filter : OpBase
|
public sealed class Filter : OpBase
|
||||||
{
|
{
|
||||||
internal Filter(ITwainStateInternal session) : base(session) { }
|
internal Filter(ITwainSessionInternal session) : base(session) { }
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -8,7 +8,7 @@ namespace NTwain.Triplets
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed class GrayResponse : OpBase
|
public sealed class GrayResponse : OpBase
|
||||||
{
|
{
|
||||||
internal GrayResponse(ITwainStateInternal session) : base(session) { }
|
internal GrayResponse(ITwainSessionInternal session) : base(session) { }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The Reset operation causes the Source to use its "identity response curve." The identity
|
/// The Reset operation causes the Source to use its "identity response curve." The identity
|
||||||
|
@ -8,7 +8,7 @@ namespace NTwain.Triplets
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed class IccProfile : OpBase
|
public sealed class IccProfile : OpBase
|
||||||
{
|
{
|
||||||
internal IccProfile(ITwainStateInternal session) : base(session) { }
|
internal IccProfile(ITwainSessionInternal session) : base(session) { }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// This operation provides the application with the ICC profile associated with the image which is
|
/// This operation provides the application with the ICC profile associated with the image which is
|
||||||
|
@ -9,7 +9,7 @@ namespace NTwain.Triplets
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
sealed class ImageFileXfer : OpBase
|
sealed class ImageFileXfer : OpBase
|
||||||
{
|
{
|
||||||
internal ImageFileXfer(ITwainStateInternal session) : base(session) { }
|
internal ImageFileXfer(ITwainSessionInternal session) : base(session) { }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// This operation is used to initiate the transfer of an image from the Source to the application via
|
/// This operation is used to initiate the transfer of an image from the Source to the application via
|
||||||
|
@ -8,7 +8,7 @@ namespace NTwain.Triplets
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed class ImageInfo : OpBase
|
public sealed class ImageInfo : OpBase
|
||||||
{
|
{
|
||||||
internal ImageInfo(ITwainStateInternal session) : base(session) { }
|
internal ImageInfo(ITwainSessionInternal session) : base(session) { }
|
||||||
|
|
||||||
public ReturnCode Get(out TWImageInfo info)
|
public ReturnCode Get(out TWImageInfo info)
|
||||||
{
|
{
|
||||||
|
@ -8,7 +8,7 @@ namespace NTwain.Triplets
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed class ImageLayout : OpBase
|
public sealed class ImageLayout : OpBase
|
||||||
{
|
{
|
||||||
internal ImageLayout(ITwainStateInternal session) : base(session) { }
|
internal ImageLayout(ITwainSessionInternal session) : base(session) { }
|
||||||
|
|
||||||
public ReturnCode Get(out TWImageLayout layout)
|
public ReturnCode Get(out TWImageLayout layout)
|
||||||
{
|
{
|
||||||
|
@ -5,7 +5,7 @@ namespace NTwain.Triplets
|
|||||||
{
|
{
|
||||||
sealed class ImageMemFileXfer : OpBase
|
sealed class ImageMemFileXfer : OpBase
|
||||||
{
|
{
|
||||||
internal ImageMemFileXfer(ITwainStateInternal session) : base(session) { }
|
internal ImageMemFileXfer(ITwainSessionInternal session) : base(session) { }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// This operation is used to initiate the transfer of an image from the Source to the application via
|
/// This operation is used to initiate the transfer of an image from the Source to the application via
|
||||||
|
@ -5,7 +5,7 @@ namespace NTwain.Triplets
|
|||||||
{
|
{
|
||||||
sealed class ImageMemXfer : OpBase
|
sealed class ImageMemXfer : OpBase
|
||||||
{
|
{
|
||||||
internal ImageMemXfer(ITwainStateInternal session) : base(session) { }
|
internal ImageMemXfer(ITwainSessionInternal session) : base(session) { }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// This operation is used to initiate the transfer of an image from the Source to the application via
|
/// This operation is used to initiate the transfer of an image from the Source to the application via
|
||||||
|
@ -6,7 +6,7 @@ namespace NTwain.Triplets
|
|||||||
{
|
{
|
||||||
sealed class ImageNativeXfer : OpBase
|
sealed class ImageNativeXfer : OpBase
|
||||||
{
|
{
|
||||||
internal ImageNativeXfer(ITwainStateInternal session) : base(session) { }
|
internal ImageNativeXfer(ITwainSessionInternal session) : base(session) { }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Causes the transfer of an image’s data from the Source to the application, via the Native transfer
|
/// Causes the transfer of an image’s data from the Source to the application, via the Native transfer
|
||||||
|
@ -8,7 +8,7 @@ namespace NTwain.Triplets
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed class JpegCompression : OpBase
|
public sealed class JpegCompression : OpBase
|
||||||
{
|
{
|
||||||
internal JpegCompression(ITwainStateInternal session) : base(session) { }
|
internal JpegCompression(ITwainSessionInternal session) : base(session) { }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Causes the Source to return the parameters that will be used during the compression of data
|
/// Causes the Source to return the parameters that will be used during the compression of data
|
||||||
|
@ -8,7 +8,7 @@ namespace NTwain.Triplets
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed class Palette8 : OpBase
|
public sealed class Palette8 : OpBase
|
||||||
{
|
{
|
||||||
internal Palette8(ITwainStateInternal session) : base(session) { }
|
internal Palette8(ITwainSessionInternal session) : base(session) { }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// This operation causes the Source to report its current palette information.
|
/// This operation causes the Source to report its current palette information.
|
||||||
|
@ -8,7 +8,7 @@ namespace NTwain.Triplets
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed class RgbResponse : OpBase
|
public sealed class RgbResponse : OpBase
|
||||||
{
|
{
|
||||||
internal RgbResponse(ITwainStateInternal session) : base(session) { }
|
internal RgbResponse(ITwainSessionInternal session) : base(session) { }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Causes the Source to use its "identity" response curves for future RGB transfers. The identity
|
/// Causes the Source to use its "identity" response curves for future RGB transfers. The identity
|
||||||
|
@ -8,8 +8,8 @@ namespace NTwain.Triplets
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed class DGImage
|
public sealed class DGImage
|
||||||
{
|
{
|
||||||
ITwainStateInternal _session;
|
ITwainSessionInternal _session;
|
||||||
internal DGImage(ITwainStateInternal session)
|
internal DGImage(ITwainSessionInternal session)
|
||||||
{
|
{
|
||||||
if (session == null) { throw new ArgumentNullException("session"); }
|
if (session == null) { throw new ArgumentNullException("session"); }
|
||||||
_session = session;
|
_session = session;
|
||||||
|
@ -13,7 +13,7 @@ namespace NTwain.Triplets
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="session">The session.</param>
|
/// <param name="session">The session.</param>
|
||||||
/// <exception cref="System.ArgumentNullException"></exception>
|
/// <exception cref="System.ArgumentNullException"></exception>
|
||||||
internal OpBase(ITwainStateInternal session)
|
internal OpBase(ITwainSessionInternal session)
|
||||||
{
|
{
|
||||||
if (session == null) { throw new ArgumentNullException("session"); }
|
if (session == null) { throw new ArgumentNullException("session"); }
|
||||||
Session = session;
|
Session = session;
|
||||||
@ -25,6 +25,6 @@ namespace NTwain.Triplets
|
|||||||
/// <value>
|
/// <value>
|
||||||
/// The session.
|
/// The session.
|
||||||
/// </value>
|
/// </value>
|
||||||
internal ITwainStateInternal Session { get; private set; }
|
internal ITwainSessionInternal Session { get; private set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,7 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.ComponentModel;
|
using System.ComponentModel;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
|
using System.Globalization;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
@ -15,7 +16,7 @@ namespace NTwain
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Basic class for interfacing with TWAIN. You should only have one of this per application process.
|
/// Basic class for interfacing with TWAIN. You should only have one of this per application process.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class TwainSession : ITwainStateInternal, ITwainOperation
|
public class TwainSession : ITwainSessionInternal
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes a new instance of the <see cref="TwainSession" /> class.
|
/// Initializes a new instance of the <see cref="TwainSession" /> class.
|
||||||
@ -27,21 +28,22 @@ namespace NTwain
|
|||||||
if (appId == null) { throw new ArgumentNullException("appId"); }
|
if (appId == null) { throw new ArgumentNullException("appId"); }
|
||||||
|
|
||||||
_appId = appId;
|
_appId = appId;
|
||||||
((ITwainStateInternal)this).ChangeState(1, false);
|
((ITwainSessionInternal)this).ChangeState(1, false);
|
||||||
EnforceState = true;
|
EnforceState = true;
|
||||||
|
|
||||||
MessageLoop.Instance.EnsureStarted(HandleWndProcMessage);
|
MessageLoop.Instance.EnsureStarted(HandleWndProcMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
TWIdentity _appId;
|
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
|
||||||
object _callbackObj; // kept around so it doesn't get gc'ed
|
object _callbackObj; // kept around so it doesn't get gc'ed
|
||||||
|
TWIdentity _appId;
|
||||||
TWUserInterface _twui;
|
TWUserInterface _twui;
|
||||||
|
|
||||||
static readonly CapabilityId[] _emptyCapList = new CapabilityId[0];
|
static readonly CapabilityId[] _emptyCapList = new CapabilityId[0];
|
||||||
|
|
||||||
private IList<CapabilityId> _supportedCaps;
|
private IList<CapabilityId> _supportedCaps;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the supported caps for the current source.
|
/// Gets the supported caps for the currently open source.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>
|
/// <value>
|
||||||
/// The supported caps.
|
/// The supported caps.
|
||||||
@ -64,7 +66,7 @@ namespace NTwain
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// EXPERIMENTAL. Gets or sets the optional synchronization context.
|
/// Gets or sets the optional synchronization context.
|
||||||
/// This allows events to be raised on the thread
|
/// This allows events to be raised on the thread
|
||||||
/// associated with the context.
|
/// associated with the context.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -74,13 +76,13 @@ namespace NTwain
|
|||||||
public SynchronizationContext SynchronizationContext { get; set; }
|
public SynchronizationContext SynchronizationContext { get; set; }
|
||||||
|
|
||||||
|
|
||||||
#region ITwainStateInternal Members
|
#region ITwainSessionInternal Members
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the app id used for the session.
|
/// Gets the app id used for the session.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>The app id.</value>
|
/// <value>The app id.</value>
|
||||||
TWIdentity ITwainStateInternal.AppId { get { return _appId; } }
|
TWIdentity ITwainSessionInternal.AppId { get { return _appId; } }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets a value indicating whether calls to triplets will verify the current twain session state.
|
/// Gets or sets a value indicating whether calls to triplets will verify the current twain session state.
|
||||||
@ -90,7 +92,7 @@ namespace NTwain
|
|||||||
/// </value>
|
/// </value>
|
||||||
public bool EnforceState { get; set; }
|
public bool EnforceState { get; set; }
|
||||||
|
|
||||||
void ITwainStateInternal.ChangeState(int newState, bool notifyChange)
|
void ITwainSessionInternal.ChangeState(int newState, bool notifyChange)
|
||||||
{
|
{
|
||||||
_state = newState;
|
_state = newState;
|
||||||
if (notifyChange)
|
if (notifyChange)
|
||||||
@ -100,18 +102,31 @@ namespace NTwain
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ICommittable ITwainStateInternal.GetPendingStateChanger(int newState)
|
ICommittable ITwainSessionInternal.GetPendingStateChanger(int newState)
|
||||||
{
|
{
|
||||||
return new TentativeStateCommitable(this, newState);
|
return new TentativeStateCommitable(this, newState);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ITwainStateInternal.ChangeSourceId(TWIdentity sourceId)
|
void ITwainSessionInternal.ChangeSourceId(TWIdentity sourceId)
|
||||||
{
|
{
|
||||||
SourceId = sourceId;
|
SourceId = sourceId;
|
||||||
RaisePropertyChanged("SourceId");
|
RaisePropertyChanged("SourceId");
|
||||||
SafeAsyncSyncableRaiseOnEvent(OnSourceChanged, SourceChanged);
|
SafeAsyncSyncableRaiseOnEvent(OnSourceChanged, SourceChanged);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ITwainSessionInternal.SafeSyncableRaiseEvent(DataTransferredEventArgs e)
|
||||||
|
{
|
||||||
|
SafeSyncableRaiseOnEvent(OnDataTransferred, DataTransferred, e);
|
||||||
|
}
|
||||||
|
void ITwainSessionInternal.SafeSyncableRaiseEvent(TransferErrorEventArgs e)
|
||||||
|
{
|
||||||
|
SafeSyncableRaiseOnEvent(OnTransferError, TransferError, e);
|
||||||
|
}
|
||||||
|
void ITwainSessionInternal.SafeSyncableRaiseEvent(TransferReadyEventArgs e)
|
||||||
|
{
|
||||||
|
SafeSyncableRaiseOnEvent(OnTransferReady, TransferReady, e);
|
||||||
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region ITwainState Members
|
#region ITwainState Members
|
||||||
@ -134,7 +149,7 @@ namespace NTwain
|
|||||||
public int State
|
public int State
|
||||||
{
|
{
|
||||||
get { return _state; }
|
get { return _state; }
|
||||||
protected set
|
internal protected set
|
||||||
{
|
{
|
||||||
if (value > 0 && value < 8)
|
if (value > 0 && value < 8)
|
||||||
{
|
{
|
||||||
@ -240,7 +255,7 @@ namespace NTwain
|
|||||||
var rc = ReturnCode.Failure;
|
var rc = ReturnCode.Failure;
|
||||||
MessageLoop.Instance.Invoke(() =>
|
MessageLoop.Instance.Invoke(() =>
|
||||||
{
|
{
|
||||||
Debug.WriteLine(string.Format("Thread {0}: OpenManager.", Thread.CurrentThread.ManagedThreadId));
|
Debug.WriteLine(string.Format(CultureInfo.InvariantCulture, "Thread {0}: OpenManager.", Thread.CurrentThread.ManagedThreadId));
|
||||||
|
|
||||||
rc = DGControl.Parent.OpenDsm(MessageLoop.Instance.LoopHandle);
|
rc = DGControl.Parent.OpenDsm(MessageLoop.Instance.LoopHandle);
|
||||||
if (rc == ReturnCode.Success)
|
if (rc == ReturnCode.Success)
|
||||||
@ -274,7 +289,7 @@ namespace NTwain
|
|||||||
var rc = ReturnCode.Failure;
|
var rc = ReturnCode.Failure;
|
||||||
MessageLoop.Instance.Invoke(() =>
|
MessageLoop.Instance.Invoke(() =>
|
||||||
{
|
{
|
||||||
Debug.WriteLine(string.Format("Thread {0}: CloseManager.", Thread.CurrentThread.ManagedThreadId));
|
Debug.WriteLine(string.Format(CultureInfo.InvariantCulture, "Thread {0}: CloseManager.", Thread.CurrentThread.ManagedThreadId));
|
||||||
|
|
||||||
rc = DGControl.Parent.CloseDsm(MessageLoop.Instance.LoopHandle);
|
rc = DGControl.Parent.CloseDsm(MessageLoop.Instance.LoopHandle);
|
||||||
});
|
});
|
||||||
@ -296,7 +311,7 @@ namespace NTwain
|
|||||||
var rc = ReturnCode.Failure;
|
var rc = ReturnCode.Failure;
|
||||||
MessageLoop.Instance.Invoke(() =>
|
MessageLoop.Instance.Invoke(() =>
|
||||||
{
|
{
|
||||||
Debug.WriteLine(string.Format("Thread {0}: OpenSource.", Thread.CurrentThread.ManagedThreadId));
|
Debug.WriteLine(string.Format(CultureInfo.InvariantCulture, "Thread {0}: OpenSource.", Thread.CurrentThread.ManagedThreadId));
|
||||||
|
|
||||||
var source = new TWIdentity();
|
var source = new TWIdentity();
|
||||||
source.ProductName = sourceProductName;
|
source.ProductName = sourceProductName;
|
||||||
@ -318,7 +333,7 @@ namespace NTwain
|
|||||||
var rc = ReturnCode.Failure;
|
var rc = ReturnCode.Failure;
|
||||||
MessageLoop.Instance.Invoke(() =>
|
MessageLoop.Instance.Invoke(() =>
|
||||||
{
|
{
|
||||||
Debug.WriteLine(string.Format("Thread {0}: CloseSource.", Thread.CurrentThread.ManagedThreadId));
|
Debug.WriteLine(string.Format(CultureInfo.InvariantCulture, "Thread {0}: CloseSource.", Thread.CurrentThread.ManagedThreadId));
|
||||||
|
|
||||||
rc = DGControl.Identity.CloseDS();
|
rc = DGControl.Identity.CloseDS();
|
||||||
if (rc == ReturnCode.Success)
|
if (rc == ReturnCode.Success)
|
||||||
@ -343,7 +358,7 @@ namespace NTwain
|
|||||||
|
|
||||||
MessageLoop.Instance.Invoke(() =>
|
MessageLoop.Instance.Invoke(() =>
|
||||||
{
|
{
|
||||||
Debug.WriteLine(string.Format("Thread {0}: EnableSource.", Thread.CurrentThread.ManagedThreadId));
|
Debug.WriteLine(string.Format(CultureInfo.InvariantCulture, "Thread {0}: EnableSource.", Thread.CurrentThread.ManagedThreadId));
|
||||||
|
|
||||||
// app v2.2 or higher uses callback2
|
// app v2.2 or higher uses callback2
|
||||||
if (_appId.ProtocolMajor >= 2 && _appId.ProtocolMinor >= 2)
|
if (_appId.ProtocolMajor >= 2 && _appId.ProtocolMinor >= 2)
|
||||||
@ -387,17 +402,13 @@ namespace NTwain
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
ReturnCode ITwainSessionInternal.DisableSource()
|
||||||
/// Disables the source to end data acquisition.
|
|
||||||
/// </summary>
|
|
||||||
/// <returns></returns>
|
|
||||||
protected ReturnCode DisableSource()
|
|
||||||
{
|
{
|
||||||
var rc = ReturnCode.Failure;
|
var rc = ReturnCode.Failure;
|
||||||
|
|
||||||
MessageLoop.Instance.Invoke(() =>
|
MessageLoop.Instance.Invoke(() =>
|
||||||
{
|
{
|
||||||
Debug.WriteLine(string.Format("Thread {0}: DisableSource.", Thread.CurrentThread.ManagedThreadId));
|
Debug.WriteLine(string.Format(CultureInfo.InvariantCulture, "Thread {0}: DisableSource.", Thread.CurrentThread.ManagedThreadId));
|
||||||
|
|
||||||
rc = DGControl.UserInterface.DisableDS(_twui);
|
rc = DGControl.UserInterface.DisableDS(_twui);
|
||||||
if (rc == ReturnCode.Success)
|
if (rc == ReturnCode.Success)
|
||||||
@ -416,7 +427,7 @@ namespace NTwain
|
|||||||
/// <param name="targetState">State of the target.</param>
|
/// <param name="targetState">State of the target.</param>
|
||||||
public void ForceStepDown(int targetState)
|
public void ForceStepDown(int targetState)
|
||||||
{
|
{
|
||||||
Debug.WriteLine(string.Format("Thread {0}: ForceStepDown.", Thread.CurrentThread.ManagedThreadId));
|
Debug.WriteLine(string.Format(CultureInfo.InvariantCulture, "Thread {0}: ForceStepDown.", Thread.CurrentThread.ManagedThreadId));
|
||||||
|
|
||||||
bool origFlag = EnforceState;
|
bool origFlag = EnforceState;
|
||||||
EnforceState = false;
|
EnforceState = false;
|
||||||
@ -448,7 +459,7 @@ namespace NTwain
|
|||||||
}
|
}
|
||||||
if (targetState < 5)
|
if (targetState < 5)
|
||||||
{
|
{
|
||||||
DisableSource();
|
((ITwainSessionInternal)this).DisableSource();
|
||||||
}
|
}
|
||||||
if (targetState < 4)
|
if (targetState < 4)
|
||||||
{
|
{
|
||||||
@ -496,6 +507,38 @@ namespace NTwain
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public event EventHandler<TransferErrorEventArgs> TransferError;
|
public event EventHandler<TransferErrorEventArgs> TransferError;
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Raises event and if applicable marshal it asynchronously to the <see cref="SynchronizationContext"/> thread.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="onEventFunc">The on event function.</param>
|
||||||
|
/// <param name="handler">The handler.</param>
|
||||||
|
void SafeAsyncSyncableRaiseOnEvent(Action onEventFunc, EventHandler handler)
|
||||||
|
{
|
||||||
|
var syncer = SynchronizationContext;
|
||||||
|
if (syncer == null)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
onEventFunc();
|
||||||
|
if (handler != null) { handler(this, EventArgs.Empty); }
|
||||||
|
}
|
||||||
|
catch { }
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
syncer.Post(o =>
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
onEventFunc();
|
||||||
|
if (handler != null) { handler(this, EventArgs.Empty); }
|
||||||
|
}
|
||||||
|
catch { }
|
||||||
|
}, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Raises event and if applicable marshal it synchronously to the <see cref="SynchronizationContext" /> thread.
|
/// Raises event and if applicable marshal it synchronously to the <see cref="SynchronizationContext" /> thread.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -529,37 +572,6 @@ namespace NTwain
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Raises event and if applicable marshal it asynchronously to the <see cref="SynchronizationContext"/> thread.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="onEventFunc">The on event function.</param>
|
|
||||||
/// <param name="handler">The handler.</param>
|
|
||||||
void SafeAsyncSyncableRaiseOnEvent(Action onEventFunc, EventHandler handler)
|
|
||||||
{
|
|
||||||
var syncer = SynchronizationContext;
|
|
||||||
if (syncer == null)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
onEventFunc();
|
|
||||||
if (handler != null) { handler(this, EventArgs.Empty); }
|
|
||||||
}
|
|
||||||
catch { }
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
syncer.Post(o =>
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
onEventFunc();
|
|
||||||
if (handler != null) { handler(this, EventArgs.Empty); }
|
|
||||||
}
|
|
||||||
catch { }
|
|
||||||
}, null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Called when <see cref="State"/> changed.
|
/// Called when <see cref="State"/> changed.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -585,25 +597,24 @@ namespace NTwain
|
|||||||
/// Called when a data transfer is ready.
|
/// Called when a data transfer is ready.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="e">The <see cref="TransferReadyEventArgs"/> instance containing the event data.</param>
|
/// <param name="e">The <see cref="TransferReadyEventArgs"/> instance containing the event data.</param>
|
||||||
protected virtual void OnTransferReady(TransferReadyEventArgs e) { }
|
internal protected virtual void OnTransferReady(TransferReadyEventArgs e) { }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Called when data has been transferred.
|
/// Called when data has been transferred.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="e">The <see cref="DataTransferredEventArgs"/> instance containing the event data.</param>
|
/// <param name="e">The <see cref="DataTransferredEventArgs"/> instance containing the event data.</param>
|
||||||
protected virtual void OnDataTransferred(DataTransferredEventArgs e) { }
|
internal protected virtual void OnDataTransferred(DataTransferredEventArgs e) { }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Called when an error has been encountered during transfer.
|
/// Called when an error has been encountered during transfer.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="e">The <see cref="TransferErrorEventArgs"/> instance containing the event data.</param>
|
/// <param name="e">The <see cref="TransferErrorEventArgs"/> instance containing the event data.</param>
|
||||||
protected virtual void OnTransferError(TransferErrorEventArgs e) { }
|
internal protected virtual void OnTransferError(TransferErrorEventArgs e) { }
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region TWAIN logic during xfer work
|
#region handle twain ds message
|
||||||
|
|
||||||
//[EnvironmentPermissionAttribute(SecurityAction.LinkDemand)]
|
|
||||||
void HandleWndProcMessage(ref WindowsHook.MESSAGE winMsg, ref bool handled)
|
void HandleWndProcMessage(ref WindowsHook.MESSAGE winMsg, ref bool handled)
|
||||||
{
|
{
|
||||||
// this handles the message from a typical WndProc message loop and check if it's from the TWAIN source.
|
// this handles the message from a typical WndProc message loop and check if it's from the TWAIN source.
|
||||||
@ -621,7 +632,7 @@ namespace NTwain
|
|||||||
evt.pEvent = msgPtr;
|
evt.pEvent = msgPtr;
|
||||||
if (handled = (DGControl.Event.ProcessEvent(evt) == ReturnCode.DSEvent))
|
if (handled = (DGControl.Event.ProcessEvent(evt) == ReturnCode.DSEvent))
|
||||||
{
|
{
|
||||||
Debug.WriteLine(string.Format("Thread {0}: HandleWndProcMessage at state {1} with MSG={2}.", Thread.CurrentThread.ManagedThreadId, State, evt.TWMessage));
|
Debug.WriteLine(string.Format(CultureInfo.InvariantCulture, "Thread {0}: HandleWndProcMessage at state {1} with MSG={2}.", Thread.CurrentThread.ManagedThreadId, State, evt.TWMessage));
|
||||||
|
|
||||||
HandleSourceMsg(evt.TWMessage);
|
HandleSourceMsg(evt.TWMessage);
|
||||||
}
|
}
|
||||||
@ -637,7 +648,7 @@ namespace NTwain
|
|||||||
{
|
{
|
||||||
if (origin != null && SourceId != null && origin.Id == SourceId.Id)
|
if (origin != null && SourceId != null && origin.Id == SourceId.Id)
|
||||||
{
|
{
|
||||||
Debug.WriteLine(string.Format("Thread {0}: CallbackHandler at state {1} with MSG={2}.", Thread.CurrentThread.ManagedThreadId, State, msg));
|
Debug.WriteLine(string.Format(CultureInfo.InvariantCulture, "Thread {0}: CallbackHandler at state {1} with MSG={2}.", Thread.CurrentThread.ManagedThreadId, State, msg));
|
||||||
// spec says we must handle this on the thread that enabled the DS.
|
// spec says we must handle this on the thread that enabled the DS.
|
||||||
// by using the internal dispatcher this will be the case.
|
// by using the internal dispatcher this will be the case.
|
||||||
|
|
||||||
@ -660,7 +671,7 @@ namespace NTwain
|
|||||||
{
|
{
|
||||||
State = 6;
|
State = 6;
|
||||||
}
|
}
|
||||||
DoTransferRoutine();
|
TransferLogic.DoTransferRoutine(this);
|
||||||
break;
|
break;
|
||||||
case Message.DeviceEvent:
|
case Message.DeviceEvent:
|
||||||
TWDeviceEvent de;
|
TWDeviceEvent de;
|
||||||
@ -683,530 +694,12 @@ namespace NTwain
|
|||||||
else if (State == 5)
|
else if (State == 5)
|
||||||
{
|
{
|
||||||
// needs this state check since some source sends this more than once
|
// needs this state check since some source sends this more than once
|
||||||
DisableSource();
|
((ITwainSessionInternal)this).DisableSource();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Performs the TWAIN transfer routine at state 6.
|
|
||||||
/// </summary>
|
|
||||||
protected virtual void DoTransferRoutine()
|
|
||||||
{
|
|
||||||
var pending = new TWPendingXfers();
|
|
||||||
var rc = ReturnCode.Success;
|
|
||||||
|
|
||||||
do
|
|
||||||
{
|
|
||||||
#region build and raise xfer ready
|
|
||||||
|
|
||||||
TWAudioInfo audInfo;
|
|
||||||
if (DGAudio.AudioInfo.Get(out audInfo) != ReturnCode.Success)
|
|
||||||
{
|
|
||||||
audInfo = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
TWImageInfo imgInfo;
|
|
||||||
if (DGImage.ImageInfo.Get(out imgInfo) != ReturnCode.Success)
|
|
||||||
{
|
|
||||||
imgInfo = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ask consumer for xfer details
|
|
||||||
var preXferArgs = new TransferReadyEventArgs
|
|
||||||
{
|
|
||||||
AudioInfo = audInfo,
|
|
||||||
PendingImageInfo = imgInfo,
|
|
||||||
PendingTransferCount = pending.Count,
|
|
||||||
EndOfJob = pending.EndOfJob == 0
|
|
||||||
};
|
|
||||||
|
|
||||||
SafeSyncableRaiseOnEvent(OnTransferReady, TransferReady, preXferArgs);
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region actually handle xfer
|
|
||||||
|
|
||||||
if (preXferArgs.CancelAll)
|
|
||||||
{
|
|
||||||
rc = DGControl.PendingXfers.Reset(pending);
|
|
||||||
}
|
|
||||||
else if (!preXferArgs.CancelCurrent)
|
|
||||||
{
|
|
||||||
DataGroups xferGroup = DataGroups.None;
|
|
||||||
|
|
||||||
if (DGControl.XferGroup.Get(ref xferGroup) != ReturnCode.Success)
|
|
||||||
{
|
|
||||||
xferGroup = DataGroups.None;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((xferGroup & DataGroups.Image) == DataGroups.Image)
|
|
||||||
{
|
|
||||||
var mech = this.GetCurrentCap(CapabilityId.ICapXferMech).ConvertToEnum<XferMech>();
|
|
||||||
switch (mech)
|
|
||||||
{
|
|
||||||
case XferMech.Native:
|
|
||||||
DoImageNativeXfer();
|
|
||||||
break;
|
|
||||||
case XferMech.Memory:
|
|
||||||
DoImageMemoryXfer();
|
|
||||||
break;
|
|
||||||
case XferMech.File:
|
|
||||||
DoImageFileXfer();
|
|
||||||
break;
|
|
||||||
case XferMech.MemFile:
|
|
||||||
DoImageMemoryFileXfer();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ((xferGroup & DataGroups.Audio) == DataGroups.Audio)
|
|
||||||
{
|
|
||||||
var mech = this.GetCurrentCap(CapabilityId.ACapXferMech).ConvertToEnum<XferMech>();
|
|
||||||
switch (mech)
|
|
||||||
{
|
|
||||||
case XferMech.Native:
|
|
||||||
DoAudioNativeXfer();
|
|
||||||
break;
|
|
||||||
case XferMech.File:
|
|
||||||
DoAudioFileXfer();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
rc = DGControl.PendingXfers.EndXfer(pending);
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
} while (rc == ReturnCode.Success && pending.Count != 0);
|
|
||||||
|
|
||||||
State = 5;
|
|
||||||
DisableSource();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#region audio xfers
|
|
||||||
|
|
||||||
private void DoAudioNativeXfer()
|
|
||||||
{
|
|
||||||
IntPtr dataPtr = IntPtr.Zero;
|
|
||||||
IntPtr lockedPtr = IntPtr.Zero;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var xrc = DGAudio.AudioNativeXfer.Get(ref dataPtr);
|
|
||||||
if (xrc == ReturnCode.XferDone)
|
|
||||||
{
|
|
||||||
State = 7;
|
|
||||||
if (dataPtr != IntPtr.Zero)
|
|
||||||
{
|
|
||||||
lockedPtr = Platform.MemoryManager.Lock(dataPtr);
|
|
||||||
}
|
|
||||||
|
|
||||||
SafeSyncableRaiseOnEvent(OnDataTransferred, DataTransferred, new DataTransferredEventArgs { NativeData = lockedPtr });
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
SafeSyncableRaiseOnEvent(OnTransferError, TransferError, new TransferErrorEventArgs { ReturnCode = xrc, SourceStatus = this.GetSourceStatus() });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
SafeSyncableRaiseOnEvent(OnTransferError, TransferError, new TransferErrorEventArgs { Exception = ex });
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
State = 6;
|
|
||||||
// data here is allocated by source so needs to use shared mem calls
|
|
||||||
if (lockedPtr != IntPtr.Zero)
|
|
||||||
{
|
|
||||||
Platform.MemoryManager.Unlock(lockedPtr);
|
|
||||||
lockedPtr = IntPtr.Zero;
|
|
||||||
}
|
|
||||||
if (dataPtr != IntPtr.Zero)
|
|
||||||
{
|
|
||||||
Platform.MemoryManager.Free(dataPtr);
|
|
||||||
dataPtr = IntPtr.Zero;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void DoAudioFileXfer()
|
|
||||||
{
|
|
||||||
string filePath = null;
|
|
||||||
TWSetupFileXfer setupInfo;
|
|
||||||
if (DGControl.SetupFileXfer.Get(out setupInfo) == ReturnCode.Success)
|
|
||||||
{
|
|
||||||
filePath = setupInfo.FileName;
|
|
||||||
}
|
|
||||||
|
|
||||||
var xrc = DGAudio.AudioFileXfer.Get();
|
|
||||||
if (xrc == ReturnCode.XferDone)
|
|
||||||
{
|
|
||||||
SafeSyncableRaiseOnEvent(OnDataTransferred, DataTransferred, new DataTransferredEventArgs { FileDataPath = filePath });
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
SafeSyncableRaiseOnEvent(OnTransferError, TransferError, new TransferErrorEventArgs { ReturnCode = xrc, SourceStatus = this.GetSourceStatus() });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region image xfers
|
|
||||||
|
|
||||||
private void DoImageNativeXfer()
|
|
||||||
{
|
|
||||||
IntPtr dataPtr = IntPtr.Zero;
|
|
||||||
IntPtr lockedPtr = IntPtr.Zero;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var xrc = DGImage.ImageNativeXfer.Get(ref dataPtr);
|
|
||||||
if (xrc == ReturnCode.XferDone)
|
|
||||||
{
|
|
||||||
State = 7;
|
|
||||||
TWImageInfo imgInfo;
|
|
||||||
TWExtImageInfo extInfo = null;
|
|
||||||
if (SupportedCaps.Contains(CapabilityId.ICapExtImageInfo))
|
|
||||||
{
|
|
||||||
if (DGImage.ExtImageInfo.Get(out extInfo) != ReturnCode.Success)
|
|
||||||
{
|
|
||||||
extInfo = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (DGImage.ImageInfo.Get(out imgInfo) != ReturnCode.Success)
|
|
||||||
{
|
|
||||||
imgInfo = null;
|
|
||||||
}
|
|
||||||
if (dataPtr != IntPtr.Zero)
|
|
||||||
{
|
|
||||||
lockedPtr = Platform.MemoryManager.Lock(dataPtr);
|
|
||||||
}
|
|
||||||
SafeSyncableRaiseOnEvent(OnDataTransferred, DataTransferred, new DataTransferredEventArgs
|
|
||||||
{
|
|
||||||
NativeData = lockedPtr,
|
|
||||||
ImageInfo = imgInfo,
|
|
||||||
ExImageInfo = extInfo
|
|
||||||
});
|
|
||||||
if (extInfo != null) { extInfo.Dispose(); }
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
SafeSyncableRaiseOnEvent(OnTransferError, TransferError, new TransferErrorEventArgs { ReturnCode = xrc, SourceStatus = this.GetSourceStatus() });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
SafeSyncableRaiseOnEvent(OnTransferError, TransferError, new TransferErrorEventArgs { Exception = ex });
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
State = 6;
|
|
||||||
// data here is allocated by source so needs to use shared mem calls
|
|
||||||
if (lockedPtr != IntPtr.Zero)
|
|
||||||
{
|
|
||||||
Platform.MemoryManager.Unlock(lockedPtr);
|
|
||||||
lockedPtr = IntPtr.Zero;
|
|
||||||
}
|
|
||||||
if (dataPtr != IntPtr.Zero)
|
|
||||||
{
|
|
||||||
Platform.MemoryManager.Free(dataPtr);
|
|
||||||
dataPtr = IntPtr.Zero;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void DoImageFileXfer()
|
|
||||||
{
|
|
||||||
string filePath = null;
|
|
||||||
TWSetupFileXfer setupInfo;
|
|
||||||
if (DGControl.SetupFileXfer.Get(out setupInfo) == ReturnCode.Success)
|
|
||||||
{
|
|
||||||
filePath = setupInfo.FileName;
|
|
||||||
}
|
|
||||||
|
|
||||||
var xrc = DGImage.ImageFileXfer.Get();
|
|
||||||
if (xrc == ReturnCode.XferDone)
|
|
||||||
{
|
|
||||||
TWImageInfo imgInfo;
|
|
||||||
TWExtImageInfo extInfo = null;
|
|
||||||
if (SupportedCaps.Contains(CapabilityId.ICapExtImageInfo))
|
|
||||||
{
|
|
||||||
if (DGImage.ExtImageInfo.Get(out extInfo) != ReturnCode.Success)
|
|
||||||
{
|
|
||||||
extInfo = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (DGImage.ImageInfo.Get(out imgInfo) != ReturnCode.Success)
|
|
||||||
{
|
|
||||||
imgInfo = null;
|
|
||||||
}
|
|
||||||
SafeSyncableRaiseOnEvent(OnDataTransferred, DataTransferred, new DataTransferredEventArgs
|
|
||||||
{
|
|
||||||
FileDataPath = filePath,
|
|
||||||
ImageInfo = imgInfo,
|
|
||||||
ExImageInfo = extInfo
|
|
||||||
});
|
|
||||||
if (extInfo != null) { extInfo.Dispose(); }
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
SafeSyncableRaiseOnEvent(OnTransferError, TransferError, new TransferErrorEventArgs { ReturnCode = xrc, SourceStatus = this.GetSourceStatus() });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void DoImageMemoryXfer()
|
|
||||||
{
|
|
||||||
TWSetupMemXfer memInfo;
|
|
||||||
if (DGControl.SetupMemXfer.Get(out memInfo) == ReturnCode.Success)
|
|
||||||
{
|
|
||||||
TWImageMemXfer xferInfo = new TWImageMemXfer();
|
|
||||||
try
|
|
||||||
{
|
|
||||||
// how to tell if going to xfer in strip vs tile?
|
|
||||||
// if tile don't allocate memory in app?
|
|
||||||
|
|
||||||
xferInfo.Memory = new TWMemory
|
|
||||||
{
|
|
||||||
Flags = MemoryFlags.AppOwns | MemoryFlags.Pointer,
|
|
||||||
Length = memInfo.Preferred,
|
|
||||||
TheMem = Platform.MemoryManager.Allocate(memInfo.Preferred)
|
|
||||||
};
|
|
||||||
|
|
||||||
// do the unthinkable and keep all xferred batches in memory,
|
|
||||||
// possibly defeating the purpose of mem xfer
|
|
||||||
// unless compression is used.
|
|
||||||
// todo: use array instead of memory stream?
|
|
||||||
using (MemoryStream xferredData = new MemoryStream())
|
|
||||||
{
|
|
||||||
var xrc = ReturnCode.Success;
|
|
||||||
do
|
|
||||||
{
|
|
||||||
xrc = DGImage.ImageMemFileXfer.Get(xferInfo);
|
|
||||||
|
|
||||||
if (xrc == ReturnCode.Success ||
|
|
||||||
xrc == ReturnCode.XferDone)
|
|
||||||
{
|
|
||||||
State = 7;
|
|
||||||
// optimize and allocate buffer only once instead of inside the loop?
|
|
||||||
byte[] buffer = new byte[(int)xferInfo.BytesWritten];
|
|
||||||
|
|
||||||
IntPtr lockPtr = IntPtr.Zero;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
lockPtr = Platform.MemoryManager.Lock(xferInfo.Memory.TheMem);
|
|
||||||
Marshal.Copy(lockPtr, buffer, 0, buffer.Length);
|
|
||||||
xferredData.Write(buffer, 0, buffer.Length);
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
if (lockPtr != IntPtr.Zero)
|
|
||||||
{
|
|
||||||
Platform.MemoryManager.Unlock(lockPtr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} while (xrc == ReturnCode.Success);
|
|
||||||
|
|
||||||
if (xrc == ReturnCode.XferDone)
|
|
||||||
{
|
|
||||||
TWImageInfo imgInfo;
|
|
||||||
TWExtImageInfo extInfo = null;
|
|
||||||
if (SupportedCaps.Contains(CapabilityId.ICapExtImageInfo))
|
|
||||||
{
|
|
||||||
if (DGImage.ExtImageInfo.Get(out extInfo) != ReturnCode.Success)
|
|
||||||
{
|
|
||||||
extInfo = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (DGImage.ImageInfo.Get(out imgInfo) != ReturnCode.Success)
|
|
||||||
{
|
|
||||||
imgInfo = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
SafeSyncableRaiseOnEvent(OnDataTransferred, DataTransferred, new DataTransferredEventArgs
|
|
||||||
{
|
|
||||||
MemData = xferredData.ToArray(),
|
|
||||||
ImageInfo = imgInfo,
|
|
||||||
ExImageInfo = extInfo
|
|
||||||
});
|
|
||||||
if (extInfo != null) { extInfo.Dispose(); }
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
SafeSyncableRaiseOnEvent(OnTransferError, TransferError, new TransferErrorEventArgs { ReturnCode = xrc, SourceStatus = this.GetSourceStatus() });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
SafeSyncableRaiseOnEvent(OnTransferError, TransferError, new TransferErrorEventArgs { Exception = ex });
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
State = 6;
|
|
||||||
if (xferInfo.Memory.TheMem != IntPtr.Zero)
|
|
||||||
{
|
|
||||||
Platform.MemoryManager.Free(xferInfo.Memory.TheMem);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void DoImageMemoryFileXfer()
|
|
||||||
{
|
|
||||||
// since it's memory-file xfer need info from both (maybe)
|
|
||||||
TWSetupMemXfer memInfo;
|
|
||||||
TWSetupFileXfer fileInfo;
|
|
||||||
if (DGControl.SetupMemXfer.Get(out memInfo) == ReturnCode.Success &&
|
|
||||||
DGControl.SetupFileXfer.Get(out fileInfo) == ReturnCode.Success)
|
|
||||||
{
|
|
||||||
TWImageMemXfer xferInfo = new TWImageMemXfer();
|
|
||||||
var tempFile = Path.GetTempFileName();
|
|
||||||
string finalFile = null;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
// no strip or tile here, just chunks
|
|
||||||
xferInfo.Memory = new TWMemory
|
|
||||||
{
|
|
||||||
Flags = MemoryFlags.AppOwns | MemoryFlags.Pointer,
|
|
||||||
Length = memInfo.Preferred,
|
|
||||||
TheMem = Platform.MemoryManager.Allocate(memInfo.Preferred)
|
|
||||||
};
|
|
||||||
|
|
||||||
var xrc = ReturnCode.Success;
|
|
||||||
using (var outStream = File.OpenWrite(tempFile))
|
|
||||||
{
|
|
||||||
do
|
|
||||||
{
|
|
||||||
xrc = DGImage.ImageMemFileXfer.Get(xferInfo);
|
|
||||||
|
|
||||||
if (xrc == ReturnCode.Success ||
|
|
||||||
xrc == ReturnCode.XferDone)
|
|
||||||
{
|
|
||||||
State = 7;
|
|
||||||
byte[] buffer = new byte[(int)xferInfo.BytesWritten];
|
|
||||||
|
|
||||||
IntPtr lockPtr = IntPtr.Zero;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
lockPtr = Platform.MemoryManager.Lock(xferInfo.Memory.TheMem);
|
|
||||||
Marshal.Copy(lockPtr, buffer, 0, buffer.Length);
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
if (lockPtr != IntPtr.Zero)
|
|
||||||
{
|
|
||||||
Platform.MemoryManager.Unlock(lockPtr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
outStream.Write(buffer, 0, buffer.Length);
|
|
||||||
}
|
|
||||||
} while (xrc == ReturnCode.Success);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (xrc == ReturnCode.XferDone)
|
|
||||||
{
|
|
||||||
switch (fileInfo.Format)
|
|
||||||
{
|
|
||||||
case FileFormat.Bmp:
|
|
||||||
finalFile = Path.ChangeExtension(tempFile, ".bmp");
|
|
||||||
break;
|
|
||||||
case FileFormat.Dejavu:
|
|
||||||
finalFile = Path.ChangeExtension(tempFile, ".dejavu");
|
|
||||||
break;
|
|
||||||
case FileFormat.Exif:
|
|
||||||
finalFile = Path.ChangeExtension(tempFile, ".exit");
|
|
||||||
break;
|
|
||||||
case FileFormat.Fpx:
|
|
||||||
finalFile = Path.ChangeExtension(tempFile, ".fpx");
|
|
||||||
break;
|
|
||||||
case FileFormat.Jfif:
|
|
||||||
finalFile = Path.ChangeExtension(tempFile, ".jpg");
|
|
||||||
break;
|
|
||||||
case FileFormat.Jp2:
|
|
||||||
finalFile = Path.ChangeExtension(tempFile, ".jp2");
|
|
||||||
break;
|
|
||||||
case FileFormat.Jpx:
|
|
||||||
finalFile = Path.ChangeExtension(tempFile, ".jpx");
|
|
||||||
break;
|
|
||||||
case FileFormat.Pdf:
|
|
||||||
case FileFormat.PdfA:
|
|
||||||
case FileFormat.PdfA2:
|
|
||||||
finalFile = Path.ChangeExtension(tempFile, ".pdf");
|
|
||||||
break;
|
|
||||||
case FileFormat.Pict:
|
|
||||||
finalFile = Path.ChangeExtension(tempFile, ".pict");
|
|
||||||
break;
|
|
||||||
case FileFormat.Png:
|
|
||||||
finalFile = Path.ChangeExtension(tempFile, ".png");
|
|
||||||
break;
|
|
||||||
case FileFormat.Spiff:
|
|
||||||
finalFile = Path.ChangeExtension(tempFile, ".spiff");
|
|
||||||
break;
|
|
||||||
case FileFormat.Tiff:
|
|
||||||
case FileFormat.TiffMulti:
|
|
||||||
finalFile = Path.ChangeExtension(tempFile, ".tif");
|
|
||||||
break;
|
|
||||||
case FileFormat.Xbm:
|
|
||||||
finalFile = Path.ChangeExtension(tempFile, ".xbm");
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
finalFile = Path.ChangeExtension(tempFile, ".unknown");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
File.Move(tempFile, finalFile);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
SafeSyncableRaiseOnEvent(OnTransferError, TransferError, new TransferErrorEventArgs { ReturnCode = xrc, SourceStatus = this.GetSourceStatus() });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
SafeSyncableRaiseOnEvent(OnTransferError, TransferError, new TransferErrorEventArgs { Exception = ex });
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
State = 6;
|
|
||||||
if (xferInfo.Memory.TheMem != IntPtr.Zero)
|
|
||||||
{
|
|
||||||
Platform.MemoryManager.Free(xferInfo.Memory.TheMem);
|
|
||||||
}
|
|
||||||
if (File.Exists(tempFile))
|
|
||||||
{
|
|
||||||
File.Delete(tempFile);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (File.Exists(finalFile))
|
|
||||||
{
|
|
||||||
TWImageInfo imgInfo;
|
|
||||||
TWExtImageInfo extInfo = null;
|
|
||||||
if (SupportedCaps.Contains(CapabilityId.ICapExtImageInfo))
|
|
||||||
{
|
|
||||||
if (DGImage.ExtImageInfo.Get(out extInfo) != ReturnCode.Success)
|
|
||||||
{
|
|
||||||
extInfo = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (DGImage.ImageInfo.Get(out imgInfo) != ReturnCode.Success)
|
|
||||||
{
|
|
||||||
imgInfo = null;
|
|
||||||
}
|
|
||||||
SafeSyncableRaiseOnEvent(OnDataTransferred, DataTransferred, new DataTransferredEventArgs
|
|
||||||
{
|
|
||||||
FileDataPath = finalFile,
|
|
||||||
ImageInfo = imgInfo,
|
|
||||||
ExImageInfo = extInfo
|
|
||||||
});
|
|
||||||
if (extInfo != null) { extInfo.Dispose(); }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,7 +15,7 @@ namespace NTwain
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="session">The session.</param>
|
/// <param name="session">The session.</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public static TWStatus GetManagerStatus(this TwainSession session)
|
public static TWStatus GetManagerStatus(this ITwainOperation session)
|
||||||
{
|
{
|
||||||
TWStatus stat;
|
TWStatus stat;
|
||||||
session.DGControl.Status.GetManager(out stat);
|
session.DGControl.Status.GetManager(out stat);
|
||||||
@ -26,7 +26,7 @@ namespace NTwain
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="session">The session.</param>
|
/// <param name="session">The session.</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public static TWStatus GetSourceStatus(this TwainSession session)
|
public static TWStatus GetSourceStatus(this ITwainOperation session)
|
||||||
{
|
{
|
||||||
TWStatus stat;
|
TWStatus stat;
|
||||||
session.DGControl.Status.GetSource(out stat);
|
session.DGControl.Status.GetSource(out stat);
|
||||||
@ -39,7 +39,7 @@ namespace NTwain
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="session">The session.</param>
|
/// <param name="session">The session.</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public static IList<TWIdentity> GetSources(this TwainSession session)
|
public static IList<TWIdentity> GetSources(this ITwainOperation session)
|
||||||
{
|
{
|
||||||
List<TWIdentity> list = new List<TWIdentity>();
|
List<TWIdentity> list = new List<TWIdentity>();
|
||||||
|
|
||||||
@ -67,7 +67,7 @@ namespace NTwain
|
|||||||
/// <param name="session">The session.</param>
|
/// <param name="session">The session.</param>
|
||||||
/// <param name="capId">The cap id.</param>
|
/// <param name="capId">The cap id.</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public static object GetCurrentCap(this TwainSession session, CapabilityId capId)
|
public static object GetCurrentCap(this ITwainOperation session, CapabilityId capId)
|
||||||
{
|
{
|
||||||
using (TWCapability cap = new TWCapability(capId))
|
using (TWCapability cap = new TWCapability(capId))
|
||||||
{
|
{
|
||||||
@ -147,7 +147,7 @@ namespace NTwain
|
|||||||
/// <param name="session">The session.</param>
|
/// <param name="session">The session.</param>
|
||||||
/// <param name="capabilityId">The capability unique identifier.</param>
|
/// <param name="capabilityId">The capability unique identifier.</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public static IList<object> GetCapabilityValues(this TwainSession session, CapabilityId capabilityId)
|
public static IList<object> GetCapabilityValues(this ITwainOperation session, CapabilityId capabilityId)
|
||||||
{
|
{
|
||||||
var list = new List<object>();
|
var list = new List<object>();
|
||||||
using (TWCapability cap = new TWCapability(capabilityId))
|
using (TWCapability cap = new TWCapability(capabilityId))
|
||||||
@ -167,7 +167,7 @@ namespace NTwain
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="session">The session.</param>
|
/// <param name="session">The session.</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
internal static IList<CapabilityId> GetCapabilities(this TwainSession session)
|
internal static IList<CapabilityId> GetCapabilities(this ITwainOperation session)
|
||||||
{
|
{
|
||||||
return session.GetCapabilityValues(CapabilityId.CapSupportedCaps).CastToEnum<CapabilityId>(false);
|
return session.GetCapabilityValues(CapabilityId.CapSupportedCaps).CastToEnum<CapabilityId>(false);
|
||||||
}
|
}
|
||||||
@ -180,7 +180,7 @@ namespace NTwain
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="session">The session.</param>
|
/// <param name="session">The session.</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public static IList<XferMech> CapGetImageXferMech(this TwainSession session)
|
public static IList<XferMech> CapGetImageXferMech(this ITwainOperation session)
|
||||||
{
|
{
|
||||||
return session.GetCapabilityValues(CapabilityId.ICapXferMech).CastToEnum<XferMech>(true);
|
return session.GetCapabilityValues(CapabilityId.ICapXferMech).CastToEnum<XferMech>(true);
|
||||||
}
|
}
|
||||||
@ -195,7 +195,7 @@ namespace NTwain
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="session">The session.</param>
|
/// <param name="session">The session.</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public static IList<CompressionType> CapGetCompression(this TwainSession session)
|
public static IList<CompressionType> CapGetCompression(this ITwainOperation session)
|
||||||
{
|
{
|
||||||
return session.GetCapabilityValues(CapabilityId.ICapCompression).CastToEnum<CompressionType>(true);
|
return session.GetCapabilityValues(CapabilityId.ICapCompression).CastToEnum<CompressionType>(true);
|
||||||
}
|
}
|
||||||
@ -206,7 +206,7 @@ namespace NTwain
|
|||||||
/// <param name="session">The session.</param>
|
/// <param name="session">The session.</param>
|
||||||
/// <param name="compression">The compression.</param>
|
/// <param name="compression">The compression.</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public static ReturnCode CapSetImageCompression(this TwainSession session, CompressionType compression)
|
public static ReturnCode CapSetImageCompression(this ITwainOperation session, CompressionType compression)
|
||||||
{
|
{
|
||||||
using (TWCapability compressCap = new TWCapability(CapabilityId.ICapCompression, new TWOneValue { Item = (uint)compression, ItemType = ItemType.UInt16 }))
|
using (TWCapability compressCap = new TWCapability(CapabilityId.ICapCompression, new TWOneValue { Item = (uint)compression, ItemType = ItemType.UInt16 }))
|
||||||
{
|
{
|
||||||
@ -224,7 +224,7 @@ namespace NTwain
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="session">The session.</param>
|
/// <param name="session">The session.</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public static IList<FileFormat> CapGetImageFileFormat(this TwainSession session)
|
public static IList<FileFormat> CapGetImageFileFormat(this ITwainOperation session)
|
||||||
{
|
{
|
||||||
return session.GetCapabilityValues(CapabilityId.ICapImageFileFormat).CastToEnum<FileFormat>(true);
|
return session.GetCapabilityValues(CapabilityId.ICapImageFileFormat).CastToEnum<FileFormat>(true);
|
||||||
}
|
}
|
||||||
@ -235,7 +235,7 @@ namespace NTwain
|
|||||||
/// <param name="session">The session.</param>
|
/// <param name="session">The session.</param>
|
||||||
/// <param name="format">The format.</param>
|
/// <param name="format">The format.</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public static ReturnCode CapSetImageFormat(this TwainSession session, FileFormat format)
|
public static ReturnCode CapSetImageFormat(this ITwainOperation session, FileFormat format)
|
||||||
{
|
{
|
||||||
using (TWCapability formatCap = new TWCapability(CapabilityId.ICapImageFileFormat, new TWOneValue { Item = (uint)format, ItemType = ItemType.UInt16 }))
|
using (TWCapability formatCap = new TWCapability(CapabilityId.ICapImageFileFormat, new TWOneValue { Item = (uint)format, ItemType = ItemType.UInt16 }))
|
||||||
{
|
{
|
||||||
@ -253,7 +253,7 @@ namespace NTwain
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="session">The session.</param>
|
/// <param name="session">The session.</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public static IList<PixelType> CapGetPixelTypes(this TwainSession session)
|
public static IList<PixelType> CapGetPixelTypes(this ITwainOperation session)
|
||||||
{
|
{
|
||||||
return session.GetCapabilityValues(CapabilityId.ICapPixelType).CastToEnum<PixelType>(true);
|
return session.GetCapabilityValues(CapabilityId.ICapPixelType).CastToEnum<PixelType>(true);
|
||||||
}
|
}
|
||||||
@ -264,7 +264,7 @@ namespace NTwain
|
|||||||
/// <param name="session">The session.</param>
|
/// <param name="session">The session.</param>
|
||||||
/// <param name="type">The type.</param>
|
/// <param name="type">The type.</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public static ReturnCode CapSetPixelType(this TwainSession session, PixelType type)
|
public static ReturnCode CapSetPixelType(this ITwainOperation session, PixelType type)
|
||||||
{
|
{
|
||||||
var one = new TWOneValue();
|
var one = new TWOneValue();
|
||||||
one.Item = (uint)type;
|
one.Item = (uint)type;
|
||||||
@ -285,7 +285,7 @@ namespace NTwain
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="session">The session.</param>
|
/// <param name="session">The session.</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public static IList<XferMech> CapGetImageXferMechs(this TwainSession session)
|
public static IList<XferMech> CapGetImageXferMechs(this ITwainOperation session)
|
||||||
{
|
{
|
||||||
return session.GetCapabilityValues(CapabilityId.ICapXferMech).CastToEnum<XferMech>(true);
|
return session.GetCapabilityValues(CapabilityId.ICapXferMech).CastToEnum<XferMech>(true);
|
||||||
}
|
}
|
||||||
@ -296,7 +296,7 @@ namespace NTwain
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="session">The session.</param>
|
/// <param name="session">The session.</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public static IList<XferMech> CapGetAudioXferMechs(this TwainSession session)
|
public static IList<XferMech> CapGetAudioXferMechs(this ITwainOperation session)
|
||||||
{
|
{
|
||||||
return session.GetCapabilityValues(CapabilityId.ACapXferMech).CastToEnum<XferMech>(true);
|
return session.GetCapabilityValues(CapabilityId.ACapXferMech).CastToEnum<XferMech>(true);
|
||||||
}
|
}
|
||||||
@ -307,7 +307,7 @@ namespace NTwain
|
|||||||
/// <param name="session">The session.</param>
|
/// <param name="session">The session.</param>
|
||||||
/// <param name="type">The type.</param>
|
/// <param name="type">The type.</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public static ReturnCode CapSetImageXferMech(this TwainSession session, XferMech type)
|
public static ReturnCode CapSetImageXferMech(this ITwainOperation session, XferMech type)
|
||||||
{
|
{
|
||||||
var one = new TWOneValue();
|
var one = new TWOneValue();
|
||||||
one.Item = (uint)type;
|
one.Item = (uint)type;
|
||||||
@ -324,7 +324,7 @@ namespace NTwain
|
|||||||
/// <param name="session">The session.</param>
|
/// <param name="session">The session.</param>
|
||||||
/// <param name="type">The type.</param>
|
/// <param name="type">The type.</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public static ReturnCode CapSetAudioXferMech(this TwainSession session, XferMech type)
|
public static ReturnCode CapSetAudioXferMech(this ITwainOperation session, XferMech type)
|
||||||
{
|
{
|
||||||
var one = new TWOneValue();
|
var one = new TWOneValue();
|
||||||
one.Item = (uint)type;
|
one.Item = (uint)type;
|
||||||
@ -345,7 +345,7 @@ namespace NTwain
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="session">The session.</param>
|
/// <param name="session">The session.</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public static IList<TWFix32> CapGetDPIs(this TwainSession session)
|
public static IList<TWFix32> CapGetDPIs(this ITwainOperation session)
|
||||||
{
|
{
|
||||||
var list = session.GetCapabilityValues(CapabilityId.ICapXResolution);
|
var list = session.GetCapabilityValues(CapabilityId.ICapXResolution);
|
||||||
return list.Select(o => o.ConvertToFix32()).ToList();
|
return list.Select(o => o.ConvertToFix32()).ToList();
|
||||||
@ -357,7 +357,7 @@ namespace NTwain
|
|||||||
/// <param name="session">The session.</param>
|
/// <param name="session">The session.</param>
|
||||||
/// <param name="dpi">The DPI.</param>
|
/// <param name="dpi">The DPI.</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public static ReturnCode CapSetDPI(this TwainSession session, TWFix32 dpi)
|
public static ReturnCode CapSetDPI(this ITwainOperation session, TWFix32 dpi)
|
||||||
{
|
{
|
||||||
return CapSetDPI(session, dpi, dpi);
|
return CapSetDPI(session, dpi, dpi);
|
||||||
}
|
}
|
||||||
@ -369,7 +369,7 @@ namespace NTwain
|
|||||||
/// <param name="xDPI">The x DPI.</param>
|
/// <param name="xDPI">The x DPI.</param>
|
||||||
/// <param name="yDPI">The y DPI.</param>
|
/// <param name="yDPI">The y DPI.</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public static ReturnCode CapSetDPI(this TwainSession session, TWFix32 xDPI, TWFix32 yDPI)
|
public static ReturnCode CapSetDPI(this ITwainOperation session, TWFix32 xDPI, TWFix32 yDPI)
|
||||||
{
|
{
|
||||||
TWOneValue one = new TWOneValue();
|
TWOneValue one = new TWOneValue();
|
||||||
one.Item = (uint)xDPI;// ((uint)dpi) << 16;
|
one.Item = (uint)xDPI;// ((uint)dpi) << 16;
|
||||||
@ -400,7 +400,7 @@ namespace NTwain
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="session">The session.</param>
|
/// <param name="session">The session.</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public static IList<SupportedSize> CapGetSupportedSizes(this TwainSession session)
|
public static IList<SupportedSize> CapGetSupportedSizes(this ITwainOperation session)
|
||||||
{
|
{
|
||||||
return session.GetCapabilityValues(CapabilityId.ICapSupportedSizes).CastToEnum<SupportedSize>(true);
|
return session.GetCapabilityValues(CapabilityId.ICapSupportedSizes).CastToEnum<SupportedSize>(true);
|
||||||
}
|
}
|
||||||
@ -411,7 +411,7 @@ namespace NTwain
|
|||||||
/// <param name="session">The session.</param>
|
/// <param name="session">The session.</param>
|
||||||
/// <param name="size">The size.</param>
|
/// <param name="size">The size.</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public static ReturnCode CapSetSupportedSize(this TwainSession session, SupportedSize size)
|
public static ReturnCode CapSetSupportedSize(this ITwainOperation session, SupportedSize size)
|
||||||
{
|
{
|
||||||
var one = new TWOneValue();
|
var one = new TWOneValue();
|
||||||
one.Item = (uint)size;
|
one.Item = (uint)size;
|
||||||
@ -474,7 +474,7 @@ namespace NTwain
|
|||||||
/// <param name="session">The session.</param>
|
/// <param name="session">The session.</param>
|
||||||
/// <param name="useIt">if set to <c>true</c> [use it].</param>
|
/// <param name="useIt">if set to <c>true</c> [use it].</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public static ReturnCode CapSetAutoRotate(this TwainSession session, bool useIt)
|
public static ReturnCode CapSetAutoRotate(this ITwainSession session, bool useIt)
|
||||||
{
|
{
|
||||||
var rc = ReturnCode.Failure;
|
var rc = ReturnCode.Failure;
|
||||||
if (session.SupportedCaps.Contains(CapabilityId.ICapAutomaticRotate))
|
if (session.SupportedCaps.Contains(CapabilityId.ICapAutomaticRotate))
|
||||||
@ -512,7 +512,7 @@ namespace NTwain
|
|||||||
/// <param name="session">The session.</param>
|
/// <param name="session">The session.</param>
|
||||||
/// <param name="useIt">if set to <c>true</c> [use it].</param>
|
/// <param name="useIt">if set to <c>true</c> [use it].</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public static ReturnCode CapSetBorderDetection(this TwainSession session, bool useIt)
|
public static ReturnCode CapSetBorderDetection(this ITwainSession session, bool useIt)
|
||||||
{
|
{
|
||||||
var rc = ReturnCode.Failure;
|
var rc = ReturnCode.Failure;
|
||||||
if (session.SupportedCaps.Contains(CapabilityId.ICapAutomaticBorderDetection))
|
if (session.SupportedCaps.Contains(CapabilityId.ICapAutomaticBorderDetection))
|
||||||
@ -560,7 +560,7 @@ namespace NTwain
|
|||||||
/// <param name="session">The session.</param>
|
/// <param name="session">The session.</param>
|
||||||
/// <param name="useIt">if set to <c>true</c> [use it].</param>
|
/// <param name="useIt">if set to <c>true</c> [use it].</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public static ReturnCode CapSetDuplex(this TwainSession session, bool useIt)
|
public static ReturnCode CapSetDuplex(this ITwainSession session, bool useIt)
|
||||||
{
|
{
|
||||||
if (session.SourceId.ProtocolMajor >= 2)
|
if (session.SourceId.ProtocolMajor >= 2)
|
||||||
{
|
{
|
||||||
@ -594,7 +594,7 @@ namespace NTwain
|
|||||||
/// <param name="session">The session.</param>
|
/// <param name="session">The session.</param>
|
||||||
/// <param name="useIt">if set to <c>true</c> [use it].</param>
|
/// <param name="useIt">if set to <c>true</c> [use it].</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public static ReturnCode CapSetFeeder(this TwainSession session, bool useIt)
|
public static ReturnCode CapSetFeeder(this ITwainSession session, bool useIt)
|
||||||
{
|
{
|
||||||
var rc = ReturnCode.Failure;
|
var rc = ReturnCode.Failure;
|
||||||
if (session.SupportedCaps.Contains(CapabilityId.CapFeederEnabled))
|
if (session.SupportedCaps.Contains(CapabilityId.CapFeederEnabled))
|
||||||
|
@ -12,7 +12,7 @@ namespace NTwain.Tests
|
|||||||
[ExpectedException(typeof(TwainStateException), "State check failed to throw.")]
|
[ExpectedException(typeof(TwainStateException), "State check failed to throw.")]
|
||||||
public void VerifyState_Throws_When_State_Is_Enforced()
|
public void VerifyState_Throws_When_State_Is_Enforced()
|
||||||
{
|
{
|
||||||
ITwainStateInternal session = new TwainSession(TWIdentity.Create(DataGroups.Image, new Version(1, 0), "test", "test", "test", "test"));
|
ITwainSessionInternal session = new TwainSession(TWIdentity.Create(DataGroups.Image, new Version(1, 0), "test", "test", "test", "test"));
|
||||||
session.EnforceState = true;
|
session.EnforceState = true;
|
||||||
session.ChangeState(4, false);
|
session.ChangeState(4, false);
|
||||||
|
|
||||||
@ -22,7 +22,7 @@ namespace NTwain.Tests
|
|||||||
[TestMethod]
|
[TestMethod]
|
||||||
public void VerifyState_No_Throws_When_State_Is_Not_Enforced()
|
public void VerifyState_No_Throws_When_State_Is_Not_Enforced()
|
||||||
{
|
{
|
||||||
ITwainStateInternal session = new TwainSession(TWIdentity.Create(DataGroups.Image, new Version(1, 0), "test", "test", "test", "test"));
|
ITwainSessionInternal session = new TwainSession(TWIdentity.Create(DataGroups.Image, new Version(1, 0), "test", "test", "test", "test"));
|
||||||
session.EnforceState = false;
|
session.EnforceState = false;
|
||||||
session.ChangeState(4, false);
|
session.ChangeState(4, false);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user