Added DG triplet placeholders.

This commit is contained in:
Eugene Wang
2018-11-13 19:30:58 -05:00
parent cad3e5d37f
commit 4d3690874d
17 changed files with 572 additions and 115 deletions

View File

@@ -13,11 +13,22 @@ namespace NetCoreConsole
.Build();
using (var session = new TwainSession(config))
{
session.PropertyChanged += Session_PropertyChanged;
var handle = IntPtr.Zero;
session.Open(ref handle);
}
}
Console.WriteLine("Hello World!");
private static void Session_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
var session = (TwainSession)sender;
if (e.PropertyName == "State")
{
Console.WriteLine($"State changed to {session.State}");
}
}
}
}

View File

@@ -27,14 +27,6 @@ using TW_UINT8 = System.Byte; // unsigned char
// http://www.mono-project.com/Interop_with_Native_Libraries (old)
// http://www.mono-project.com/docs/advanced/pinvoke/ (new url)
//////////////////////////////////
// Data structures that
// are passed to the TWAIN method
// are defined as classes to reduce
// ref/out in the low-level calls.
// Others continue to be structs.
//////////////////////////////////
namespace NTwain.Data
{
@@ -241,7 +233,7 @@ namespace NTwain.Data
TW_MEMREF _context;
[FieldOffset(520)] // not sure why it should be 520 but whatev
Int32 Recursive;
Int32 _recursive;
[FieldOffset(520)]
TW_BOOL _subdirectories;

View File

@@ -1419,8 +1419,8 @@ namespace NTwain.Data
/// </summary>
public bool Recursive
{
get { return _subdirectories == TwainConst.True; }
set { _subdirectories = value ? TwainConst.True : TwainConst.False; }
get { return _recursive == 1; }
set { _recursive = value ? 1 : 0; }
}
/// <summary>
@@ -1688,7 +1688,6 @@ namespace NTwain.Data
internal set { _supportedGroups = ((uint)value & 0xffff0000) | (0x0000ffff & _supportedGroups); }
}
public string Manufacturer
{
get { return _manufacturer; }

View File

@@ -21,10 +21,6 @@
<Version>4.0.0</Version>
</PropertyGroup>
<ItemGroup>
<Folder Include="Triplets\" />
</ItemGroup>
<ItemGroup>
<Compile Update="Resources\MsgText.Designer.cs">
<DesignTime>True</DesignTime>

View File

@@ -0,0 +1,12 @@
namespace NTwain.Triplets
{
public abstract class BaseTriplet
{
protected TwainSession session;
public BaseTriplet(TwainSession session)
{
this.session = session;
}
}
}

View File

@@ -0,0 +1,13 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace NTwain.Triplets
{
public partial class DGAudio : BaseTriplet
{
internal DGAudio(TwainSession session) : base(session) { }
}
}

View File

@@ -0,0 +1,27 @@
using NTwain.Data;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace NTwain.Triplets
{
public partial class Parent : BaseTriplet
{
internal Parent(TwainSession session) : base(session) { }
public ReturnCode OpenDSM(ref IntPtr hWnd)
{
var rc = NativeMethods.DsmWin32(session.Config.AppWin32, null, DataGroups.Control, DataArgumentType.Parent, Message.OpenDSM, ref hWnd);
if (rc == ReturnCode.Success) session.State = TwainState.DsmOpened;
return rc;
}
public ReturnCode CloseDSM(ref IntPtr hWnd)
{
var rc = NativeMethods.DsmWin32(session.Config.AppWin32, null, DataGroups.Control, DataArgumentType.Parent, Message.CloseDSM, ref hWnd);
if (rc == ReturnCode.Success) session.State = TwainState.DsmLoaded;
return rc;
}
}
}

View File

@@ -0,0 +1,15 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace NTwain.Triplets
{
public partial class DGControl : BaseTriplet
{
internal DGControl(TwainSession session) : base(session) { }
Parent _parent;
internal Parent Parent => _parent ?? (_parent = new Parent(session));
}
}

View File

@@ -0,0 +1,13 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace NTwain.Triplets
{
public partial class DGCustom : BaseTriplet
{
internal DGCustom(TwainSession session) : base(session) { }
}
}

View File

@@ -0,0 +1,13 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace NTwain.Triplets
{
public partial class DGImage : BaseTriplet
{
internal DGImage(TwainSession session) : base(session) { }
}
}

View File

@@ -0,0 +1,283 @@
using NTwain.Data;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
namespace NTwain.Triplets
{
static partial class NativeMethods
{
[DllImport(WinDsmDll, EntryPoint = EntryName)]
public static extern ReturnCode DsmWin32(
[In, Out]TW_IDENTITY origin,
[In, Out]TW_IDENTITY destination,
DataGroups dg,
DataArgumentType dat,
Message msg,
ref IntPtr data);
[DllImport(WinDsmDll, EntryPoint = EntryName)]
public static extern ReturnCode DsmWin32(
[In, Out]TW_IDENTITY origin,
[In, Out]TW_IDENTITY destination,
DataGroups dg,
DataArgumentType dat,
Message msg,
ref DataGroups data);
[DllImport(WinDsmDll, EntryPoint = EntryName)]
public static extern ReturnCode DsmWin32(
[In, Out]TW_IDENTITY origin,
[In, Out]TW_IDENTITY destination,
DataGroups dg,
DataArgumentType dat,
Message msg,
ref TW_AUDIOINFO data);
//[DllImport(DSM.WinDsmDll, EntryPoint = DSM.EntryName)]
//public static extern ReturnCode DsmWin32(
// [In, Out]TW_IDENTITY origin,
// [In, Out]TW_IDENTITY destination,
// DataGroups dg,
// DataArgumentType dat,
// Message msg,
// ref TWCapability data);
[DllImport(WinDsmDll, EntryPoint = EntryName)]
public static extern ReturnCode DsmWin32(
[In, Out]TW_IDENTITY origin,
[In, Out]TW_IDENTITY destination,
DataGroups dg,
DataArgumentType dat,
Message msg,
ref TW_CUSTOMDSDATA data);
[DllImport(WinDsmDll, EntryPoint = EntryName)]
public static extern ReturnCode DsmWin32(
[In, Out]TW_IDENTITY origin,
[In, Out]TW_IDENTITY destination,
DataGroups dg,
DataArgumentType dat,
Message msg,
ref TW_DEVICEEVENT data);
[DllImport(WinDsmDll, EntryPoint = EntryName)]
public static extern ReturnCode DsmWin32(
[In, Out]TW_IDENTITY origin,
[In, Out]TW_IDENTITY destination,
DataGroups dg,
DataArgumentType dat,
Message msg,
ref TW_CALLBACK data);
[DllImport(WinDsmDll, EntryPoint = EntryName)]
public static extern ReturnCode DsmWin32(
[In, Out]TW_IDENTITY origin,
[In, Out]TW_IDENTITY destination,
DataGroups dg,
DataArgumentType dat,
Message msg,
ref TW_CALLBACK2 data);
[DllImport(WinDsmDll, EntryPoint = EntryName)]
public static extern ReturnCode DsmWin32(
[In, Out]TW_IDENTITY origin,
[In, Out]TW_IDENTITY destination,
DataGroups dg,
DataArgumentType dat,
Message msg,
ref TW_ENTRYPOINT data);
[DllImport(WinDsmDll, EntryPoint = EntryName)]
public static extern ReturnCode DsmWin32(
[In, Out]TW_IDENTITY origin,
[In, Out]TW_IDENTITY destination,
DataGroups dg,
DataArgumentType dat,
Message msg,
ref TW_EVENT data);
[DllImport(WinDsmDll, EntryPoint = EntryName)]
public static extern ReturnCode DsmWin32(
[In, Out]TW_IDENTITY origin,
[In, Out]TW_IDENTITY destination,
DataGroups dg,
DataArgumentType dat,
Message msg,
ref TW_FILESYSTEM data);
[DllImport(WinDsmDll, EntryPoint = EntryName)]
public static extern ReturnCode DsmWin32(
[In, Out]TW_IDENTITY origin,
IntPtr zero,
DataGroups dg,
DataArgumentType dat,
Message msg,
[In, Out]TW_IDENTITY data);
[DllImport(WinDsmDll, EntryPoint = EntryName)]
public static extern ReturnCode DsmWin32(
[In, Out]TW_IDENTITY origin,
[In, Out]TW_IDENTITY destination,
DataGroups dg,
DataArgumentType dat,
Message msg,
ref TW_PASSTHRU data);
[DllImport(WinDsmDll, EntryPoint = EntryName)]
public static extern ReturnCode DsmWin32(
[In, Out]TW_IDENTITY origin,
[In, Out]TW_IDENTITY destination,
DataGroups dg,
DataArgumentType dat,
Message msg,
ref TW_PENDINGXFERS data);
[DllImport(WinDsmDll, EntryPoint = EntryName)]
public static extern ReturnCode DsmWin32(
[In, Out]TW_IDENTITY origin,
[In, Out]TW_IDENTITY destination,
DataGroups dg,
DataArgumentType dat,
Message msg,
ref TW_SETUPFILEXFER data);
[DllImport(WinDsmDll, EntryPoint = EntryName)]
public static extern ReturnCode DsmWin32(
[In, Out]TW_IDENTITY origin,
[In, Out]TW_IDENTITY destination,
DataGroups dg,
DataArgumentType dat,
Message msg,
ref TW_SETUPMEMXFER data);
[DllImport(WinDsmDll, EntryPoint = EntryName)]
public static extern ReturnCode DsmWin32(
[In, Out]TW_IDENTITY origin,
[In, Out]TW_IDENTITY destination,
DataGroups dg,
DataArgumentType dat,
Message msg,
ref TW_STATUSUTF8 data);
[DllImport(WinDsmDll, EntryPoint = EntryName)]
public static extern ReturnCode DsmWin32(
[In, Out]TW_IDENTITY origin,
[In, Out]TW_IDENTITY destination,
DataGroups dg,
DataArgumentType dat,
Message msg,
ref TW_USERINTERFACE data);
[DllImport(WinDsmDll, EntryPoint = EntryName)]
public static extern ReturnCode DsmWin32(
[In, Out]TW_IDENTITY origin,
[In, Out]TW_IDENTITY destination,
DataGroups dg,
DataArgumentType dat,
Message msg,
ref TW_CIECOLOR data);
[DllImport(WinDsmDll, EntryPoint = EntryName)]
public static extern ReturnCode DsmWin32(
[In, Out]TW_IDENTITY origin,
[In, Out]TW_IDENTITY destination,
DataGroups dg,
DataArgumentType dat,
Message msg,
ref TW_EXTIMAGEINFO data);
[DllImport(WinDsmDll, EntryPoint = EntryName)]
public static extern ReturnCode DsmWin32(
[In, Out]TW_IDENTITY origin,
[In, Out]TW_IDENTITY destination,
DataGroups dg,
DataArgumentType dat,
Message msg,
ref TW_FILTER data);
//[DllImport(DSM.WinDsmDll, EntryPoint = DSM.EntryName)]
//public static extern ReturnCode DsmWin32(
// [In, Out]TW_IDENTITY origin,
// [In, Out]TW_IDENTITY destination,
// DataGroups dg,
// DataArgumentType dat,
// Message msg,
// ref TWGrayResponse data);
[DllImport(WinDsmDll, EntryPoint = EntryName)]
public static extern ReturnCode DsmWin32(
[In, Out]TW_IDENTITY origin,
[In, Out]TW_IDENTITY destination,
DataGroups dg,
DataArgumentType dat,
Message msg,
ref TW_IMAGEINFO data);
[DllImport(WinDsmDll, EntryPoint = EntryName)]
public static extern ReturnCode DsmWin32(
[In, Out]TW_IDENTITY origin,
[In, Out]TW_IDENTITY destination,
DataGroups dg,
DataArgumentType dat,
Message msg,
ref TW_IMAGELAYOUT data);
[DllImport(WinDsmDll, EntryPoint = EntryName)]
public static extern ReturnCode DsmWin32(
[In, Out]TW_IDENTITY origin,
[In, Out]TW_IDENTITY destination,
DataGroups dg,
DataArgumentType dat,
Message msg,
ref TW_IMAGEMEMXFER data);
[DllImport(WinDsmDll, EntryPoint = EntryName)]
public static extern ReturnCode DsmWin32(
[In, Out]TW_IDENTITY origin,
[In, Out]TW_IDENTITY destination,
DataGroups dg,
DataArgumentType dat,
Message msg,
ref TW_JPEGCOMPRESSION data);
[DllImport(WinDsmDll, EntryPoint = EntryName)]
public static extern ReturnCode DsmWin32(
[In, Out]TW_IDENTITY origin,
[In, Out]TW_IDENTITY destination,
DataGroups dg,
DataArgumentType dat,
Message msg,
ref TW_PALETTE8 data);
//[DllImport(DSM.WinDsmDll, EntryPoint = DSM.EntryName)]
//public static extern ReturnCode DsmWin32(
// [In, Out]TW_IDENTITY origin,
// [In, Out]TW_IDENTITY destination,
// DataGroups dg,
// DataArgumentType dat,
// Message msg,
// ref TWRgbResponse data);
[DllImport(WinDsmDll, EntryPoint = EntryName)]
public static extern ReturnCode DsmWin32(
[In, Out]TW_IDENTITY origin,
[In, Out]TW_IDENTITY destination,
DataGroups dg,
DataArgumentType dat,
Message msg,
ref TW_STATUS data);
[DllImport(WinDsmDll, EntryPoint = EntryName)]
public static extern ReturnCode DsmWin32(
[In, Out]TW_IDENTITY origin,
[In, Out]TW_IDENTITY destination,
DataGroups dg,
DataArgumentType dat,
Message msg,
ref TW_MEMORY data);
}
}

View File

@@ -0,0 +1,18 @@
using NTwain.Data;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace NTwain.Triplets
{
static partial class NativeMethods
{
const string EntryName = "DSM_Entry";
const string WinDsmDll = "twaindsm.dll";
const string LinuxDsmDll = "/usr/local/lib/libtwaindsm.so";
const string MacDsmDll = "/Library/Frameworks/TWAINDSM.framework/TWAINDSM";
}
}

View File

@@ -13,9 +13,11 @@ namespace NTwain
{
internal TwainConfig() { }
public bool PreferLegacyDsm { get; internal set; }
//public bool PreferLegacyDsm { get; internal set; }
public ITW_IDENTITY App { get; internal set; }
internal TW_IDENTITY AppWin32 { get; set; }
internal TW_IDENTITY SrcWin32 { get; set; }
internal IMemoryManager MemoryManager { get; set; }
}

View File

@@ -26,20 +26,20 @@ namespace NTwain
_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 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.
@@ -101,7 +101,7 @@ namespace NTwain
/// <returns></returns>
public TwainConfig Build()
{
ITW_IDENTITY app = null;
var config = new TwainConfig();
// todo: change id based on platform
switch (_platform)
@@ -110,7 +110,7 @@ namespace NTwain
case PlatformID.Unix:
case PlatformID.MacOSX:
default:
app = new TW_IDENTITY
config.AppWin32 = new TW_IDENTITY
{
DataFunctionalities = DataFunctionalities.App2,
DataGroup = DataGroups.Control | _dg,
@@ -130,12 +130,7 @@ namespace NTwain
};
break;
}
return new TwainConfig
{
PreferLegacyDsm = _legacy,
App = app
};
return config;
}
}
}

View File

@@ -0,0 +1,52 @@
using NTwain.Data;
using NTwain.Triplets;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
namespace NTwain
{
partial class TwainSession : IDisposable
{
private bool disposedValue = false; // To detect redundant calls
/// <summary>
/// Handles actual disposal logic.
/// </summary>
/// <param name="disposing"></param>
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);
// }
/// <summary>
/// Closes any open TWAIN objects.
/// </summary>
public void Dispose()
{
Dispose(true);
// TODO: uncomment the following line if the finalizer is overridden above.
// GC.SuppressFinalize(this);
}
}
}

View File

@@ -0,0 +1,66 @@
using NTwain.Data;
using NTwain.Triplets;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
namespace NTwain
{
partial class TwainSession : INotifyPropertyChanged
{
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));
}
}
DGControl dgControl;
/// <summary>
/// Gets the triplet operations defined for control data group.
/// </summary>
public DGControl DGControl => dgControl ?? (dgControl = new DGControl(this));
DGImage dgImage;
/// <summary>
/// Gets the triplet operations defined for image data group.
/// </summary>
public DGImage DGImage => dgImage ?? (dgImage = new DGImage(this));
DGAudio dgAudio;
/// <summary>
/// Gets the triplet operations defined for audio data group.
/// </summary>
public DGAudio DGAudio => dgAudio ?? (dgAudio = new DGAudio(this));
/// <summary>
/// Gets/sets the direct triplet operation entry for custom values.
/// </summary>
public DGCustom DGCustom { get; set; }
/// <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>
protected void RaisePropertyChanged(string propertyName)
{
var handle = PropertyChanged;
handle?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
}

View File

@@ -1,4 +1,5 @@
using NTwain.Data;
using NTwain.Triplets;
using System;
using System.Collections.Generic;
using System.ComponentModel;
@@ -7,87 +8,36 @@ using System.Text;
namespace NTwain
{
public class TwainSession : INotifyPropertyChanged, IDisposable
public partial class TwainSession
{
private TwainConfig _config;
internal TwainConfig Config;
private IntPtr _hWnd;
public TwainSession(TwainConfig config)
{
_config = config;
var rc = Open();
if (rc != ReturnCode.Success)
Config = config;
}
public ReturnCode Open(ref IntPtr hWnd)
{
}
_hWnd = hWnd;
return DGControl.Parent.OpenDSM(ref hWnd);
}
private TwainState _state;
/// <summary>
/// Gets the logical state of the session.
/// </summary>
public TwainState State
public ReturnCode StepDown(TwainState targetState)
{
get { return _state; }
internal set
var rc = ReturnCode.Failure;
while (State > targetState)
{
_state = value;
RaisePropertyChanged(nameof(State));
}
}
public event PropertyChangedEventHandler PropertyChanged;
void RaisePropertyChanged(string property)
switch (State)
{
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;
case TwainState.DsmOpened:
rc = DGControl.Parent.CloseDSM(ref _hWnd);
if (rc != ReturnCode.Success) return rc;
break;
}
}
// 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
return rc;
}
}
}