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}";
+ }
}
}