Made old session inherit the refactored version.

This commit is contained in:
soukoku
2014-04-05 20:14:19 -04:00
parent 0064db2c2d
commit 3dc90eff89
13 changed files with 472 additions and 936 deletions

View File

@@ -972,42 +972,42 @@ namespace NTwain.Data
Marshal.WriteByte(baseAddr, offset, 0); Marshal.WriteByte(baseAddr, offset, 0);
} }
} }
/// <summary> ///// <summary>
/// Writes unicode string value. ///// Writes unicode string value.
/// </summary> ///// </summary>
/// <param name="baseAddr"></param> ///// <param name="baseAddr"></param>
/// <param name="offset"></param> ///// <param name="offset"></param>
/// <param name="item"></param> ///// <param name="item"></param>
/// <param name="maxLength"></param> ///// <param name="maxLength"></param>
[EnvironmentPermissionAttribute(SecurityAction.LinkDemand)] //[EnvironmentPermissionAttribute(SecurityAction.LinkDemand)]
private void WriteUString(IntPtr baseAddr, int offset, string item, int maxLength) //private void WriteUString(IntPtr baseAddr, int offset, string item, int maxLength)
{ //{
if (string.IsNullOrEmpty(item)) // if (string.IsNullOrEmpty(item))
{ // {
// write zero // // write zero
Marshal.WriteInt16(baseAddr, offset, (char)0); // Marshal.WriteInt16(baseAddr, offset, (char)0);
} // }
else // else
{ // {
// use 2 bytes per char // // use 2 bytes per char
for (int i = 0; i < maxLength; i++) // for (int i = 0; i < maxLength; i++)
{ // {
if (i == item.Length) // if (i == item.Length)
{ // {
// string end reached, so write \0 and quit // // string end reached, so write \0 and quit
Marshal.WriteInt16(baseAddr, offset, (char)0); // Marshal.WriteInt16(baseAddr, offset, (char)0);
return; // return;
} // }
else // else
{ // {
Marshal.WriteInt16(baseAddr, offset, item[i]); // Marshal.WriteInt16(baseAddr, offset, item[i]);
offset += 2; // offset += 2;
} // }
} // }
// when ended normally also write \0 // // when ended normally also write \0
Marshal.WriteByte(baseAddr, offset, 0); // Marshal.WriteByte(baseAddr, offset, 0);
} // }
} //}
/// <summary> /// <summary>
/// Entry call for reading values. /// Entry call for reading values.
/// </summary> /// </summary>

View File

@@ -72,8 +72,8 @@
<Compile Include="Triplets\DGControl\DGControl.Callback2.cs" /> <Compile Include="Triplets\DGControl\DGControl.Callback2.cs" />
<Compile Include="Triplets\DGImage\DGImage.Filter.cs" /> <Compile Include="Triplets\DGImage\DGImage.Filter.cs" />
<Compile Include="Triplets\OpBase.cs" /> <Compile Include="Triplets\OpBase.cs" />
<Compile Include="Triplets\PInvokes.32bit.cs" /> <Compile Include="Triplets\PInvoke.Win32.cs" />
<Compile Include="Triplets\PInvokes.64bit.cs" /> <Compile Include="Triplets\PInvoke.Win64.cs" />
<Compile Include="TwainSessionExtensions.cs" /> <Compile Include="TwainSessionExtensions.cs" />
<Compile Include="TwainSessionBase.cs" /> <Compile Include="TwainSessionBase.cs" />
<Compile Include="TwainSessionWPF.cs" /> <Compile Include="TwainSessionWPF.cs" />
@@ -119,7 +119,7 @@
<Compile Include="Triplets\DGImage\DGImage.RgbResponse.cs" /> <Compile Include="Triplets\DGImage\DGImage.RgbResponse.cs" />
<Compile Include="Triplets\PInvoke.cs" /> <Compile Include="Triplets\PInvoke.cs" />
<Compile Include="TwainException.cs" /> <Compile Include="TwainException.cs" />
<Compile Include="TwainSession.cs" /> <Compile Include="TwainSessionOld.cs" />
<Compile Include="Values\DataValues.cs" /> <Compile Include="Values\DataValues.cs" />
<Compile Include="Values\SourceEnableMode.cs" /> <Compile Include="Values\SourceEnableMode.cs" />
<Compile Include="Values\TwainConst.cs" /> <Compile Include="Values\TwainConst.cs" />

View File

@@ -7,7 +7,7 @@ namespace NTwain.Triplets
{ {
static partial class PInvoke static partial class PInvoke
{ {
static partial class NativeMethods static partial class WinNativeMethods
{ {
[DllImport("twain_32", EntryPoint = "#1")] [DllImport("twain_32", EntryPoint = "#1")]
public static extern ReturnCode DsmEntry32( public static extern ReturnCode DsmEntry32(

View File

@@ -7,7 +7,7 @@ namespace NTwain.Triplets
{ {
static partial class PInvoke static partial class PInvoke
{ {
static partial class NativeMethods static partial class WinNativeMethods
{ {
[DllImport("twaindsm", EntryPoint = "#1")] [DllImport("twaindsm", EntryPoint = "#1")]
public static extern ReturnCode DsmEntry64( public static extern ReturnCode DsmEntry64(

View File

@@ -35,8 +35,8 @@ namespace NTwain.Triplets
Message msg, Message msg,
ref IntPtr data) ref IntPtr data)
{ {
if (Is64Bit) { return NativeMethods.DsmEntry64(origin, destination, dg, dat, msg, ref data); } if (Is64Bit) { return WinNativeMethods.DsmEntry64(origin, destination, dg, dat, msg, ref data); }
else { return NativeMethods.DsmEntry32(origin, destination, dg, dat, msg, ref data); } else { return WinNativeMethods.DsmEntry32(origin, destination, dg, dat, msg, ref data); }
} }
public static ReturnCode DsmEntry( public static ReturnCode DsmEntry(
@@ -47,8 +47,8 @@ namespace NTwain.Triplets
Message msg, Message msg,
ref uint data) ref uint data)
{ {
if (Is64Bit) { return NativeMethods.DsmEntry64(origin, destination, dg, dat, msg, ref data); } if (Is64Bit) { return WinNativeMethods.DsmEntry64(origin, destination, dg, dat, msg, ref data); }
else { return NativeMethods.DsmEntry32(origin, destination, dg, dat, msg, ref data); } else { return WinNativeMethods.DsmEntry32(origin, destination, dg, dat, msg, ref data); }
} }
public static ReturnCode DsmEntry( public static ReturnCode DsmEntry(
@@ -57,8 +57,8 @@ namespace NTwain.Triplets
Message msg, Message msg,
TWAudioInfo data) TWAudioInfo data)
{ {
if (Is64Bit) { return NativeMethods.DsmEntry64(origin, destination, DataGroups.Audio, DataArgumentType.AudioInfo, msg, data); } if (Is64Bit) { return WinNativeMethods.DsmEntry64(origin, destination, DataGroups.Audio, DataArgumentType.AudioInfo, msg, data); }
else { return NativeMethods.DsmEntry32(origin, destination, DataGroups.Audio, DataArgumentType.AudioInfo, msg, data); } else { return WinNativeMethods.DsmEntry32(origin, destination, DataGroups.Audio, DataArgumentType.AudioInfo, msg, data); }
} }
@@ -68,8 +68,8 @@ namespace NTwain.Triplets
Message msg, Message msg,
TWCapability data) TWCapability data)
{ {
if (Is64Bit) { return NativeMethods.DsmEntry64(origin, destination, DataGroups.Control, DataArgumentType.Capability, msg, data); } if (Is64Bit) { return WinNativeMethods.DsmEntry64(origin, destination, DataGroups.Control, DataArgumentType.Capability, msg, data); }
else { return NativeMethods.DsmEntry32(origin, destination, DataGroups.Control, DataArgumentType.Capability, msg, data); } else { return WinNativeMethods.DsmEntry32(origin, destination, DataGroups.Control, DataArgumentType.Capability, msg, data); }
} }
@@ -79,8 +79,8 @@ namespace NTwain.Triplets
Message msg, Message msg,
TWCustomDSData data) TWCustomDSData data)
{ {
if (Is64Bit) { return NativeMethods.DsmEntry64(origin, destination, DataGroups.Control, DataArgumentType.CustomDSData, msg, data); } if (Is64Bit) { return WinNativeMethods.DsmEntry64(origin, destination, DataGroups.Control, DataArgumentType.CustomDSData, msg, data); }
else { return NativeMethods.DsmEntry32(origin, destination, DataGroups.Control, DataArgumentType.CustomDSData, msg, data); } else { return WinNativeMethods.DsmEntry32(origin, destination, DataGroups.Control, DataArgumentType.CustomDSData, msg, data); }
} }
@@ -90,8 +90,8 @@ namespace NTwain.Triplets
Message msg, Message msg,
TWDeviceEvent data) TWDeviceEvent data)
{ {
if (Is64Bit) { return NativeMethods.DsmEntry64(origin, destination, DataGroups.Control, DataArgumentType.DeviceEvent, msg, data); } if (Is64Bit) { return WinNativeMethods.DsmEntry64(origin, destination, DataGroups.Control, DataArgumentType.DeviceEvent, msg, data); }
else { return NativeMethods.DsmEntry32(origin, destination, DataGroups.Control, DataArgumentType.DeviceEvent, msg, data); } else { return WinNativeMethods.DsmEntry32(origin, destination, DataGroups.Control, DataArgumentType.DeviceEvent, msg, data); }
} }
@@ -101,8 +101,8 @@ namespace NTwain.Triplets
Message msg, Message msg,
TWCallback data) TWCallback data)
{ {
if (Is64Bit) { return NativeMethods.DsmEntry64(origin, destination, DataGroups.Control, DataArgumentType.Callback, msg, data); } if (Is64Bit) { return WinNativeMethods.DsmEntry64(origin, destination, DataGroups.Control, DataArgumentType.Callback, msg, data); }
else { return NativeMethods.DsmEntry32(origin, destination, DataGroups.Control, DataArgumentType.Callback, msg, data); } else { return WinNativeMethods.DsmEntry32(origin, destination, DataGroups.Control, DataArgumentType.Callback, msg, data); }
} }
@@ -112,8 +112,8 @@ namespace NTwain.Triplets
Message msg, Message msg,
TWCallback2 data) TWCallback2 data)
{ {
if (Is64Bit) { return NativeMethods.DsmEntry64(origin, destination, DataGroups.Control, DataArgumentType.Callback, msg, data); } if (Is64Bit) { return WinNativeMethods.DsmEntry64(origin, destination, DataGroups.Control, DataArgumentType.Callback, msg, data); }
else { return NativeMethods.DsmEntry32(origin, destination, DataGroups.Control, DataArgumentType.Callback, msg, data); } else { return WinNativeMethods.DsmEntry32(origin, destination, DataGroups.Control, DataArgumentType.Callback, msg, data); }
} }
@@ -123,8 +123,8 @@ namespace NTwain.Triplets
Message msg, Message msg,
TWEntryPoint data) TWEntryPoint data)
{ {
if (Is64Bit) { return NativeMethods.DsmEntry64(origin, destination, DataGroups.Control, DataArgumentType.EntryPoint, msg, data); } if (Is64Bit) { return WinNativeMethods.DsmEntry64(origin, destination, DataGroups.Control, DataArgumentType.EntryPoint, msg, data); }
else { return NativeMethods.DsmEntry32(origin, destination, DataGroups.Control, DataArgumentType.EntryPoint, msg, data); } else { return WinNativeMethods.DsmEntry32(origin, destination, DataGroups.Control, DataArgumentType.EntryPoint, msg, data); }
} }
@@ -134,8 +134,8 @@ namespace NTwain.Triplets
Message msg, Message msg,
TWEvent data) TWEvent data)
{ {
if (Is64Bit) { return NativeMethods.DsmEntry64(origin, destination, DataGroups.Control, DataArgumentType.Event, msg, data); } if (Is64Bit) { return WinNativeMethods.DsmEntry64(origin, destination, DataGroups.Control, DataArgumentType.Event, msg, data); }
else { return NativeMethods.DsmEntry32(origin, destination, DataGroups.Control, DataArgumentType.Event, msg, data); } else { return WinNativeMethods.DsmEntry32(origin, destination, DataGroups.Control, DataArgumentType.Event, msg, data); }
} }
@@ -145,8 +145,8 @@ namespace NTwain.Triplets
Message msg, Message msg,
TWFileSystem data) TWFileSystem data)
{ {
if (Is64Bit) { return NativeMethods.DsmEntry64(origin, destination, DataGroups.Control, DataArgumentType.FileSystem, msg, data); } if (Is64Bit) { return WinNativeMethods.DsmEntry64(origin, destination, DataGroups.Control, DataArgumentType.FileSystem, msg, data); }
else { return NativeMethods.DsmEntry32(origin, destination, DataGroups.Control, DataArgumentType.FileSystem, msg, data); } else { return WinNativeMethods.DsmEntry32(origin, destination, DataGroups.Control, DataArgumentType.FileSystem, msg, data); }
} }
public static ReturnCode DsmEntry( public static ReturnCode DsmEntry(
@@ -154,8 +154,8 @@ namespace NTwain.Triplets
Message msg, Message msg,
TWIdentity data) TWIdentity data)
{ {
if (Is64Bit) { return NativeMethods.DsmEntry64(origin, IntPtr.Zero, DataGroups.Control, DataArgumentType.Identity, msg, data); } if (Is64Bit) { return WinNativeMethods.DsmEntry64(origin, IntPtr.Zero, DataGroups.Control, DataArgumentType.Identity, msg, data); }
else { return NativeMethods.DsmEntry32(origin, IntPtr.Zero, DataGroups.Control, DataArgumentType.Identity, msg, data); } else { return WinNativeMethods.DsmEntry32(origin, IntPtr.Zero, DataGroups.Control, DataArgumentType.Identity, msg, data); }
} }
@@ -165,8 +165,8 @@ namespace NTwain.Triplets
Message msg, Message msg,
TWPassThru data) TWPassThru data)
{ {
if (Is64Bit) { return NativeMethods.DsmEntry64(origin, destination, DataGroups.Control, DataArgumentType.PassThru, msg, data); } if (Is64Bit) { return WinNativeMethods.DsmEntry64(origin, destination, DataGroups.Control, DataArgumentType.PassThru, msg, data); }
else { return NativeMethods.DsmEntry32(origin, destination, DataGroups.Control, DataArgumentType.PassThru, msg, data); } else { return WinNativeMethods.DsmEntry32(origin, destination, DataGroups.Control, DataArgumentType.PassThru, msg, data); }
} }
@@ -176,8 +176,8 @@ namespace NTwain.Triplets
Message msg, Message msg,
TWPendingXfers data) TWPendingXfers data)
{ {
if (Is64Bit) { return NativeMethods.DsmEntry64(origin, destination, DataGroups.Control, DataArgumentType.PendingXfers, msg, data); } if (Is64Bit) { return WinNativeMethods.DsmEntry64(origin, destination, DataGroups.Control, DataArgumentType.PendingXfers, msg, data); }
else { return NativeMethods.DsmEntry32(origin, destination, DataGroups.Control, DataArgumentType.PendingXfers, msg, data); } else { return WinNativeMethods.DsmEntry32(origin, destination, DataGroups.Control, DataArgumentType.PendingXfers, msg, data); }
} }
@@ -187,8 +187,8 @@ namespace NTwain.Triplets
Message msg, Message msg,
TWSetupFileXfer data) TWSetupFileXfer data)
{ {
if (Is64Bit) { return NativeMethods.DsmEntry64(origin, destination, DataGroups.Control, DataArgumentType.SetupFileXfer, msg, data); } if (Is64Bit) { return WinNativeMethods.DsmEntry64(origin, destination, DataGroups.Control, DataArgumentType.SetupFileXfer, msg, data); }
else { return NativeMethods.DsmEntry32(origin, destination, DataGroups.Control, DataArgumentType.SetupFileXfer, msg, data); } else { return WinNativeMethods.DsmEntry32(origin, destination, DataGroups.Control, DataArgumentType.SetupFileXfer, msg, data); }
} }
@@ -198,8 +198,8 @@ namespace NTwain.Triplets
Message msg, Message msg,
TWSetupMemXfer data) TWSetupMemXfer data)
{ {
if (Is64Bit) { return NativeMethods.DsmEntry64(origin, destination, DataGroups.Control, DataArgumentType.SetupMemXfer, msg, data); } if (Is64Bit) { return WinNativeMethods.DsmEntry64(origin, destination, DataGroups.Control, DataArgumentType.SetupMemXfer, msg, data); }
else { return NativeMethods.DsmEntry32(origin, destination, DataGroups.Control, DataArgumentType.SetupMemXfer, msg, data); } else { return WinNativeMethods.DsmEntry32(origin, destination, DataGroups.Control, DataArgumentType.SetupMemXfer, msg, data); }
} }
@@ -209,8 +209,8 @@ namespace NTwain.Triplets
Message msg, Message msg,
TWStatusUtf8 data) TWStatusUtf8 data)
{ {
if (Is64Bit) { return NativeMethods.DsmEntry64(origin, destination, DataGroups.Control, DataArgumentType.StatusUtf8, msg, data); } if (Is64Bit) { return WinNativeMethods.DsmEntry64(origin, destination, DataGroups.Control, DataArgumentType.StatusUtf8, msg, data); }
else { return NativeMethods.DsmEntry32(origin, destination, DataGroups.Control, DataArgumentType.StatusUtf8, msg, data); } else { return WinNativeMethods.DsmEntry32(origin, destination, DataGroups.Control, DataArgumentType.StatusUtf8, msg, data); }
} }
@@ -220,8 +220,8 @@ namespace NTwain.Triplets
Message msg, Message msg,
TWUserInterface data) TWUserInterface data)
{ {
if (Is64Bit) { return NativeMethods.DsmEntry64(origin, destination, DataGroups.Control, DataArgumentType.UserInterface, msg, data); } if (Is64Bit) { return WinNativeMethods.DsmEntry64(origin, destination, DataGroups.Control, DataArgumentType.UserInterface, msg, data); }
else { return NativeMethods.DsmEntry32(origin, destination, DataGroups.Control, DataArgumentType.UserInterface, msg, data); } else { return WinNativeMethods.DsmEntry32(origin, destination, DataGroups.Control, DataArgumentType.UserInterface, msg, data); }
} }
@@ -231,8 +231,8 @@ namespace NTwain.Triplets
Message msg, Message msg,
TWCieColor data) TWCieColor data)
{ {
if (Is64Bit) { return NativeMethods.DsmEntry64(origin, destination, DataGroups.Image, DataArgumentType.CieColor, msg, data); } if (Is64Bit) { return WinNativeMethods.DsmEntry64(origin, destination, DataGroups.Image, DataArgumentType.CieColor, msg, data); }
else { return NativeMethods.DsmEntry32(origin, destination, DataGroups.Image, DataArgumentType.CieColor, msg, data); } else { return WinNativeMethods.DsmEntry32(origin, destination, DataGroups.Image, DataArgumentType.CieColor, msg, data); }
} }
@@ -242,8 +242,8 @@ namespace NTwain.Triplets
Message msg, Message msg,
TWExtImageInfo data) TWExtImageInfo data)
{ {
if (Is64Bit) { return NativeMethods.DsmEntry64(origin, destination, DataGroups.Image, DataArgumentType.ExtImageInfo, msg, data); } if (Is64Bit) { return WinNativeMethods.DsmEntry64(origin, destination, DataGroups.Image, DataArgumentType.ExtImageInfo, msg, data); }
else { return NativeMethods.DsmEntry32(origin, destination, DataGroups.Image, DataArgumentType.ExtImageInfo, msg, data); } else { return WinNativeMethods.DsmEntry32(origin, destination, DataGroups.Image, DataArgumentType.ExtImageInfo, msg, data); }
} }
public static ReturnCode DsmEntry( public static ReturnCode DsmEntry(
@@ -252,8 +252,8 @@ namespace NTwain.Triplets
Message msg, Message msg,
TWFilter data) TWFilter data)
{ {
if (Is64Bit) { return NativeMethods.DsmEntry64(origin, destination, DataGroups.Image, DataArgumentType.Filter, msg, data); } if (Is64Bit) { return WinNativeMethods.DsmEntry64(origin, destination, DataGroups.Image, DataArgumentType.Filter, msg, data); }
else { return NativeMethods.DsmEntry32(origin, destination, DataGroups.Image, DataArgumentType.Filter, msg, data); } else { return WinNativeMethods.DsmEntry32(origin, destination, DataGroups.Image, DataArgumentType.Filter, msg, data); }
} }
public static ReturnCode DsmEntry( public static ReturnCode DsmEntry(
@@ -262,8 +262,8 @@ namespace NTwain.Triplets
Message msg, Message msg,
TWGrayResponse data) TWGrayResponse data)
{ {
if (Is64Bit) { return NativeMethods.DsmEntry64(origin, destination, DataGroups.Image, DataArgumentType.GrayResponse, msg, data); } if (Is64Bit) { return WinNativeMethods.DsmEntry64(origin, destination, DataGroups.Image, DataArgumentType.GrayResponse, msg, data); }
else { return NativeMethods.DsmEntry32(origin, destination, DataGroups.Image, DataArgumentType.GrayResponse, msg, data); } else { return WinNativeMethods.DsmEntry32(origin, destination, DataGroups.Image, DataArgumentType.GrayResponse, msg, data); }
} }
@@ -273,8 +273,8 @@ namespace NTwain.Triplets
Message msg, Message msg,
TWImageInfo data) TWImageInfo data)
{ {
if (Is64Bit) { return NativeMethods.DsmEntry64(origin, destination, DataGroups.Image, DataArgumentType.ImageInfo, msg, data); } if (Is64Bit) { return WinNativeMethods.DsmEntry64(origin, destination, DataGroups.Image, DataArgumentType.ImageInfo, msg, data); }
else { return NativeMethods.DsmEntry32(origin, destination, DataGroups.Image, DataArgumentType.ImageInfo, msg, data); } else { return WinNativeMethods.DsmEntry32(origin, destination, DataGroups.Image, DataArgumentType.ImageInfo, msg, data); }
} }
@@ -284,8 +284,8 @@ namespace NTwain.Triplets
Message msg, Message msg,
TWImageLayout data) TWImageLayout data)
{ {
if (Is64Bit) { return NativeMethods.DsmEntry64(origin, destination, DataGroups.Image, DataArgumentType.ImageLayout, msg, data); } if (Is64Bit) { return WinNativeMethods.DsmEntry64(origin, destination, DataGroups.Image, DataArgumentType.ImageLayout, msg, data); }
else { return NativeMethods.DsmEntry32(origin, destination, DataGroups.Image, DataArgumentType.ImageLayout, msg, data); } else { return WinNativeMethods.DsmEntry32(origin, destination, DataGroups.Image, DataArgumentType.ImageLayout, msg, data); }
} }
@@ -295,8 +295,8 @@ namespace NTwain.Triplets
Message msg, Message msg,
TWImageMemXfer data) TWImageMemXfer data)
{ {
if (Is64Bit) { return NativeMethods.DsmEntry64(origin, destination, DataGroups.Image, DataArgumentType.ImageMemXfer, msg, data); } if (Is64Bit) { return WinNativeMethods.DsmEntry64(origin, destination, DataGroups.Image, DataArgumentType.ImageMemXfer, msg, data); }
else { return NativeMethods.DsmEntry32(origin, destination, DataGroups.Image, DataArgumentType.ImageMemXfer, msg, data); } else { return WinNativeMethods.DsmEntry32(origin, destination, DataGroups.Image, DataArgumentType.ImageMemXfer, msg, data); }
} }
@@ -306,8 +306,8 @@ namespace NTwain.Triplets
Message msg, Message msg,
TWJpegCompression data) TWJpegCompression data)
{ {
if (Is64Bit) { return NativeMethods.DsmEntry64(origin, destination, DataGroups.Image, DataArgumentType.JpegCompression, msg, data); } if (Is64Bit) { return WinNativeMethods.DsmEntry64(origin, destination, DataGroups.Image, DataArgumentType.JpegCompression, msg, data); }
else { return NativeMethods.DsmEntry32(origin, destination, DataGroups.Image, DataArgumentType.JpegCompression, msg, data); } else { return WinNativeMethods.DsmEntry32(origin, destination, DataGroups.Image, DataArgumentType.JpegCompression, msg, data); }
} }
@@ -317,8 +317,8 @@ namespace NTwain.Triplets
Message msg, Message msg,
TWPalette8 data) TWPalette8 data)
{ {
if (Is64Bit) { return NativeMethods.DsmEntry64(origin, destination, DataGroups.Image, DataArgumentType.Palette8, msg, data); } if (Is64Bit) { return WinNativeMethods.DsmEntry64(origin, destination, DataGroups.Image, DataArgumentType.Palette8, msg, data); }
else { return NativeMethods.DsmEntry32(origin, destination, DataGroups.Image, DataArgumentType.Palette8, msg, data); } else { return WinNativeMethods.DsmEntry32(origin, destination, DataGroups.Image, DataArgumentType.Palette8, msg, data); }
} }
@@ -328,8 +328,8 @@ namespace NTwain.Triplets
Message msg, Message msg,
TWRgbResponse data) TWRgbResponse data)
{ {
if (Is64Bit) { return NativeMethods.DsmEntry64(origin, destination, DataGroups.Image, DataArgumentType.RgbResponse, msg, data); } if (Is64Bit) { return WinNativeMethods.DsmEntry64(origin, destination, DataGroups.Image, DataArgumentType.RgbResponse, msg, data); }
else { return NativeMethods.DsmEntry32(origin, destination, DataGroups.Image, DataArgumentType.RgbResponse, msg, data); } else { return WinNativeMethods.DsmEntry32(origin, destination, DataGroups.Image, DataArgumentType.RgbResponse, msg, data); }
} }
@@ -339,8 +339,8 @@ namespace NTwain.Triplets
Message msg, Message msg,
TWStatus data) TWStatus data)
{ {
if (Is64Bit) { return NativeMethods.DsmEntry64(origin, destination, DataGroups.Control, DataArgumentType.Status, msg, data); } if (Is64Bit) { return WinNativeMethods.DsmEntry64(origin, destination, DataGroups.Control, DataArgumentType.Status, msg, data); }
else { return NativeMethods.DsmEntry32(origin, destination, DataGroups.Control, DataArgumentType.Status, msg, data); } else { return WinNativeMethods.DsmEntry32(origin, destination, DataGroups.Control, DataArgumentType.Status, msg, data); }
} }
@@ -351,8 +351,8 @@ namespace NTwain.Triplets
Message msg, Message msg,
ref TWMemory data) ref TWMemory data)
{ {
if (Is64Bit) { return NativeMethods.DsmEntry64(origin, destination, DataGroups.Control, dat, msg, ref data); } if (Is64Bit) { return WinNativeMethods.DsmEntry64(origin, destination, DataGroups.Control, dat, msg, ref data); }
else { return NativeMethods.DsmEntry32(origin, destination, DataGroups.Control, dat, msg, ref data); } else { return WinNativeMethods.DsmEntry32(origin, destination, DataGroups.Control, dat, msg, ref data); }
} }

View File

@@ -1,791 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NTwain.Triplets;
using NTwain.Data;
using NTwain.Values;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using System.Windows.Interop;
using System.Diagnostics;
using System.Security.Permissions;
using System.IO;
using System.ComponentModel;
using System.Threading;
namespace NTwain
{
/// <summary>
/// Provides a session for working with TWAIN api in an application.
/// </summary>
public class TwainSession : ITwainStateInternal, IMessageFilter, INotifyPropertyChanged
{
/// <summary>
/// Initializes a new instance of the <see cref="TwainSession" /> class.
/// </summary>
/// <param name="appId">The app id.</param>
/// <exception cref="System.ArgumentNullException"></exception>
public TwainSession(TWIdentity appId)
{
if (appId == null) { throw new ArgumentNullException("appId"); }
_appId = appId;
State = 1;
EnforceState = true;
}
#region properties
object _callbackObj;
SynchronizationContext _syncer;
TWIdentity _appId;
/// <summary>
/// Gets the app id used for the session.
/// </summary>
/// <value>The app id.</value>
TWIdentity ITwainStateInternal.GetAppId() { return _appId; }
/// <summary>
/// Gets the source id used for the session.
/// </summary>
/// <value>The source id.</value>
public TWIdentity SourceId { get; private set; }
/// <summary>
/// Gets the current state number as defined by the TWAIN spec.
/// </summary>
/// <value>The state.</value>
public int State { get; private set; }
/// <summary>
/// Gets or sets a value indicating whether callback is used parts of source communication
/// if supported. May be required if things don't work. This does not take effect if
/// the source is already open.
/// </summary>
/// <value>
/// <c>true</c> to disable callback; otherwise, <c>false</c>.
/// </value>
public bool DisableCallback { get; set; }
/// <summary>
/// Gets or sets a value indicating whether calls to triplets will verify the current twain session state.
/// </summary>
/// <value>
/// <c>true</c> if state value is enforced; otherwise, <c>false</c>.
/// </value>
public bool EnforceState { get; set; }
DGAudio _dgAudio;
/// <summary>
/// Gets the triplet operations defined for audio data group.
/// </summary>
/// <value>The DG audio.</value>
public DGAudio DGAudio
{
get
{
if (_dgAudio == null) { _dgAudio = new DGAudio(this); }
return _dgAudio;
}
}
DGControl _dgControl;
/// <summary>
/// Gets the triplet operations defined for control data group.
/// </summary>
/// <value>The DG control.</value>
public DGControl DGControl
{
get
{
if (_dgControl == null) { _dgControl = new DGControl(this); }
return _dgControl;
}
}
DGImage _dgImage;
/// <summary>
/// Gets the triplet operations defined for image data group.
/// </summary>
/// <value>The DG image.</value>
public DGImage DGImage
{
get
{
if (_dgImage == null) { _dgImage = new DGImage(this); }
return _dgImage;
}
}
private IList<CapabilityId> _supportedCaps;
/// <summary>
/// Gets the supported caps for the current source.
/// </summary>
/// <value>
/// The supported caps.
/// </value>
public IList<CapabilityId> SupportedCaps
{
get
{
if (_supportedCaps == null && State > 3)
{
_supportedCaps = this.GetCapabilities();
}
return _supportedCaps ?? new CapabilityId[0];
}
private set
{
_supportedCaps = value;
RaisePropertyChanged("SupportedCaps");
}
}
#endregion
#region state transition calls
void ITwainStateInternal.ChangeState(int newState, bool notifyChange)
{
Debug.WriteLine("TWAIN State = " + newState);
State = newState;
if (notifyChange) { RaisePropertyChanged("State"); }
}
ICommitable ITwainStateInternal.GetPendingStateChanger(int newState)
{
return new TentativeStateCommitable(this, newState);
}
void ITwainStateInternal.ChangeSourceId(TWIdentity sourceId)
{
SourceId = sourceId;
RaisePropertyChanged("SourceId");
}
HandleRef _parentHandle;
/// <summary>
/// Opens the data source manager.
/// </summary>
/// <param name="handle">The handle. On Windows = points to the window handle (hWnd) that will act as the Sources
/// "parent". On Macintosh = should be a NULL value.</param>
/// <returns></returns>
public ReturnCode OpenManager(HandleRef handle)
{
Debug.WriteLine(string.Format("Thread {0}: OpenManager.", Thread.CurrentThread.ManagedThreadId));
_parentHandle = handle;
var rc = DGControl.Parent.OpenDsm(handle.Handle);
if (rc == ReturnCode.Success)
{
// if twain2 then get mem management stuff
if ((_appId.DataFunctionalities & DataFunctionalities.Dsm2) == DataFunctionalities.Dsm2)
{
TWEntryPoint entry;
rc = DGControl.EntryPoint.Get(out entry);
if (rc == ReturnCode.Success)
{
MemoryManager.Instance.UpdateEntryPoint(entry);
Debug.WriteLine("Using TWAIN2 memory functions.");
}
else
{
CloseManager();
}
}
}
return rc;
}
/// <summary>
/// Closes the data source manager.
/// </summary>
/// <returns></returns>
public ReturnCode CloseManager()
{
Debug.WriteLine(string.Format("Thread {0}: CloseManager.", Thread.CurrentThread.ManagedThreadId));
var rc = DGControl.Parent.CloseDsm(_parentHandle.Handle);
if (rc == ReturnCode.Success)
{
_parentHandle = default(HandleRef);
MemoryManager.Instance.UpdateEntryPoint(null);
}
return rc;
}
/// <summary>
/// Loads the specified source into main memory and causes its initialization.
/// </summary>
/// <param name="sourceProductName">Name of the source.</param>
/// <returns></returns>
public ReturnCode OpenSource(string sourceProductName)
{
var source = new TWIdentity();
source.ProductName = sourceProductName;
return OpenSource(source);
}
/// <summary>
/// Loads the specified Source into main memory and causes its initialization.
/// </summary>
/// <param name="sourceId">The source id.</param>
/// <returns></returns>
public ReturnCode OpenSource(TWIdentity sourceId)
{
if (sourceId == null) { throw new ArgumentNullException("sourceId"); }
Debug.WriteLine(string.Format("Thread {0}: OpenSource.", Thread.CurrentThread.ManagedThreadId));
var rc = DGControl.Identity.OpenDS(sourceId);
if (rc == ReturnCode.Success)
{
SupportedCaps = this.GetCapabilities();
// TODO: does it work?
_syncer = SynchronizationContext.Current ?? new SynchronizationContext();
if (!DisableCallback)
{
// app v2.2 or higher uses callback2
if (_appId.ProtocolMajor >= 2 && _appId.ProtocolMinor >= 2)
{
var cb = new TWCallback2(CallbackHandler);
var rc2 = DGControl.Callback2.RegisterCallback(cb);
if (rc2 == ReturnCode.Success)
{
Debug.WriteLine("Registered callback2.");
_callbackObj = cb;
}
}
else
{
var cb = new TWCallback(CallbackHandler);
var rc2 = DGControl.Callback.RegisterCallback(cb);
if (rc2 == ReturnCode.Success)
{
Debug.WriteLine("Registered callback.");
_callbackObj = cb;
}
}
}
}
return rc;
}
ReturnCode CallbackHandler(TWIdentity origin, TWIdentity dest,
DataGroups dg, DataArgumentType dat, Values.Message msg, IntPtr data)
{
if (origin != null && SourceId != null && origin.Id == SourceId.Id)
{
Debug.WriteLine(string.Format("Thread {0}: GOT TWAIN callback for msg {1}.", Thread.CurrentThread.ManagedThreadId, msg));
// spec says should handle this on the thread that enabled the DS,
// but it's already the same and doesn't work (failure + seqError) w/o jumping to another thread and back.
// My guess is the DS needs to see the Success first before letting transfer happen
// so this is an artificial delay to make it happen.
// TODO: find a better method.
ThreadPool.QueueUserWorkItem(o =>
{
_syncer.Send(blah =>
{
HandleSourceMsg(origin, dest, dg, dat, msg, data);
}, null);
}, null);
return ReturnCode.Success;
}
return ReturnCode.Failure;
}
/// <summary>
/// When an application is finished with a Source, it must formally close the session between them
/// using this operation. This is necessary in case the Source only supports connection with a single
/// application (many desktop scanners will behave this way). A Source such as this cannot be
/// accessed by other applications until its current session is terminated
/// </summary>
/// <returns></returns>
public ReturnCode CloseSource()
{
Debug.WriteLine(string.Format("Thread {0}: CloseSource.", Thread.CurrentThread.ManagedThreadId));
var rc = DGControl.Identity.CloseDS();
if (rc == ReturnCode.Success)
{
_callbackObj = null;
SupportedCaps = null;
}
return rc;
}
TWUserInterface _twui;
/// <summary>
/// Enables the source for data acquisition.
/// </summary>
/// <param name="mode">The mode.</param>
/// <param name="modal">if set to <c>true</c> any driver UI will display as modal.</param>
/// <param name="windowHandle">The window handle if modal.</param>
/// <returns></returns>
public ReturnCode EnableSource(SourceEnableMode mode, bool modal, HandleRef windowHandle)
{
Debug.WriteLine(string.Format("Thread {0}: EnableSource.", Thread.CurrentThread.ManagedThreadId));
_twui = new TWUserInterface();
_twui.ShowUI = mode == SourceEnableMode.ShowUI;
_twui.ModalUI = modal;
_twui.hParent = windowHandle.Handle;
if (mode == SourceEnableMode.ShowUIOnly)
{
return DGControl.UserInterface.EnableDSUIOnly(_twui);
}
else
{
return DGControl.UserInterface.EnableDS(_twui);
}
}
/// <summary>
/// Disables the source to end data acquisition.
/// </summary>
/// <returns></returns>
ReturnCode DisableSource()
{
Debug.WriteLine(string.Format("Thread {0}: DisableSource.", Thread.CurrentThread.ManagedThreadId));
var rc = DGControl.UserInterface.DisableDS(_twui);
if (rc == ReturnCode.Success)
{
var hand = SourceDisabled;
if (hand != null)
{
try
{
hand(this, EventArgs.Empty);
}
catch { }
}
}
return rc;
}
#endregion
#region consumer to handle
/// <summary>
/// Occurs when source has been disabled (back to state 4).
/// </summary>
public event EventHandler SourceDisabled;
/// <summary>
/// Occurs when a data transfer is ready.
/// </summary>
public event EventHandler<TransferReadyEventArgs> TransferReady;
/// <summary>
/// Occurs when the source has generated an event.
/// </summary>
public event EventHandler<DeviceEventArgs> DeviceEvent;
/// <summary>
/// Occurs when data has been transferred.
/// </summary>
public event EventHandler<DataTransferredEventArgs> DataTransferred;
private void DoTransferRoutine()
{
TWPendingXfers pending = new TWPendingXfers();
var rc = ReturnCode.Success;
do
{
IList<FileFormat> formats = Enumerable.Empty<FileFormat>().ToList();
IList<Compression> compressions = Enumerable.Empty<Compression>().ToList();
bool canDoFileXfer = this.CapGetImageXferMech().Contains(XferMech.File);
var curFormat = this.GetCurrentCap<FileFormat>(CapabilityId.ICapImageFileFormat);
var curComp = this.GetCurrentCap<Compression>(CapabilityId.ICapCompression);
TWImageInfo imgInfo;
bool skip = false;
if (DGImage.ImageInfo.Get(out imgInfo) != ReturnCode.Success)
{
// bad!
skip = true;
}
try
{
formats = this.CapGetImageFileFormat();
}
catch { }
try
{
compressions = this.CapGetCompression();
}
catch { }
// ask consumer for cancel in case of non-ui multi-page transfers
TransferReadyEventArgs args = new TransferReadyEventArgs(pending, formats, curFormat, compressions,
curComp, canDoFileXfer, imgInfo);
args.CancelCurrent = skip;
var hand = TransferReady;
if (hand != null)
{
try
{
hand(this, args);
}
catch { }
}
if (!args.CancelAll && !args.CancelCurrent)
{
Values.XferMech mech = this.GetCurrentCap<XferMech>(CapabilityId.ICapXferMech);
if (args.CanDoFileXfer && !string.IsNullOrEmpty(args.OutputFile))
{
var setXferRC = DGControl.SetupFileXfer.Set(new TWSetupFileXfer
{
FileName = args.OutputFile,
Format = args.ImageFormat
});
if (setXferRC == ReturnCode.Success)
{
mech = XferMech.File;
}
}
// I don't know how this is supposed to work so it probably doesn't
//this.CapSetImageFormat(args.ImageFormat);
//this.CapSetImageCompression(args.ImageCompression);
#region do xfer
// TODO: expose all swallowed exceptions somehow later
IntPtr dataPtr = IntPtr.Zero;
IntPtr lockedPtr = IntPtr.Zero;
string file = null;
try
{
ReturnCode xrc = ReturnCode.Cancel;
switch (mech)
{
case Values.XferMech.Native:
xrc = DGImage.ImageNativeXfer.Get(ref dataPtr);
break;
case Values.XferMech.File:
xrc = DGImage.ImageFileXfer.Get();
if (File.Exists(args.OutputFile))
{
file = args.OutputFile;
}
break;
case Values.XferMech.MemFile:
// not supported yet
//TWImageMemXfer memxfer = new TWImageMemXfer();
//xrc = DGImage.ImageMemXfer.Get(memxfer);
break;
}
if (xrc == ReturnCode.XferDone)
{
State = 7;
try
{
var dtHand = DataTransferred;
if (dtHand != null)
{
if (dataPtr != IntPtr.Zero)
{
lockedPtr = MemoryManager.Instance.Lock(dataPtr);
}
dtHand(this, new DataTransferredEventArgs(lockedPtr, file));
}
}
catch { }
}
//}
//else if (group == DataGroups.Audio)
//{
// var xrc = DGAudio.AudioNativeXfer.Get(ref dataPtr);
// if (xrc == ReturnCode.XferDone)
// {
// State = 7;
// try
// {
// var dtHand = DataTransferred;
// if (dtHand != null)
// {
// lockedPtr = MemoryManager.Instance.MemLock(dataPtr);
// dtHand(this, new DataTransferredEventArgs(lockedPtr));
// }
// }
// catch { }
// }
//}
}
finally
{
State = 6;
// data here is allocated by source so needs to use shared mem calls
if (lockedPtr != IntPtr.Zero)
{
MemoryManager.Instance.Unlock(lockedPtr);
lockedPtr = IntPtr.Zero;
}
if (dataPtr != IntPtr.Zero)
{
MemoryManager.Instance.Free(dataPtr);
dataPtr = IntPtr.Zero;
}
}
#endregion
}
if (args.CancelAll)
{
rc = DGControl.PendingXfers.Reset(pending);
if (rc == ReturnCode.Success)
{
// if audio exit here
//if (group == DataGroups.Audio)
//{
// //???
// return;
//}
}
}
else
{
rc = DGControl.PendingXfers.EndXfer(pending);
}
} while (rc == ReturnCode.Success && pending.Count != 0);
State = 5;
DisableSource();
}
#endregion
#region messaging use
ReturnCode HandleSourceMsg(TWIdentity origin, TWIdentity destination,
DataGroups dg, DataArgumentType dat, NTwain.Values.Message msg, IntPtr data)
{
Debug.WriteLine(string.Format("Thread {0}: HandleSourceMsg at state {1} with DG={2} DAT={3} MSG={4}.", Thread.CurrentThread.ManagedThreadId, State, dg, dat, msg));
ReturnCode rc = ReturnCode.Success;
switch (msg)
{
case Values.Message.XferReady:
if (State < 6)
State = 6;
// this is the meat of all twain stuff
DoTransferRoutine();
break;
case Values.Message.DeviceEvent:
TWDeviceEvent de;
rc = DGControl.DeviceEvent.Get(out de);
if (rc == ReturnCode.Success)
{
var hand = this.DeviceEvent;
if (hand != null)
{
try
{
hand(this, new DeviceEventArgs(de));
}
catch { }
}
}
break;
case Values.Message.CloseDSReq:
case Values.Message.CloseDSOK:
// even though it says closeDS it's really disable.
// dsok is sent if source is enabled with uionly
// some sources send this at other states so do a step down
if (State > 5)
{
ForceStepDown(4);
}
else if (State == 5)
{
// needs this state check since some source sends this more than once
DisableSource();
}
break;
}
return rc;
}
/// <summary>
/// Forces the stepping down of an opened source ignoring return values.
/// Used when session state and source state become out of sync.
/// </summary>
/// <param name="targetState">State of the target.</param>
public void ForceStepDown(int targetState)
{
Debug.WriteLine(string.Format("Thread {0}: ForceStepDown.", Thread.CurrentThread.ManagedThreadId));
bool origFlag = EnforceState;
EnforceState = false;
// From the twain spec
// Stepping Back Down the States
// DG_CONTROL / DAT_PENDINGXFERS / MSG_ENDXFER → state 7 to 6
// DG_CONTROL / DAT_PENDINGXFERS / MSG_RESET → state 6 to 5
// DG_CONTROL / DAT_USERINTERFACE / MSG_DISABLEDS → state 5 to 4
// DG_CONTROL / DAT_IDENTITY / MSG_CLOSEDS → state 4 to 3
// Ignore the status returns from the calls prior to the one yielding the desired state. For instance, if a
// call during scanning returns TWCC_SEQERROR and the desire is to return to state 5, then use the
// following commands.
// DG_CONTROL / DAT_PENDINGXFERS / MSG_ENDXFER → state 7 to 6
// DG_CONTROL / DAT_PENDINGXFERS / MSG_RESET → state 6 to 5
// Being sure to confirm that DG_CONTROL / DAT_PENDINGXFERS / MSG_RESET returned
// success, the return status from DG_CONTROL / DAT_PENDINGXFERS / MSG_ENDXFER may
// be ignored.
if (targetState < 7)
{
DGControl.PendingXfers.EndXfer(new TWPendingXfers());
}
if (targetState < 6)
{
DGControl.PendingXfers.Reset(new TWPendingXfers());
}
if (targetState < 5)
{
DisableSource();
}
if (targetState < 4)
{
CloseSource();
}
if (targetState < 3)
{
CloseManager();
}
EnforceState = origFlag;
}
/// <summary>
/// Handles the message from a message loop.
/// </summary>
/// <param name="msgPtr">Pointer to message structure.</param>
/// <returns>True if handled by TWAIN.</returns>
bool HandleLoopMsgEvent(ref IntPtr msgPtr)
{
TWEvent evt = new TWEvent();
evt.pEvent = msgPtr;
var rc = DGControl.Event.ProcessEvent(evt);
HandleSourceMsg(null, null, DataGroups.Control, DataArgumentType.Null, evt.TWMessage, IntPtr.Zero);
return rc == ReturnCode.DSEvent;
}
/// <summary>
/// Message loop processor for winform.
/// Use this by adding the <see cref="TwainSession"/> as an <see cref="IMessageFilter "/>.
/// </summary>
/// <param name="m">The message to be dispatched. You cannot modify this message.</param>
/// <returns>
/// true to filter the message and stop it from being dispatched; false to allow the message to continue to the next filter or control.
/// </returns>
//[EnvironmentPermissionAttribute(SecurityAction.LinkDemand)]
[SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)]
bool IMessageFilter.PreFilterMessage(ref System.Windows.Forms.Message m)
{
if (State > 3)
{
MSG winmsg = default(MSG);
winmsg.hwnd = m.HWnd;
winmsg.lParam = m.LParam;
winmsg.message = m.Msg;
winmsg.wParam = m.WParam;
IntPtr msgPtr = IntPtr.Zero;
try
{
// no need to lock for marshal alloc
//msgPtr = MemoryManager.Instance.Allocate((uint)Marshal.SizeOf(winmsg));
msgPtr = Marshal.AllocHGlobal(Marshal.SizeOf(winmsg));
Marshal.StructureToPtr(winmsg, msgPtr, false);
return HandleLoopMsgEvent(ref msgPtr);
}
finally
{
if (msgPtr != IntPtr.Zero)
Marshal.FreeHGlobal(msgPtr);
//MemoryManager.Instance.Free(msgPtr);
}
}
return false;
}
/// <summary>
/// Message loop processor for wpf.
/// Use this as the target of <see cref="HwndSourceHook"/> delegate.
/// </summary>
/// <param name="hwnd">The window handle.</param>
/// <param name="msg">The message ID.</param>
/// <param name="wParam">The message's wParam value.</param>
/// <param name="lParam">The message's lParam value.</param>
/// <param name="handled">A value that indicates whether the message was handled. Set the value to true if the message was handled; otherwise, false.</param>
/// <returns></returns>
[EnvironmentPermissionAttribute(SecurityAction.LinkDemand)]
public IntPtr PreFilterMessage(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
// always pass message since it works whether there's a callback or not?
if (State > 3)// && _callbackObj == null)
{
MSG winmsg = default(MSG);
winmsg.hwnd = hwnd;
winmsg.lParam = lParam;
winmsg.message = msg;
winmsg.wParam = wParam;
IntPtr msgPtr = IntPtr.Zero;
try
{
// no need to lock for marshal alloc
//msgPtr = MemoryManager.Instance.Allocate((uint)Marshal.SizeOf(winmsg));
msgPtr = Marshal.AllocHGlobal(Marshal.SizeOf(winmsg));
Marshal.StructureToPtr(winmsg, msgPtr, false);
handled = HandleLoopMsgEvent(ref msgPtr);
}
finally
{
if (msgPtr != IntPtr.Zero)
Marshal.FreeHGlobal(msgPtr);
//MemoryManager.Instance.Free(msgPtr);
}
}
return IntPtr.Zero;
}
#endregion
#region INotifyPropertyChanged Members
/// <summary>
/// Occurs when a property value changes.
/// </summary>
public event PropertyChangedEventHandler PropertyChanged;
void RaisePropertyChanged(string property)
{
var hand = PropertyChanged;
if (hand != null) { hand(this, new PropertyChangedEventArgs(property)); }
}
#endregion
}
}

View File

@@ -19,7 +19,7 @@ namespace NTwain
public class TwainSessionBase : ITwainStateInternal, ITwainOperation public class TwainSessionBase : ITwainStateInternal, ITwainOperation
{ {
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="TwainSession" /> class. /// Initializes a new instance of the <see cref="TwainSessionOld" /> class.
/// </summary> /// </summary>
/// <param name="appId">The app id.</param> /// <param name="appId">The app id.</param>
/// <exception cref="System.ArgumentNullException"></exception> /// <exception cref="System.ArgumentNullException"></exception>
@@ -37,6 +37,32 @@ namespace NTwain
object _callbackObj; // kept around so it doesn't get gc'ed object _callbackObj; // kept around so it doesn't get gc'ed
TWUserInterface _twui; TWUserInterface _twui;
private IList<CapabilityId> _supportedCaps;
/// <summary>
/// Gets the supported caps for the current source.
/// </summary>
/// <value>
/// The supported caps.
/// </value>
public IList<CapabilityId> SupportedCaps
{
get
{
if (_supportedCaps == null && State > 3)
{
_supportedCaps = this.GetCapabilities();
}
return _supportedCaps ?? new CapabilityId[0];
}
private set
{
_supportedCaps = value;
RaisePropertyChanged("SupportedCaps");
}
}
#region ITwainStateInternal Members #region ITwainStateInternal Members
/// <summary> /// <summary>
@@ -55,7 +81,7 @@ namespace NTwain
void ITwainStateInternal.ChangeState(int newState, bool notifyChange) void ITwainStateInternal.ChangeState(int newState, bool notifyChange)
{ {
State = newState; _state = newState;
if (notifyChange) if (notifyChange)
{ {
RaisePropertyChanged("State"); RaisePropertyChanged("State");
@@ -72,7 +98,7 @@ namespace NTwain
{ {
SourceId = sourceId; SourceId = sourceId;
RaisePropertyChanged("SourceId"); RaisePropertyChanged("SourceId");
OnSourceIdChanged(); OnSourceChanged();
} }
#endregion #endregion
@@ -87,13 +113,26 @@ namespace NTwain
/// </value> /// </value>
public TWIdentity SourceId { get; private set; } public TWIdentity SourceId { get; private set; }
int _state;
/// <summary> /// <summary>
/// Gets the current state number as defined by the TWAIN spec. /// Gets the current state number as defined by the TWAIN spec.
/// </summary> /// </summary>
/// <value> /// <value>
/// The state. /// The state.
/// </value> /// </value>
public int State { get; private set; } public int State
{
get { return _state; }
protected set
{
if (value > 0 && value < 8)
{
_state = value;
RaisePropertyChanged("State");
OnStateChanged();
}
}
}
#endregion #endregion
@@ -262,7 +301,7 @@ namespace NTwain
/// <param name="windowHandle">The window handle if modal.</param> /// <param name="windowHandle">The window handle if modal.</param>
/// <param name="context">The /// <param name="context">The
/// <see cref="SynchronizationContext" /> that is required for certain operations. /// <see cref="SynchronizationContext" /> that is required for certain operations.
/// It is recommended you call this method in a UI thread and pass in /// It is recommended you call this method in an UI thread and pass in
/// <see cref="SynchronizationContext.Current" /> /// <see cref="SynchronizationContext.Current" />
/// if you do not have a custom one setup.</param> /// if you do not have a custom one setup.</param>
/// <returns></returns> /// <returns></returns>
@@ -319,7 +358,7 @@ namespace NTwain
/// Disables the source to end data acquisition. /// Disables the source to end data acquisition.
/// </summary> /// </summary>
/// <returns></returns> /// <returns></returns>
ReturnCode DisableSource() protected ReturnCode DisableSource()
{ {
Debug.WriteLine(string.Format("Thread {0}: DisableSource.", Thread.CurrentThread.ManagedThreadId)); Debug.WriteLine(string.Format("Thread {0}: DisableSource.", Thread.CurrentThread.ManagedThreadId));
@@ -553,13 +592,14 @@ namespace NTwain
} }
// final method that handles stuff from the source, whether it's from wndproc or callbacks // final method that handles stuff from the source, whether it's from wndproc or callbacks
void HandleSourceMsg(TWIdentity origin, TWIdentity destination, DataGroups dg, DataArgumentType dat, Message msg, IntPtr data) protected virtual void HandleSourceMsg(TWIdentity origin, TWIdentity destination, DataGroups dg, DataArgumentType dat, Message msg, IntPtr data)
{ {
if (msg != Message.Null) if (msg != Message.Null)
{ {
Debug.WriteLine(string.Format("Thread {0}: HandleSourceMsg at state {1} with DG={2} DAT={3} MSG={4}.", Thread.CurrentThread.ManagedThreadId, State, dg, dat, msg)); Debug.WriteLine(string.Format("Thread {0}: HandleSourceMsg at state {1} with DG={2} DAT={3} MSG={4}.", Thread.CurrentThread.ManagedThreadId, State, dg, dat, msg));
} }
throw new NotImplementedException();
} }

View File

@@ -8,7 +8,7 @@ using System.Text;
namespace NTwain namespace NTwain
{ {
/// <summary> /// <summary>
/// Defines common methods on <see cref="TwainSession"/> using the raw /// Defines common methods on <see cref="TwainSessionOld"/> using the raw
/// TWAIN triplet api. /// TWAIN triplet api.
/// </summary> /// </summary>
public static class TwainSessionExtensions public static class TwainSessionExtensions
@@ -18,7 +18,7 @@ namespace NTwain
/// </summary> /// </summary>
/// <param name="session">The session.</param> /// <param name="session">The session.</param>
/// <returns></returns> /// <returns></returns>
public static TWStatus GetManagerStatus(this TwainSession session) public static TWStatus GetManagerStatus(this TwainSessionBase session)
{ {
TWStatus stat; TWStatus stat;
session.DGControl.Status.GetManager(out stat); session.DGControl.Status.GetManager(out stat);
@@ -29,7 +29,7 @@ namespace NTwain
/// </summary> /// </summary>
/// <param name="session">The session.</param> /// <param name="session">The session.</param>
/// <returns></returns> /// <returns></returns>
public static TWStatus GetSourceStatus(this TwainSession session) public static TWStatus GetSourceStatus(this TwainSessionBase session)
{ {
TWStatus stat; TWStatus stat;
session.DGControl.Status.GetSource(out stat); session.DGControl.Status.GetSource(out stat);
@@ -42,7 +42,7 @@ namespace NTwain
/// </summary> /// </summary>
/// <param name="session">The session.</param> /// <param name="session">The session.</param>
/// <returns></returns> /// <returns></returns>
public static IList<TWIdentity> GetSources(this TwainSession session) public static IList<TWIdentity> GetSources(this TwainSessionBase session)
{ {
List<TWIdentity> list = new List<TWIdentity>(); List<TWIdentity> list = new List<TWIdentity>();
@@ -93,7 +93,7 @@ namespace NTwain
/// <param name="session">The session.</param> /// <param name="session">The session.</param>
/// <param name="capId">The cap id.</param> /// <param name="capId">The cap id.</param>
/// <returns></returns> /// <returns></returns>
public static T GetCurrentCap<T>(this TwainSession session, CapabilityId capId) where T : struct,IConvertible public static T GetCurrentCap<T>(this TwainSessionBase session, CapabilityId capId) where T : struct,IConvertible
{ {
using (TWCapability cap = new TWCapability(capId)) using (TWCapability cap = new TWCapability(capId))
{ {
@@ -230,14 +230,14 @@ namespace NTwain
} }
/// <summary> /// <summary>
/// A generic method that tries to get capability values from current <see cref="TwainSession" />. /// A generic method that tries to get capability values from current <see cref="TwainSessionOld" />.
/// </summary> /// </summary>
/// <typeparam name="TCapVal">The expected capability value type.</typeparam> /// <typeparam name="TCapVal">The expected capability value type.</typeparam>
/// <param name="session">The session.</param> /// <param name="session">The session.</param>
/// <param name="capabilityId">The capability unique identifier.</param> /// <param name="capabilityId">The capability unique identifier.</param>
/// <param name="tryUpperWord">if set to <c>true</c> then apply to workaround for certain bad sources.</param> /// <param name="tryUpperWord">if set to <c>true</c> then apply to workaround for certain bad sources.</param>
/// <returns></returns> /// <returns></returns>
public static IList<TCapVal> GetCapabilityValues<TCapVal>(this TwainSession session, CapabilityId capabilityId, bool tryUpperWord) where TCapVal : struct,IConvertible public static IList<TCapVal> GetCapabilityValues<TCapVal>(this TwainSessionBase session, CapabilityId capabilityId, bool tryUpperWord) where TCapVal : struct,IConvertible
{ {
var list = new List<TCapVal>(); var list = new List<TCapVal>();
using (TWCapability cap = new TWCapability(capabilityId)) using (TWCapability cap = new TWCapability(capabilityId))
@@ -257,7 +257,7 @@ namespace NTwain
/// </summary> /// </summary>
/// <param name="session">The session.</param> /// <param name="session">The session.</param>
/// <returns></returns> /// <returns></returns>
internal static IList<CapabilityId> GetCapabilities(this TwainSession session) internal static IList<CapabilityId> GetCapabilities(this TwainSessionBase session)
{ {
return session.GetCapabilityValues<CapabilityId>(CapabilityId.CapSupportedCaps, false); return session.GetCapabilityValues<CapabilityId>(CapabilityId.CapSupportedCaps, false);
} }
@@ -270,7 +270,7 @@ namespace NTwain
/// </summary> /// </summary>
/// <param name="session">The session.</param> /// <param name="session">The session.</param>
/// <returns></returns> /// <returns></returns>
public static IList<XferMech> CapGetImageXferMech(this TwainSession session) public static IList<XferMech> CapGetImageXferMech(this TwainSessionBase session)
{ {
return session.GetCapabilityValues<XferMech>(CapabilityId.ICapXferMech, true); return session.GetCapabilityValues<XferMech>(CapabilityId.ICapXferMech, true);
} }
@@ -285,7 +285,7 @@ namespace NTwain
/// </summary> /// </summary>
/// <param name="session">The session.</param> /// <param name="session">The session.</param>
/// <returns></returns> /// <returns></returns>
public static IList<Compression> CapGetCompression(this TwainSession session) public static IList<Compression> CapGetCompression(this TwainSessionBase session)
{ {
return session.GetCapabilityValues<Compression>(CapabilityId.ICapCompression, true); return session.GetCapabilityValues<Compression>(CapabilityId.ICapCompression, true);
} }
@@ -296,7 +296,7 @@ namespace NTwain
/// <param name="session">The session.</param> /// <param name="session">The session.</param>
/// <param name="compression">The compression.</param> /// <param name="compression">The compression.</param>
/// <returns></returns> /// <returns></returns>
public static ReturnCode CapSetImageCompression(this TwainSession session, Compression compression) public static ReturnCode CapSetImageCompression(this TwainSessionBase session, Compression compression)
{ {
using (TWCapability compressCap = new TWCapability(CapabilityId.ICapCompression, new TWOneValue { Item = (uint)compression, ItemType = Values.ItemType.UInt16 })) using (TWCapability compressCap = new TWCapability(CapabilityId.ICapCompression, new TWOneValue { Item = (uint)compression, ItemType = Values.ItemType.UInt16 }))
{ {
@@ -314,7 +314,7 @@ namespace NTwain
/// </summary> /// </summary>
/// <param name="session">The session.</param> /// <param name="session">The session.</param>
/// <returns></returns> /// <returns></returns>
public static IList<FileFormat> CapGetImageFileFormat(this TwainSession session) public static IList<FileFormat> CapGetImageFileFormat(this TwainSessionBase session)
{ {
return session.GetCapabilityValues<FileFormat>(CapabilityId.ICapImageFileFormat, true); return session.GetCapabilityValues<FileFormat>(CapabilityId.ICapImageFileFormat, true);
} }
@@ -325,7 +325,7 @@ namespace NTwain
/// <param name="session">The session.</param> /// <param name="session">The session.</param>
/// <param name="format">The format.</param> /// <param name="format">The format.</param>
/// <returns></returns> /// <returns></returns>
public static ReturnCode CapSetImageFormat(this TwainSession session, FileFormat format) public static ReturnCode CapSetImageFormat(this TwainSessionBase session, FileFormat format)
{ {
using (TWCapability formatCap = new TWCapability(CapabilityId.ICapImageFileFormat, new TWOneValue { Item = (uint)format, ItemType = Values.ItemType.UInt16 })) using (TWCapability formatCap = new TWCapability(CapabilityId.ICapImageFileFormat, new TWOneValue { Item = (uint)format, ItemType = Values.ItemType.UInt16 }))
{ {
@@ -343,7 +343,7 @@ namespace NTwain
/// </summary> /// </summary>
/// <param name="session">The session.</param> /// <param name="session">The session.</param>
/// <returns></returns> /// <returns></returns>
public static IList<PixelType> CapGetPixelTypes(this TwainSession session) public static IList<PixelType> CapGetPixelTypes(this TwainSessionBase session)
{ {
return session.GetCapabilityValues<PixelType>(CapabilityId.ICapPixelType, true); return session.GetCapabilityValues<PixelType>(CapabilityId.ICapPixelType, true);
} }
@@ -354,7 +354,7 @@ namespace NTwain
/// <param name="session">The session.</param> /// <param name="session">The session.</param>
/// <param name="type">The type.</param> /// <param name="type">The type.</param>
/// <returns></returns> /// <returns></returns>
public static ReturnCode CapSetPixelType(this TwainSession session, PixelType type) public static ReturnCode CapSetPixelType(this TwainSessionBase session, PixelType type)
{ {
var one = new TWOneValue(); var one = new TWOneValue();
one.Item = (uint)type; one.Item = (uint)type;
@@ -375,7 +375,7 @@ namespace NTwain
/// </summary> /// </summary>
/// <param name="session">The session.</param> /// <param name="session">The session.</param>
/// <returns></returns> /// <returns></returns>
public static IList<int> CapGetDPIs(this TwainSession session) public static IList<int> CapGetDPIs(this TwainSessionBase session)
{ {
return session.GetCapabilityValues<int>(CapabilityId.ICapXResolution, true); return session.GetCapabilityValues<int>(CapabilityId.ICapXResolution, true);
} }
@@ -386,7 +386,7 @@ namespace NTwain
/// <param name="session">The session.</param> /// <param name="session">The session.</param>
/// <param name="dpi">The DPI.</param> /// <param name="dpi">The DPI.</param>
/// <returns></returns> /// <returns></returns>
public static ReturnCode CapSetDPI(this TwainSession session, int dpi) public static ReturnCode CapSetDPI(this TwainSessionBase session, int dpi)
{ {
return CapSetDPI(session, dpi, dpi); return CapSetDPI(session, dpi, dpi);
} }
@@ -398,7 +398,7 @@ namespace NTwain
/// <param name="xDPI">The x DPI.</param> /// <param name="xDPI">The x DPI.</param>
/// <param name="yDPI">The y DPI.</param> /// <param name="yDPI">The y DPI.</param>
/// <returns></returns> /// <returns></returns>
public static ReturnCode CapSetDPI(this TwainSession session, int xDPI, int yDPI) public static ReturnCode CapSetDPI(this TwainSessionBase session, int xDPI, int yDPI)
{ {
TWOneValue one = new TWOneValue(); TWOneValue one = new TWOneValue();
one.Item = (uint)xDPI;// ((uint)dpi) << 16; one.Item = (uint)xDPI;// ((uint)dpi) << 16;
@@ -429,7 +429,7 @@ namespace NTwain
/// </summary> /// </summary>
/// <param name="session">The session.</param> /// <param name="session">The session.</param>
/// <returns></returns> /// <returns></returns>
public static IList<SupportedSize> CapGetSupportedSizes(this TwainSession session) public static IList<SupportedSize> CapGetSupportedSizes(this TwainSessionBase session)
{ {
return session.GetCapabilityValues<SupportedSize>(CapabilityId.ICapSupportedSizes, true); return session.GetCapabilityValues<SupportedSize>(CapabilityId.ICapSupportedSizes, true);
} }
@@ -440,7 +440,7 @@ namespace NTwain
/// <param name="session">The session.</param> /// <param name="session">The session.</param>
/// <param name="size">The size.</param> /// <param name="size">The size.</param>
/// <returns></returns> /// <returns></returns>
public static ReturnCode CapSetSupportedSize(this TwainSession session, SupportedSize size) public static ReturnCode CapSetSupportedSize(this TwainSessionBase session, SupportedSize size)
{ {
var one = new TWOneValue(); var one = new TWOneValue();
one.Item = (uint)size; one.Item = (uint)size;
@@ -463,7 +463,7 @@ namespace NTwain
/// <param name="session">The session.</param> /// <param name="session">The session.</param>
/// <param name="useIt">if set to <c>true</c> [use it].</param> /// <param name="useIt">if set to <c>true</c> [use it].</param>
/// <returns></returns> /// <returns></returns>
public static ReturnCode CapSetAutoDeskew(this TwainSession session, bool useIt) public static ReturnCode CapSetAutoDeskew(this TwainSessionBase session, bool useIt)
{ {
var rc = ReturnCode.Failure; var rc = ReturnCode.Failure;
if (session.SupportedCaps.Contains(CapabilityId.ICapAutomaticDeskew)) if (session.SupportedCaps.Contains(CapabilityId.ICapAutomaticDeskew))
@@ -503,7 +503,7 @@ namespace NTwain
/// <param name="session">The session.</param> /// <param name="session">The session.</param>
/// <param name="useIt">if set to <c>true</c> [use it].</param> /// <param name="useIt">if set to <c>true</c> [use it].</param>
/// <returns></returns> /// <returns></returns>
public static ReturnCode CapSetAutoRotate(this TwainSession session, bool useIt) public static ReturnCode CapSetAutoRotate(this TwainSessionBase session, bool useIt)
{ {
var rc = ReturnCode.Failure; var rc = ReturnCode.Failure;
if (session.SupportedCaps.Contains(CapabilityId.ICapAutomaticRotate)) if (session.SupportedCaps.Contains(CapabilityId.ICapAutomaticRotate))
@@ -541,7 +541,7 @@ namespace NTwain
/// <param name="session">The session.</param> /// <param name="session">The session.</param>
/// <param name="useIt">if set to <c>true</c> [use it].</param> /// <param name="useIt">if set to <c>true</c> [use it].</param>
/// <returns></returns> /// <returns></returns>
public static ReturnCode CapSetBorderDetection(this TwainSession session, bool useIt) public static ReturnCode CapSetBorderDetection(this TwainSessionBase session, bool useIt)
{ {
var rc = ReturnCode.Failure; var rc = ReturnCode.Failure;
if (session.SupportedCaps.Contains(CapabilityId.ICapAutomaticBorderDetection)) if (session.SupportedCaps.Contains(CapabilityId.ICapAutomaticBorderDetection))
@@ -589,7 +589,7 @@ namespace NTwain
/// <param name="session">The session.</param> /// <param name="session">The session.</param>
/// <param name="useIt">if set to <c>true</c> [use it].</param> /// <param name="useIt">if set to <c>true</c> [use it].</param>
/// <returns></returns> /// <returns></returns>
public static ReturnCode CapSetDuplex(this TwainSession session, bool useIt) public static ReturnCode CapSetDuplex(this TwainSessionBase session, bool useIt)
{ {
if (session.SourceId.ProtocolMajor >= 2) if (session.SourceId.ProtocolMajor >= 2)
{ {
@@ -623,7 +623,7 @@ namespace NTwain
/// <param name="session">The session.</param> /// <param name="session">The session.</param>
/// <param name="useIt">if set to <c>true</c> [use it].</param> /// <param name="useIt">if set to <c>true</c> [use it].</param>
/// <returns></returns> /// <returns></returns>
public static ReturnCode CapSetFeeder(this TwainSession session, bool useIt) public static ReturnCode CapSetFeeder(this TwainSessionBase session, bool useIt)
{ {
var rc = ReturnCode.Failure; var rc = ReturnCode.Failure;
if (session.SupportedCaps.Contains(CapabilityId.CapFeederEnabled)) if (session.SupportedCaps.Contains(CapabilityId.CapFeederEnabled))

284
NTwain/TwainSessionOld.cs Normal file
View File

@@ -0,0 +1,284 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NTwain.Triplets;
using NTwain.Data;
using NTwain.Values;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using System.Windows.Interop;
using System.Diagnostics;
using System.Security.Permissions;
using System.IO;
using System.ComponentModel;
using System.Threading;
namespace NTwain
{
/// <summary>
/// Provides a session for working with TWAIN api in an application.
/// This is the old implementation for reference purposes only.
/// </summary>
[Obsolete("For reference purposes only.")]
public class TwainSessionOld : TwainSessionBase, IMessageFilter
{
/// <summary>
/// Initializes a new instance of the <see cref="TwainSessionOld" /> class.
/// </summary>
/// <param name="appId">The app id.</param>
/// <exception cref="System.ArgumentNullException"></exception>
public TwainSessionOld(TWIdentity appId) : base(appId) { }
private void DoTransferRoutine()
{
TWPendingXfers pending = new TWPendingXfers();
var rc = ReturnCode.Success;
do
{
IList<FileFormat> formats = Enumerable.Empty<FileFormat>().ToList();
IList<Compression> compressions = Enumerable.Empty<Compression>().ToList();
bool canDoFileXfer = this.CapGetImageXferMech().Contains(XferMech.File);
var curFormat = this.GetCurrentCap<FileFormat>(CapabilityId.ICapImageFileFormat);
var curComp = this.GetCurrentCap<Compression>(CapabilityId.ICapCompression);
TWImageInfo imgInfo;
bool skip = false;
if (DGImage.ImageInfo.Get(out imgInfo) != ReturnCode.Success)
{
// bad!
skip = true;
}
try
{
formats = this.CapGetImageFileFormat();
}
catch { }
try
{
compressions = this.CapGetCompression();
}
catch { }
// ask consumer for cancel in case of non-ui multi-page transfers
TransferReadyEventArgs args = new TransferReadyEventArgs(pending, formats, curFormat, compressions,
curComp, canDoFileXfer, imgInfo);
args.CancelCurrent = skip;
OnTransferReady(args);
if (!args.CancelAll && !args.CancelCurrent)
{
Values.XferMech mech = this.GetCurrentCap<XferMech>(CapabilityId.ICapXferMech);
if (args.CanDoFileXfer && !string.IsNullOrEmpty(args.OutputFile))
{
var setXferRC = DGControl.SetupFileXfer.Set(new TWSetupFileXfer
{
FileName = args.OutputFile,
Format = args.ImageFormat
});
if (setXferRC == ReturnCode.Success)
{
mech = XferMech.File;
}
}
// I don't know how this is supposed to work so it probably doesn't
//this.CapSetImageFormat(args.ImageFormat);
//this.CapSetImageCompression(args.ImageCompression);
#region do xfer
// TODO: expose all swallowed exceptions somehow later
IntPtr dataPtr = IntPtr.Zero;
IntPtr lockedPtr = IntPtr.Zero;
string file = null;
try
{
ReturnCode xrc = ReturnCode.Cancel;
switch (mech)
{
case Values.XferMech.Native:
xrc = DGImage.ImageNativeXfer.Get(ref dataPtr);
break;
case Values.XferMech.File:
xrc = DGImage.ImageFileXfer.Get();
if (File.Exists(args.OutputFile))
{
file = args.OutputFile;
}
break;
case Values.XferMech.MemFile:
// not supported yet
//TWImageMemXfer memxfer = new TWImageMemXfer();
//xrc = DGImage.ImageMemXfer.Get(memxfer);
break;
}
if (xrc == ReturnCode.XferDone)
{
State = 7;
if (dataPtr != IntPtr.Zero)
{
lockedPtr = MemoryManager.Instance.Lock(dataPtr);
}
OnDataTransferred(new DataTransferredEventArgs(lockedPtr, file));
}
//}
//else if (group == DataGroups.Audio)
//{
// var xrc = DGAudio.AudioNativeXfer.Get(ref dataPtr);
// if (xrc == ReturnCode.XferDone)
// {
// State = 7;
// try
// {
// var dtHand = DataTransferred;
// if (dtHand != null)
// {
// lockedPtr = MemoryManager.Instance.MemLock(dataPtr);
// dtHand(this, new DataTransferredEventArgs(lockedPtr));
// }
// }
// catch { }
// }
//}
}
finally
{
State = 6;
// data here is allocated by source so needs to use shared mem calls
if (lockedPtr != IntPtr.Zero)
{
MemoryManager.Instance.Unlock(lockedPtr);
lockedPtr = IntPtr.Zero;
}
if (dataPtr != IntPtr.Zero)
{
MemoryManager.Instance.Free(dataPtr);
dataPtr = IntPtr.Zero;
}
}
#endregion
}
if (args.CancelAll)
{
rc = DGControl.PendingXfers.Reset(pending);
if (rc == ReturnCode.Success)
{
// if audio exit here
//if (group == DataGroups.Audio)
//{
// //???
// return;
//}
}
}
else
{
rc = DGControl.PendingXfers.EndXfer(pending);
}
} while (rc == ReturnCode.Success && pending.Count != 0);
State = 5;
DisableSource();
}
#region messaging use
protected override void HandleSourceMsg(TWIdentity origin, TWIdentity destination, DataGroups dg, DataArgumentType dat, Values.Message msg, IntPtr data)
{
if (msg != Values.Message.Null)
{
Debug.WriteLine(string.Format("Thread {0}: HandleSourceMsg at state {1} with DG={2} DAT={3} MSG={4}.", Thread.CurrentThread.ManagedThreadId, State, dg, dat, msg));
}
switch (msg)
{
case Values.Message.XferReady:
if (State < 6)
State = 6;
// this is the meat of all twain stuff
DoTransferRoutine();
break;
case Values.Message.DeviceEvent:
TWDeviceEvent de;
var rc = DGControl.DeviceEvent.Get(out de);
if (rc == ReturnCode.Success)
{
OnDeviceEvent(new DeviceEventArgs(de));
}
break;
case Values.Message.CloseDSReq:
case Values.Message.CloseDSOK:
// even though it says closeDS it's really disable.
// dsok is sent if source is enabled with uionly
// some sources send this at other states so do a step down
if (State > 5)
{
ForceStepDown(4);
}
else if (State == 5)
{
// needs this state check since some source sends this more than once
DisableSource();
}
break;
}
}
/// <summary>
/// Message loop processor for winform.
/// Use this by adding the <see cref="TwainSessionOld"/> as an <see cref="IMessageFilter "/>.
/// </summary>
/// <param name="m">The message to be dispatched. You cannot modify this message.</param>
/// <returns>
/// true to filter the message and stop it from being dispatched; false to allow the message to continue to the next filter or control.
/// </returns>
//[EnvironmentPermissionAttribute(SecurityAction.LinkDemand)]
[SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)]
bool IMessageFilter.PreFilterMessage(ref System.Windows.Forms.Message m)
{
MSG winmsg = default(MSG);
winmsg.hwnd = m.HWnd;
winmsg.lParam = m.LParam;
winmsg.message = m.Msg;
winmsg.wParam = m.WParam;
return HandleWndProcMessage(ref winmsg);
}
/// <summary>
/// Message loop processor for WPF.
/// </summary>
/// <param name="hwnd">The window handle.</param>
/// <param name="msg">The message ID.</param>
/// <param name="wParam">The message's wParam value.</param>
/// <param name="lParam">The message's lParam value.</param>
/// <param name="handled">A value that indicates whether the message was handled. Set the value to true if the message was handled; otherwise, false.</param>
/// <returns></returns>
[EnvironmentPermissionAttribute(SecurityAction.LinkDemand)]
public IntPtr PreFilterMessage(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
MSG winmsg = default(MSG);
winmsg.hwnd = hwnd;
winmsg.lParam = lParam;
winmsg.message = msg;
winmsg.wParam = wParam;
handled = base.HandleWndProcMessage(ref winmsg);
return IntPtr.Zero;
}
#endregion
}
}

View File

@@ -3,11 +3,12 @@ TWAIN Application-Side Library
Info Info
-------------------------------------- --------------------------------------
This is a dotnet library created to work with [TWAIN](http://twain.org/) interface on Windows. This is a dotnet library created to work with [TWAIN](http://twain.org/) interface.
This project follows these general goals: This project follows these general goals:
* Targets latest TWAIN version (2.3 at the moment) * Targets latest TWAIN version (2.3 at the moment)
* Supports all the TWAIN commands in the spec (or those that are possible) * Supports all the TWAIN commands in the spec (or those that are possible)
* Eventally work on platforms other than Windows
The solution contains sample projects in both winforms and wpf. A nuget package is also The solution contains sample projects in both winforms and wpf. A nuget package is also
[available here](https://www.nuget.org/packages/ntwain) [available here](https://www.nuget.org/packages/ntwain)

View File

@@ -12,7 +12,7 @@ namespace NTwain.Tests
[ExpectedException(typeof(TwainStateException), "State check failed to throw.")] [ExpectedException(typeof(TwainStateException), "State check failed to throw.")]
public void VerifyState_Throws_When_State_Is_Enforced() public void VerifyState_Throws_When_State_Is_Enforced()
{ {
ITwainStateInternal session = new TwainSession(TWIdentity.Create(DataGroups.Image, new Version(1, 0), "test", "test", "test", "test")); ITwainStateInternal session = new TwainSessionOld(TWIdentity.Create(DataGroups.Image, new Version(1, 0), "test", "test", "test", "test"));
session.EnforceState = true; session.EnforceState = true;
session.ChangeState(4, false); session.ChangeState(4, false);
@@ -22,7 +22,7 @@ namespace NTwain.Tests
[TestMethod] [TestMethod]
public void VerifyState_No_Throws_When_State_Is_Not_Enforced() public void VerifyState_No_Throws_When_State_Is_Not_Enforced()
{ {
ITwainStateInternal session = new TwainSession(TWIdentity.Create(DataGroups.Image, new Version(1, 0), "test", "test", "test", "test")); ITwainStateInternal session = new TwainSessionOld(TWIdentity.Create(DataGroups.Image, new Version(1, 0), "test", "test", "test", "test"));
session.EnforceState = false; session.EnforceState = false;
session.ChangeState(4, false); session.ChangeState(4, false);

View File

@@ -17,6 +17,7 @@ using NTwain.Values;
using System.Windows.Interop; using System.Windows.Interop;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using CommonWin32; using CommonWin32;
using System.Threading;
namespace Tester.WPF namespace Tester.WPF
{ {
@@ -25,7 +26,7 @@ namespace Tester.WPF
/// </summary> /// </summary>
public partial class MainWindow : Window public partial class MainWindow : Window
{ {
TwainSession twain; TwainSessionOld twain;
public MainWindow() public MainWindow()
{ {
InitializeComponent(); InitializeComponent();
@@ -58,7 +59,7 @@ namespace Tester.WPF
private void SetupTwain() private void SetupTwain()
{ {
TWIdentity appId = TWIdentity.Create(DataGroups.Image, new Version(1, 0), "My Company", "Test Family", "Tester", null); TWIdentity appId = TWIdentity.Create(DataGroups.Image, new Version(1, 0), "My Company", "Test Family", "Tester", null);
twain = new TwainSession(appId); twain = new TwainSessionOld(appId);
twain.DataTransferred += (s, e) => twain.DataTransferred += (s, e) =>
{ {
if (e.Data != IntPtr.Zero) if (e.Data != IntPtr.Zero)
@@ -117,7 +118,7 @@ namespace Tester.WPF
if (rc == ReturnCode.Success) if (rc == ReturnCode.Success)
{ {
step = "Open DS"; step = "Open DS";
rc = twain.OpenSource(dsId); rc = twain.OpenSource(dsId.ProductName);
//rc = DGControl.Status.Get(dsId, ref stat); //rc = DGControl.Status.Get(dsId, ref stat);
if (rc == ReturnCode.Success) if (rc == ReturnCode.Success)
{ {
@@ -137,7 +138,7 @@ namespace Tester.WPF
} }
step = "Enable DS"; step = "Enable DS";
rc = twain.EnableSource(SourceEnableMode.NoUI, false, hand); rc = twain.EnableSource(SourceEnableMode.NoUI, false, hand, SynchronizationContext.Current);
return; return;
} }
else else

View File

@@ -13,13 +13,14 @@ using System.Runtime.InteropServices;
using System.Collections.Generic; using System.Collections.Generic;
using System.Reflection; using System.Reflection;
using CommonWin32; using CommonWin32;
using System.Threading;
namespace Tester.Winform namespace Tester.Winform
{ {
sealed partial class TestForm : Form sealed partial class TestForm : Form
{ {
ImageCodecInfo _tiffCodecInfo; ImageCodecInfo _tiffCodecInfo;
TwainSession _twain; TwainSessionOld _twain;
bool _stopScan; bool _stopScan;
bool _loadingCaps; bool _loadingCaps;
@@ -63,7 +64,7 @@ namespace Tester.Winform
TWIdentity appId = TWIdentity.Create(DataGroups.Image, new Version(appVer.ProductMajorPart, appVer.ProductMinorPart), TWIdentity appId = TWIdentity.Create(DataGroups.Image, new Version(appVer.ProductMajorPart, appVer.ProductMinorPart),
"My Company", "Test Family", "Tester", "A TWAIN testing app."); "My Company", "Test Family", "Tester", "A TWAIN testing app.");
_twain = new TwainSession(appId); _twain = new TwainSessionOld(appId);
_twain.DataTransferred += (s, e) => _twain.DataTransferred += (s, e) =>
{ {
if (pictureBox1.Image != null) if (pictureBox1.Image != null)
@@ -167,7 +168,7 @@ namespace Tester.Winform
if (_twain.SupportedCaps.Contains(CapabilityId.CapUIControllable)) if (_twain.SupportedCaps.Contains(CapabilityId.CapUIControllable))
{ {
// hide scanner ui if possible // hide scanner ui if possible
if (_twain.EnableSource(SourceEnableMode.NoUI, false, hand) == ReturnCode.Success) if (_twain.EnableSource(SourceEnableMode.NoUI, false, hand, SynchronizationContext.Current) == ReturnCode.Success)
{ {
btnStopScan.Enabled = true; btnStopScan.Enabled = true;
btnStartCapture.Enabled = false; btnStartCapture.Enabled = false;
@@ -176,7 +177,7 @@ namespace Tester.Winform
} }
else else
{ {
if (_twain.EnableSource(SourceEnableMode.ShowUI, false, hand) == ReturnCode.Success) if (_twain.EnableSource(SourceEnableMode.ShowUI, false, hand, SynchronizationContext.Current) == ReturnCode.Success)
{ {
btnStopScan.Enabled = true; btnStopScan.Enabled = true;
btnStartCapture.Enabled = false; btnStartCapture.Enabled = false;
@@ -360,7 +361,7 @@ namespace Tester.Winform
private void btnAllSettings_Click(object sender, EventArgs e) private void btnAllSettings_Click(object sender, EventArgs e)
{ {
var hand = new HandleRef(this, this.Handle); var hand = new HandleRef(this, this.Handle);
_twain.EnableSource(SourceEnableMode.ShowUIOnly, true, hand); _twain.EnableSource(SourceEnableMode.ShowUIOnly, true, hand, SynchronizationContext.Current);
} }
#endregion #endregion