mirror of
https://github.com/soukoku/ntwain.git
synced 2025-09-19 18:27:56 +08:00
Start experimenting with configuration builder-type initialization.
This commit is contained in:
76
src/NTwain/Data/TwainState.cs
Normal file
76
src/NTwain/Data/TwainState.cs
Normal file
@@ -0,0 +1,76 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace NTwain.Data
|
||||
{
|
||||
/// <summary>
|
||||
/// The logical state of a TWAIN session.
|
||||
/// </summary>
|
||||
public enum TwainState
|
||||
{
|
||||
/// <summary>
|
||||
/// Just a default value.
|
||||
/// </summary>
|
||||
Invalid = 0,
|
||||
/// <summary>
|
||||
/// The starting state, nothing loaded.
|
||||
/// </summary>
|
||||
S1 = 1,
|
||||
/// <summary>
|
||||
/// The DSM library has been loaded.
|
||||
/// </summary>
|
||||
S2 = 2,
|
||||
/// <summary>
|
||||
/// The DSM has been opened.
|
||||
/// </summary>
|
||||
S3 = 3,
|
||||
/// <summary>
|
||||
/// A data source has been opened, ready for configuration.
|
||||
/// </summary>
|
||||
S4 = 4,
|
||||
/// <summary>
|
||||
/// A data source has been enabled, GUI up or waiting to transfer first image.
|
||||
/// </summary>
|
||||
S5 = 5,
|
||||
/// <summary>
|
||||
/// Data is ready for transfer from the source.
|
||||
/// </summary>
|
||||
S6 = 6,
|
||||
/// <summary>
|
||||
/// Data is being transferred.
|
||||
/// </summary>
|
||||
S7 = 7,
|
||||
|
||||
/// <summary>
|
||||
/// The starting state, nothing loaded.
|
||||
/// </summary>
|
||||
DsmUnloaded = S1,
|
||||
/// <summary>
|
||||
/// The DSM library has been loaded.
|
||||
/// </summary>
|
||||
DsmLoaded = S2,
|
||||
/// <summary>
|
||||
/// The DSM has been opened.
|
||||
/// </summary>
|
||||
DsmOpened = S3,
|
||||
/// <summary>
|
||||
/// A data source has been opened, ready for configuration.
|
||||
/// </summary>
|
||||
SourceOpened = S4,
|
||||
/// <summary>
|
||||
/// A data source has been enabled, GUI up or waiting to transfer first image.
|
||||
/// </summary>
|
||||
SourceEnabled = S5,
|
||||
/// <summary>
|
||||
/// Data is ready for transfer from the source.
|
||||
/// </summary>
|
||||
TransferReady = S6,
|
||||
/// <summary>
|
||||
/// Data is being transferred.
|
||||
/// </summary>
|
||||
Transferring = S7
|
||||
}
|
||||
|
||||
}
|
39
src/NTwain/Internals/IMemoryManager.cs
Normal file
39
src/NTwain/Internals/IMemoryManager.cs
Normal file
@@ -0,0 +1,39 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace NTwain.Internals
|
||||
{
|
||||
/// <summary>
|
||||
/// Interface that provides the correct methods for managing memory on data exchanged with TWAIN sources.
|
||||
/// </summary>
|
||||
interface IMemoryManager
|
||||
{
|
||||
/// <summary>
|
||||
/// Function to allocate memory. Calls to this must be coupled with <see cref="Free"/> later.
|
||||
/// </summary>
|
||||
/// <param name="size">The size in bytes.</param>
|
||||
/// <returns>Handle to the allocated memory.</returns>
|
||||
IntPtr Allocate(uint size);
|
||||
|
||||
/// <summary>
|
||||
/// Function to free memory.
|
||||
/// </summary>
|
||||
/// <param name="handle">The handle from <see cref="Allocate"/>.</param>
|
||||
void Free(IntPtr handle);
|
||||
|
||||
/// <summary>
|
||||
/// Function to lock some memory. Calls to this must be coupled with <see cref="Unlock"/> later.
|
||||
/// </summary>
|
||||
/// <param name="handle">The handle to allocated memory.</param>
|
||||
/// <returns>Handle to the lock.</returns>
|
||||
IntPtr Lock(IntPtr handle);
|
||||
|
||||
/// <summary>
|
||||
/// Function to unlock a previously locked memory region.
|
||||
/// </summary>
|
||||
/// <param name="handle">The same handle passed <see cref="Lock"/>.</param>
|
||||
void Unlock(IntPtr handle);
|
||||
}
|
||||
}
|
37
src/NTwain/Internals/LinuxMemoryManager.cs
Normal file
37
src/NTwain/Internals/LinuxMemoryManager.cs
Normal file
@@ -0,0 +1,37 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
|
||||
namespace NTwain.Internals
|
||||
{
|
||||
// probably wrong
|
||||
|
||||
class LinuxMemoryManager : IMemoryManager
|
||||
{
|
||||
#region IMemoryManager Members
|
||||
|
||||
public IntPtr Allocate(uint size)
|
||||
{
|
||||
return Marshal.AllocHGlobal((int)size);
|
||||
}
|
||||
|
||||
public void Free(IntPtr handle)
|
||||
{
|
||||
Marshal.FreeHGlobal(handle);
|
||||
}
|
||||
|
||||
public IntPtr Lock(IntPtr handle)
|
||||
{
|
||||
return handle;
|
||||
}
|
||||
|
||||
public void Unlock(IntPtr handle)
|
||||
{
|
||||
// no op
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
61
src/NTwain/Internals/WinMemoryManager.cs
Normal file
61
src/NTwain/Internals/WinMemoryManager.cs
Normal file
@@ -0,0 +1,61 @@
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Security;
|
||||
|
||||
namespace NTwain.Internals
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides methods for managing memory on data exchanged with twain sources using old win32 methods.
|
||||
/// </summary>
|
||||
class WinMemoryManager : IMemoryManager
|
||||
{
|
||||
public IntPtr Allocate(uint size)
|
||||
{
|
||||
IntPtr retVal = UnsafeNativeMethods.WinGlobalAlloc(0x0040, new UIntPtr(size));
|
||||
|
||||
if (retVal == IntPtr.Zero)
|
||||
{
|
||||
throw new Win32Exception();
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
|
||||
public void Free(IntPtr handle)
|
||||
{
|
||||
UnsafeNativeMethods.WinGlobalFree(handle);
|
||||
}
|
||||
|
||||
public IntPtr Lock(IntPtr handle)
|
||||
{
|
||||
return UnsafeNativeMethods.WinGlobalLock(handle);
|
||||
}
|
||||
|
||||
public void Unlock(IntPtr handle)
|
||||
{
|
||||
UnsafeNativeMethods.WinGlobalUnlock(handle);
|
||||
}
|
||||
|
||||
|
||||
[SuppressUnmanagedCodeSecurity]
|
||||
static class UnsafeNativeMethods
|
||||
{
|
||||
#region mem stuff for twain 1.x
|
||||
|
||||
[DllImport("kernel32", SetLastError = true, EntryPoint = "GlobalAlloc")]
|
||||
internal static extern IntPtr WinGlobalAlloc(uint uFlags, UIntPtr dwBytes);
|
||||
|
||||
[DllImport("kernel32", SetLastError = true, EntryPoint = "GlobalFree")]
|
||||
internal static extern IntPtr WinGlobalFree(IntPtr hMem);
|
||||
|
||||
[DllImport("kernel32", SetLastError = true, EntryPoint = "GlobalLock")]
|
||||
internal static extern IntPtr WinGlobalLock(IntPtr handle);
|
||||
|
||||
[DllImport("kernel32", SetLastError = true, EntryPoint = "GlobalUnlock")]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
internal static extern bool WinGlobalUnlock(IntPtr handle);
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
}
|
113
src/NTwain/TwainConfig.cs
Normal file
113
src/NTwain/TwainConfig.cs
Normal file
@@ -0,0 +1,113 @@
|
||||
using NTwain.Data;
|
||||
using NTwain.Internals;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
|
||||
namespace NTwain
|
||||
{
|
||||
public class TwainConfig
|
||||
{
|
||||
internal TwainConfig() { }
|
||||
|
||||
public bool PreferLegacyDsm { get; internal set; }
|
||||
|
||||
public string AppName { get; internal set; }
|
||||
|
||||
internal DataGroups DataGroup { get; set; }
|
||||
internal IMemoryManager MemoryManager { get; set; }
|
||||
}
|
||||
|
||||
public class TwainConfigurationBuilder
|
||||
{
|
||||
private bool _legacy;
|
||||
private string _appName;
|
||||
private string _companyName;
|
||||
private DataGroups _dg = DataGroups.Image;
|
||||
private bool _64bit;
|
||||
private PlatformID _platform;
|
||||
|
||||
/// <summary>
|
||||
/// Default ctor.
|
||||
/// </summary>
|
||||
public TwainConfigurationBuilder()
|
||||
{
|
||||
_64bit = IntPtr.Size == 8;
|
||||
_platform = Environment.OSVersion.Platform;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Specifies which DSM to use.
|
||||
/// </summary>
|
||||
/// <param name="legacyDsm"></param>
|
||||
/// <returns></returns>
|
||||
public TwainConfigurationBuilder UseDsm(bool legacyDsm = false)
|
||||
{
|
||||
if (legacyDsm)
|
||||
{
|
||||
if (_64bit) throw new InvalidOperationException("Cannot use legacy DSM under 64bit.");
|
||||
}
|
||||
_legacy = legacyDsm;
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Specifies what kind of data the app can to handle from TWAIN devices.
|
||||
/// </summary>
|
||||
/// <param name="image"></param>
|
||||
/// <param name="audio"></param>
|
||||
/// <returns></returns>
|
||||
public TwainConfigurationBuilder HandlesDataType(bool image = true, bool audio = false)
|
||||
{
|
||||
DataGroups dg = DataGroups.None;
|
||||
if (image) dg |= DataGroups.Image;
|
||||
if (audio) dg |= DataGroups.Audio;
|
||||
|
||||
if (dg == DataGroups.None) throw new InvalidOperationException("No data type specified.");
|
||||
_dg = dg;
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Defines the app info that will interface with TWAIN.
|
||||
/// </summary>
|
||||
/// <param name="appName"></param>
|
||||
/// <param name="companyName"></param>
|
||||
/// <returns></returns>
|
||||
public TwainConfigurationBuilder DefineApp(string appName, string companyName = null)
|
||||
{
|
||||
_appName = appName;
|
||||
_companyName = companyName;
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Defines the app info that will interface with TWAIN.
|
||||
/// </summary>
|
||||
/// <param name="appAssembly">Assembly containing the app info.</param>
|
||||
/// <returns></returns>
|
||||
public TwainConfigurationBuilder DefineApp(Assembly appAssembly)
|
||||
{
|
||||
var info = FileVersionInfo.GetVersionInfo(appAssembly.Location);
|
||||
return DefineApp(info.ProductName, info.CompanyName);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Builds the final configuration object.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public TwainConfig Build()
|
||||
{
|
||||
return new TwainConfig
|
||||
{
|
||||
PreferLegacyDsm = _legacy,
|
||||
AppName = _appName,
|
||||
DataGroup = _dg
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
93
src/NTwain/TwainSession.cs
Normal file
93
src/NTwain/TwainSession.cs
Normal file
@@ -0,0 +1,93 @@
|
||||
using NTwain.Data;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace NTwain
|
||||
{
|
||||
public class TwainSession : INotifyPropertyChanged, IDisposable
|
||||
{
|
||||
private TwainConfig _config;
|
||||
public TwainSession(TwainConfig config)
|
||||
{
|
||||
_config = config;
|
||||
var rc = Open();
|
||||
if (rc != ReturnCode.Success)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private TwainState _state;
|
||||
/// <summary>
|
||||
/// Gets the logical state of the session.
|
||||
/// </summary>
|
||||
public TwainState State
|
||||
{
|
||||
get { return _state; }
|
||||
internal set
|
||||
{
|
||||
_state = value;
|
||||
RaisePropertyChanged(nameof(State));
|
||||
}
|
||||
}
|
||||
|
||||
public event PropertyChangedEventHandler PropertyChanged;
|
||||
void RaisePropertyChanged(string property)
|
||||
{
|
||||
var handle = PropertyChanged;
|
||||
handle?.Invoke(this, new PropertyChangedEventArgs(property));
|
||||
}
|
||||
|
||||
ReturnCode Open()
|
||||
{
|
||||
if (State < TwainState.DsmOpened)
|
||||
{
|
||||
|
||||
}
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
ReturnCode StepDown(TwainState targetState)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
#region IDisposable Support
|
||||
private bool disposedValue = false; // To detect redundant calls
|
||||
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
if (!disposedValue)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
StepDown(TwainState.DsmLoaded);
|
||||
// TODO: dispose managed state (managed objects).
|
||||
}
|
||||
|
||||
// TODO: free unmanaged resources (unmanaged objects) and override a finalizer below.
|
||||
// TODO: set large fields to null.
|
||||
|
||||
disposedValue = true;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: override a finalizer only if Dispose(bool disposing) above has code to free unmanaged resources.
|
||||
// ~TwainSession() {
|
||||
// // Do not change this code. Put cleanup code in Dispose(bool disposing) above.
|
||||
// Dispose(false);
|
||||
// }
|
||||
|
||||
// This code added to correctly implement the disposable pattern.
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
// TODO: uncomment the following line if the finalizer is overridden above.
|
||||
// GC.SuppressFinalize(this);
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user