mirror of
https://github.com/soukoku/ntwain.git
synced 2025-09-19 18:27:56 +08:00
Made old session inherit the refactored version.
This commit is contained in:
@@ -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>
|
||||||
|
@@ -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" />
|
||||||
|
@@ -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(
|
@@ -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(
|
@@ -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); }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@@ -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 Source’s
|
|
||||||
/// "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
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
@@ -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();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -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
284
NTwain/TwainSessionOld.cs
Normal 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
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@@ -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)
|
||||||
|
@@ -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);
|
||||||
|
|
||||||
|
@@ -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
|
||||||
|
@@ -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
|
||||||
|
Reference in New Issue
Block a user