Added source selection methods.

This commit is contained in:
Eugene Wang
2018-11-13 21:02:29 -05:00
parent 63526070f8
commit 485810d46f
11 changed files with 265 additions and 21 deletions

View File

@@ -15,6 +15,7 @@ namespace NetCoreConsole
.Build();
Console.WriteLine($"App = {(config.Is64Bit ? "64bit" : "32bit")}");
Console.WriteLine($"Platform = {config.Platform}");
Console.WriteLine();
using (var session = new TwainSession(config))
{
@@ -23,18 +24,33 @@ namespace NetCoreConsole
var handle = IntPtr.Zero;
if (session.Open(ref handle) == NTwain.Data.ReturnCode.Success)
{
Console.WriteLine("Available data sources:");
foreach (var src in session.GetSources())
{
Console.WriteLine($"\t{src}");
}
Console.WriteLine();
var defaultSrc = session.DefaultSource;
Console.WriteLine($"Default data source = {defaultSrc}");
Console.WriteLine();
var selectSrc = session.ShowSourceSelector();
Console.WriteLine($"Selected data source = {selectSrc}");
Console.WriteLine();
//session.DefaultSource = null;
}
}
Console.WriteLine("Test ended, press Enter to exit...");
Console.ReadLine();
}
catch (Exception ex)
{
Console.WriteLine("ERROR: " + ex.ToString());
}
Console.WriteLine("Test ended, press Enter to exit...");
Console.ReadLine();
}
private static void Session_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)

View File

@@ -310,7 +310,7 @@ namespace NTwain.Data
partial class TW_IDENTITY
{
// TODO: id needs to be 64bit in 64bit?
TW_UINT32 _id;
internal TW_UINT32 Id;
TW_VERSION _version;
TW_UINT16 _protocolMajor;
TW_UINT16 _protocolMinor;

View File

@@ -1584,7 +1584,8 @@ namespace NTwain.Data
/// </returns>
public override string ToString()
{
return string.Format(CultureInfo.InvariantCulture, "{0}.{1} {2}", Major, Minor, Info);
if (Info == null) return $"v{Major}.{Minor}";
return $"v{Major}.{Minor} ({Info})";
}
#region equals

45
src/NTwain/DataSource.cs Normal file
View File

@@ -0,0 +1,45 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NTwain.Data;
namespace NTwain
{
/// <summary>
/// A TWAIN data source.
/// </summary>
public class DataSource
{
internal readonly TwainSession Session;
internal TW_IDENTITY Identity { get; }
internal DataSource(TwainSession session, TW_IDENTITY src)
{
this.Session = session;
this.Identity = src;
}
/// <summary>
/// Gets the source name.
/// </summary>
public string Name => Identity.ProductName;
/// <summary>
/// Gets the source version info.
/// </summary>
public TW_VERSION Version => Identity.Version;
/// <summary>
/// Returns a <see cref="System.String"/> that represents this instance.
/// </summary>
/// <returns>
/// A <see cref="System.String"/> that represents this instance.
/// </returns>
public override string ToString()
{
return $"{Name} {Version}";
}
}
}

View File

@@ -1,12 +1,25 @@
namespace NTwain.Triplets
using System;
namespace NTwain.Triplets
{
/// <summary>
/// Base class for grouping triplet operations.
/// </summary>
public abstract class BaseTriplet
{
protected TwainSession session;
/// <summary>
/// Gets the associated <see cref="TwainSession"/>.
/// </summary>
protected readonly TwainSession Session;
public BaseTriplet(TwainSession session)
/// <summary>
/// Initializes a new instance of the <see cref="BaseTriplet" /> class.
/// </summary>
/// <param name="session">The session.</param>
/// <exception cref="System.ArgumentNullException"></exception>
protected BaseTriplet(TwainSession session)
{
this.session = session;
this.Session = session ?? throw new ArgumentNullException(nameof(session));
}
}
}

View File

@@ -13,7 +13,7 @@ namespace NTwain.Triplets
public ReturnCode Get(out TW_ENTRYPOINT entryPoint)
{
entryPoint = new TW_ENTRYPOINT();
return NativeMethods.DsmWin32(session.Config.AppWin32, null,
return NativeMethods.DsmWin32(Session.Config.AppWin32, null,
DataGroups.Control, DataArgumentType.EntryPoint, Message.Get, entryPoint);
}
}

View File

@@ -0,0 +1,70 @@
using NTwain.Data;
using NTwain.Internals;
using System;
namespace NTwain.Triplets
{
sealed class Identity : BaseTriplet
{
internal Identity(TwainSession session) : base(session) { }
public ReturnCode CloseDS(TW_IDENTITY source)
{
var rc = NativeMethods.DsmWin32(Session.Config.AppWin32, IntPtr.Zero,
DataGroups.Control, DataArgumentType.Identity, Message.CloseDS, source);
if (rc == ReturnCode.Success)
{
Session.State = TwainState.S3;
Session.CurrentSource = null;
}
return rc;
}
public ReturnCode GetDefault(out TW_IDENTITY source)
{
source = new TW_IDENTITY();
return NativeMethods.DsmWin32(Session.Config.AppWin32, IntPtr.Zero,
DataGroups.Control, DataArgumentType.Identity, Message.GetDefault, source);
}
public ReturnCode GetFirst(out TW_IDENTITY source)
{
source = new TW_IDENTITY();
return NativeMethods.DsmWin32(Session.Config.AppWin32, IntPtr.Zero,
DataGroups.Control, DataArgumentType.Identity, Message.GetFirst, source);
}
public ReturnCode GetNext(out TW_IDENTITY source)
{
source = new TW_IDENTITY();
return NativeMethods.DsmWin32(Session.Config.AppWin32, IntPtr.Zero,
DataGroups.Control, DataArgumentType.Identity, Message.GetNext, source);
}
public ReturnCode OpenDS(TW_IDENTITY source)
{
var rc = NativeMethods.DsmWin32(Session.Config.AppWin32, IntPtr.Zero,
DataGroups.Control, DataArgumentType.Identity, Message.OpenDS, source);
if (rc == ReturnCode.Success)
{
Session.CurrentSource = Session.GetSourceSingleton(source);
Session.State = TwainState.S4;
}
return rc;
}
public ReturnCode Set(DataSource source)
{
return NativeMethods.DsmWin32(Session.Config.AppWin32, IntPtr.Zero,
DataGroups.Control, DataArgumentType.Identity, Message.Set, source?.Identity);
}
public ReturnCode UserSelect(out TW_IDENTITY source)
{
source = new TW_IDENTITY();
return NativeMethods.DsmWin32(Session.Config.AppWin32, IntPtr.Zero,
DataGroups.Control, DataArgumentType.Identity, Message.UserSelect, source);
}
}
}

View File

@@ -12,20 +12,20 @@ namespace NTwain.Triplets
public ReturnCode OpenDSM(ref IntPtr hWnd)
{
var rc = NativeMethods.DsmWin32(session.Config.AppWin32, null,
var rc = NativeMethods.DsmWin32(Session.Config.AppWin32, null,
DataGroups.Control, DataArgumentType.Parent, Message.OpenDSM, ref hWnd);
if (rc == ReturnCode.Success)
{
session.State = TwainState.DsmOpened;
Session.State = TwainState.DsmOpened;
// if twain2 then get memory management functions
if ((session.Config.AppWin32.DataFunctionalities & DataFunctionalities.Dsm2) == DataFunctionalities.Dsm2)
if ((Session.Config.AppWin32.DataFunctionalities & DataFunctionalities.Dsm2) == DataFunctionalities.Dsm2)
{
TW_ENTRYPOINT entry;
rc = session.DGControl.EntryPoint.Get(out entry);
rc = Session.DGControl.EntryPoint.Get(out entry);
if (rc == ReturnCode.Success)
{
session.Config.MemoryManager = entry;
Session.Config.MemoryManager = entry;
}
else
{
@@ -38,9 +38,9 @@ namespace NTwain.Triplets
public ReturnCode CloseDSM(ref IntPtr hWnd)
{
var rc = NativeMethods.DsmWin32(session.Config.AppWin32, null, DataGroups.Control,
var rc = NativeMethods.DsmWin32(Session.Config.AppWin32, null, DataGroups.Control,
DataArgumentType.Parent, Message.CloseDSM, ref hWnd);
if (rc == ReturnCode.Success) session.State = TwainState.DsmLoaded;
if (rc == ReturnCode.Success) Session.State = TwainState.DsmLoaded;
return rc;
}
}

View File

@@ -14,9 +14,12 @@ namespace NTwain.Triplets
internal DGControl(TwainSession session) : base(session) { }
Parent _parent;
internal Parent Parent => _parent ?? (_parent = new Parent(session));
internal Parent Parent => _parent ?? (_parent = new Parent(Session));
EntryPoint _entryPoint;
internal EntryPoint EntryPoint => _entryPoint ?? (_entryPoint = new EntryPoint(session));
internal EntryPoint EntryPoint => _entryPoint ?? (_entryPoint = new EntryPoint(Session));
Identity _identity;
internal Identity Identity => _identity ?? (_identity = new Identity(Session));
}
}

View File

@@ -11,7 +11,7 @@ namespace NTwain
/// </summary>
public class TwainConfigBuilder
{
private bool _legacy;
//private bool _legacy;
private string _appName;
private Version _version;
private string _companyName;

View File

@@ -8,22 +8,41 @@ using System.Text;
namespace NTwain
{
/// <summary>
/// Manages a TWAIN session.
/// </summary>
public partial class TwainSession
{
internal TwainConfig Config;
internal readonly TwainConfig Config;
private IntPtr _hWnd;
// cache generated twain sources so if you get same source from same session it'll return the same object
readonly Dictionary<string, DataSource> _ownedSources = new Dictionary<string, DataSource>();
/// <summary>
/// Constructs a new <see cref="TwainSession"/>.
/// </summary>
/// <param name="config"></param>
public TwainSession(TwainConfig config)
{
Config = config;
}
/// <summary>
/// Opens the TWAIN session.
/// </summary>
/// <param name="hWnd"></param>
/// <returns></returns>
public ReturnCode Open(ref IntPtr hWnd)
{
_hWnd = hWnd;
return DGControl.Parent.OpenDSM(ref hWnd);
}
/// <summary>
/// Steps down to the target session state.
/// </summary>
/// <param name="targetState"></param>
/// <returns></returns>
public ReturnCode StepDown(TwainState targetState)
{
var rc = ReturnCode.Failure;
@@ -39,5 +58,82 @@ namespace NTwain
}
return rc;
}
/// <summary>
/// Gets list of sources available on the machine.
/// </summary>
/// <returns></returns>
public IEnumerable<DataSource> GetSources()
{
TW_IDENTITY srcId;
var rc = DGControl.Identity.GetFirst(out srcId);
while (rc == ReturnCode.Success)
{
yield return GetSourceSingleton(srcId);
rc = DGControl.Identity.GetNext(out srcId);
}
}
/// <summary>
/// Gets/sets the default data source.
/// </summary>
public DataSource DefaultSource
{
get
{
TW_IDENTITY src;
if (DGControl.Identity.GetDefault(out src) == ReturnCode.Success)
{
return GetSourceSingleton(src);
}
return null;
}
set
{
//if (value != null && value.Session != this)
//{
// throw new InvalidOperationException("Source is not from this session.");
//}
DGControl.Identity.Set(value);
RaisePropertyChanged(nameof(DefaultSource));
}
}
/// <summary>
/// Tries to show the built-in source selector dialog and return the selected source.
/// </summary>
/// <returns></returns>
public DataSource ShowSourceSelector()
{
TW_IDENTITY id;
if (DGControl.Identity.UserSelect(out id) == ReturnCode.Success)
{
return GetSourceSingleton(id);
}
return null;
}
/// <summary>
/// Gets the currently open data source.
/// </summary>
/// <value>
/// The current source.
/// </value>
public DataSource CurrentSource { get; internal set; }
internal DataSource GetSourceSingleton(TW_IDENTITY sourceId)
{
DataSource source = null;
var key = $"{sourceId.Id}|{sourceId.Manufacturer}|{sourceId.ProductFamily}|{sourceId.ProductName}";
if (_ownedSources.ContainsKey(key))
{
source = _ownedSources[key];
}
else
{
_ownedSources[key] = source = new DataSource(this, sourceId);
}
return source;
}
}
}