Made datasource implement INotifyPropertyChanged.

This commit is contained in:
Eugene Wang
2018-11-14 19:35:34 -05:00
parent 56bfc37c89
commit ffec4319b7
7 changed files with 121 additions and 84 deletions

View File

@@ -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
{

View File

@@ -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
{
/// <summary>
/// Gets the source name.
/// </summary>
public string Name => Identity.ProductName;
/// <summary>
/// Gets the source's manufacturer name.
/// </summary>
public string Manufacturer => Identity.Manufacturer;
/// <summary>
/// Gets the source's product family.
/// </summary>
public string ProductFamily => Identity.ProductFamily;
/// <summary>
/// Gets the source's version info.
/// </summary>
public TW_VERSION Version => Identity.Version;
/// <summary>
/// Gets the supported data group.
/// </summary>
public DataGroups DataGroup => Identity.DataGroup;
/// <summary>
/// Gets the supported TWAIN protocol version.
/// </summary>
public Version ProtocolVersion { get; }
/// <summary>
/// Gets a value indicating whether this data source is open.
/// </summary>
public bool IsOpen => Session.State > TwainState.DsmOpened && Session.CurrentSource == this;
/// <summary>
/// Occurs when a property value changes.
/// </summary>
public event PropertyChangedEventHandler PropertyChanged;
/// <summary>
/// Raises the <see cref="PropertyChanged"/> event.
/// </summary>
/// <param name="propertyName">Name of the property.</param>
internal protected void RaisePropertyChanged(string propertyName)
{
var handle = PropertyChanged;
handle?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
}

View File

@@ -9,7 +9,7 @@ namespace NTwain
/// <summary>
/// A TWAIN data source.
/// </summary>
public class DataSource
public partial class DataSource
{
internal readonly TwainSession Session;
@@ -22,43 +22,6 @@ namespace NTwain
ProtocolVersion = new Version(src.ProtocolMajor, src.ProtocolMinor);
}
/// <summary>
/// Gets the source name.
/// </summary>
public string Name => Identity.ProductName;
/// <summary>
/// Gets the source's manufacturer name.
/// </summary>
public string Manufacturer => Identity.Manufacturer;
/// <summary>
/// Gets the source's product family.
/// </summary>
public string ProductFamily => Identity.ProductFamily;
/// <summary>
/// Gets the source's version info.
/// </summary>
public TW_VERSION Version => Identity.Version;
/// <summary>
/// Gets the supported data group.
/// </summary>
public DataGroups DataGroup => Identity.DataGroup;
/// <summary>
/// Gets the supported TWAIN protocol version.
/// </summary>
public Version ProtocolVersion { get; }
/// <summary>
/// Gets a value indicating whether this data source is open.
/// </summary>
public bool IsOpen => Session.State > TwainState.DsmOpened && Session.CurrentSource == this;
/// <summary>
/// Opens the source for capability negotiation.
/// </summary>

View File

@@ -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
}
}

View File

@@ -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);
}
}
}

View File

@@ -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)

View File

@@ -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);
/// <summary>
/// Manages a TWAIN session.
/// </summary>
@@ -24,6 +28,7 @@ namespace NTwain
// need to keep delegate around to prevent GC?
readonly CallbackDelegate _callbackDelegate;
/// <summary>
/// Constructs a new <see cref="TwainSession"/>.
/// </summary>
@@ -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
{
}
}
}
}
/// <summary>
/// Gets list of sources available on the machine.
/// Enumerate list of sources available on the machine.
/// </summary>
/// <returns></returns>
public IEnumerable<DataSource> GetSources()
@@ -168,13 +166,25 @@ namespace NTwain
return null;
}
private DataSource _currentSource;
/// <summary>
/// Gets the currently open data source.
/// </summary>
/// <value>
/// The current source.
/// </value>
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;
}
/// <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 $"Session: {State}";
}
}
}