diff --git a/src/NTwain/Data/TwainTypes.cs b/src/NTwain/Data/TwainTypes.cs index 2651c2e..f5137a1 100644 --- a/src/NTwain/Data/TwainTypes.cs +++ b/src/NTwain/Data/TwainTypes.cs @@ -540,10 +540,6 @@ namespace NTwain.Data TW_HANDLE _hParent; } - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - delegate ReturnCode CallbackDelegate(TW_IDENTITY origin, TW_IDENTITY destination, - DataGroups dg, DataArgumentType dat, Message msg, TW_MEMREF data); - [StructLayout(LayoutKind.Sequential, Pack = 2)] partial class TW_ENTRYPOINT { diff --git a/src/NTwain/DataSource.Props.cs b/src/NTwain/DataSource.Props.cs new file mode 100644 index 0000000..4036f80 --- /dev/null +++ b/src/NTwain/DataSource.Props.cs @@ -0,0 +1,62 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Text; +using NTwain.Data; + +namespace NTwain +{ + partial class DataSource : INotifyPropertyChanged + { + /// + /// Gets the source name. + /// + public string Name => Identity.ProductName; + + /// + /// Gets the source's manufacturer name. + /// + public string Manufacturer => Identity.Manufacturer; + + /// + /// Gets the source's product family. + /// + public string ProductFamily => Identity.ProductFamily; + + /// + /// Gets the source's version info. + /// + public TW_VERSION Version => Identity.Version; + + /// + /// Gets the supported data group. + /// + public DataGroups DataGroup => Identity.DataGroup; + + /// + /// Gets the supported TWAIN protocol version. + /// + public Version ProtocolVersion { get; } + + /// + /// Gets a value indicating whether this data source is open. + /// + public bool IsOpen => Session.State > TwainState.DsmOpened && Session.CurrentSource == this; + + /// + /// Occurs when a property value changes. + /// + public event PropertyChangedEventHandler PropertyChanged; + + /// + /// Raises the event. + /// + /// Name of the property. + internal protected void RaisePropertyChanged(string propertyName) + { + var handle = PropertyChanged; + handle?.Invoke(this, new PropertyChangedEventArgs(propertyName)); + } + } +} diff --git a/src/NTwain/DataSource.cs b/src/NTwain/DataSource.cs index c81b2ba..afd446c 100644 --- a/src/NTwain/DataSource.cs +++ b/src/NTwain/DataSource.cs @@ -9,7 +9,7 @@ namespace NTwain /// /// A TWAIN data source. /// - public class DataSource + public partial class DataSource { internal readonly TwainSession Session; @@ -22,43 +22,6 @@ namespace NTwain ProtocolVersion = new Version(src.ProtocolMajor, src.ProtocolMinor); } - /// - /// Gets the source name. - /// - public string Name => Identity.ProductName; - - /// - /// Gets the source's manufacturer name. - /// - public string Manufacturer => Identity.Manufacturer; - - /// - /// Gets the source's product family. - /// - public string ProductFamily => Identity.ProductFamily; - - /// - /// Gets the source's version info. - /// - public TW_VERSION Version => Identity.Version; - - /// - /// Gets the supported data group. - /// - public DataGroups DataGroup => Identity.DataGroup; - - /// - /// Gets the supported TWAIN protocol version. - /// - public Version ProtocolVersion { get; } - - /// - /// Gets a value indicating whether this data source is open. - /// - public bool IsOpen => Session.State > TwainState.DsmOpened && Session.CurrentSource == this; - - - /// /// Opens the source for capability negotiation. /// diff --git a/src/NTwain/Internals/LinuxMemoryManager.cs b/src/NTwain/Internals/LinuxMemoryManager.cs index 4ae8fdb..3254807 100644 --- a/src/NTwain/Internals/LinuxMemoryManager.cs +++ b/src/NTwain/Internals/LinuxMemoryManager.cs @@ -10,8 +10,6 @@ namespace NTwain.Internals class LinuxMemoryManager : IMemoryManager { - #region IMemoryManager Members - public IntPtr Allocate(uint size) { return Marshal.AllocHGlobal((int)size); @@ -32,6 +30,5 @@ namespace NTwain.Internals // no op } - #endregion } } diff --git a/src/NTwain/Internals/WinMemoryManager.cs b/src/NTwain/Internals/WinMemoryManager.cs index 7ce356d..a4dd1f5 100644 --- a/src/NTwain/Internals/WinMemoryManager.cs +++ b/src/NTwain/Internals/WinMemoryManager.cs @@ -40,22 +40,18 @@ namespace NTwain.Internals [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); + public static extern IntPtr WinGlobalAlloc(uint uFlags, UIntPtr dwBytes); [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")] - internal static extern IntPtr WinGlobalLock(IntPtr handle); + public static extern IntPtr WinGlobalLock(IntPtr handle); [DllImport("kernel32", SetLastError = true, EntryPoint = "GlobalUnlock")] [return: MarshalAs(UnmanagedType.Bool)] - internal static extern bool WinGlobalUnlock(IntPtr handle); - - #endregion + public static extern bool WinGlobalUnlock(IntPtr handle); } } } diff --git a/src/NTwain/Triplets/DGControl.Identity.cs b/src/NTwain/Triplets/DGControl.Identity.cs index 958db81..e66b028 100644 --- a/src/NTwain/Triplets/DGControl.Identity.cs +++ b/src/NTwain/Triplets/DGControl.Identity.cs @@ -44,6 +44,8 @@ namespace NTwain.Triplets public ReturnCode OpenDS(TW_IDENTITY source) { + Session.StepDown(TwainState.DsmOpened); + var rc = NativeMethods.DsmWin32(Session.Config.AppWin32, IntPtr.Zero, DataGroups.Control, DataArgumentType.Identity, Message.OpenDS, source); if (rc == ReturnCode.Success) diff --git a/src/NTwain/TwainSession.cs b/src/NTwain/TwainSession.cs index f4de1dd..63e36bb 100644 --- a/src/NTwain/TwainSession.cs +++ b/src/NTwain/TwainSession.cs @@ -11,6 +11,10 @@ using System.Threading; namespace NTwain { + //[UnmanagedFunctionPointer(CallingConvention.Cdecl)] + delegate ReturnCode CallbackDelegate(TW_IDENTITY origin, TW_IDENTITY destination, + DataGroups dg, DataArgumentType dat, Message msg, IntPtr data); + /// /// Manages a TWAIN session. /// @@ -24,6 +28,7 @@ namespace NTwain // need to keep delegate around to prevent GC? readonly CallbackDelegate _callbackDelegate; + /// /// Constructs a new . /// @@ -79,43 +84,36 @@ namespace NTwain internal void RegisterCallback() { - if (State == TwainState.S4) + var callbackPtr = Marshal.GetFunctionPointerForDelegate(_callbackDelegate); + + // try new callback first + var cb2 = new TW_CALLBACK2 { CallBackProc = callbackPtr }; + var rc = DGControl.Callback2.RegisterCallback(ref cb2); + if (rc == ReturnCode.Success) Debug.WriteLine("Registed Callback2 success."); + else { - var callbackPtr = Marshal.GetFunctionPointerForDelegate(_callbackDelegate); - var rc = ReturnCode.Failure; - // per the spec (8-10) apps for 2.2 or higher uses callback2 so try this first - if (Config.AppWin32.ProtocolMajor > 2 || - (Config.AppWin32.ProtocolMajor >= 2 && Config.AppWin32.ProtocolMinor >= 2)) + } + + + if (rc != ReturnCode.Success) + { + // always register old callback + var cb = new TW_CALLBACK { CallBackProc = callbackPtr }; + + rc = DGControl.Callback.RegisterCallback(ref cb); + + if (rc == ReturnCode.Success) Debug.WriteLine("Registed Callback success."); + else { - var cb = new TW_CALLBACK2 { CallBackProc = callbackPtr }; - rc = DGControl.Callback2.RegisterCallback(ref cb); - if (rc == ReturnCode.Success) Debug.WriteLine("Registed Callback2 success."); - else - { - } - } - - if (rc != ReturnCode.Success) - { - // always try old callback - var cb = new TW_CALLBACK { CallBackProc = callbackPtr }; - - rc = DGControl.Callback.RegisterCallback(ref cb); - - if (rc == ReturnCode.Success) Debug.WriteLine("Registed Callback success."); - else - { - - } } } } /// - /// Gets list of sources available on the machine. + /// Enumerate list of sources available on the machine. /// /// public IEnumerable GetSources() @@ -168,13 +166,25 @@ namespace NTwain return null; } + private DataSource _currentSource; + /// /// Gets the currently open data source. /// - /// - /// The current source. - /// - public DataSource CurrentSource { get; internal set; } + public DataSource CurrentSource + { + get { return _currentSource; } + internal set + { + var old = _currentSource; + _currentSource = value; + + RaisePropertyChanged(nameof(CurrentSource)); + old?.RaisePropertyChanged(nameof(DataSource.IsOpen)); + value?.RaisePropertyChanged(nameof(DataSource.IsOpen)); + } + } + internal DataSource GetSourceSingleton(TW_IDENTITY sourceId) { @@ -198,5 +208,16 @@ namespace NTwain HandleSourceMsg(msg); return ReturnCode.Success; } + + /// + /// Returns a that represents this instance. + /// + /// + /// A that represents this instance. + /// + public override string ToString() + { + return $"Session: {State}"; + } } }