Initial internal loop idea that compiles.

This commit is contained in:
soukoku
2014-04-14 19:04:48 -04:00
parent 04ee0baf75
commit 320dfb2175
13 changed files with 231 additions and 611 deletions

View File

@@ -1,50 +0,0 @@
//using System;
//using System.Collections.Generic;
//using System.Linq;
//using System.Text;
//using System.Threading;
//using System.Windows.Threading;
//namespace NTwain
//{
// // from http://blogs.msdn.com/b/pfxteam/archive/2012/01/20/10259049.aspx
// /// <summary>
// /// Provides a pump that supports running asynchronous methods on the current thread.
// /// </summary>
// public static class AsyncPump
// {
// /// <summary>
// /// Runs the specified asynchronous function.
// /// </summary>
// /// <param name="func">The asynchronous function to execute.</param>
// /// <exception cref="System.ArgumentNullException">func</exception>
// /// <exception cref="System.InvalidOperationException">No task provided.</exception>
// public static void Run(Func<Task> func)
// {
// if (func == null) throw new ArgumentNullException("func");
// var prevCtx = SynchronizationContext.Current;
// try
// {
// var syncCtx = new DispatcherSynchronizationContext();
// SynchronizationContext.SetSynchronizationContext(syncCtx);
// var t = func();
// if (t == null) throw new InvalidOperationException();
// var frame = new DispatcherFrame();
// t.ContinueWith(_ => { frame.Continue = false; },
// TaskScheduler.Default);
// Dispatcher.PushFrame(frame);
// t.GetAwaiter().GetResult();
// }
// finally
// {
// SynchronizationContext.SetSynchronizationContext(prevCtx);
// }
// }
// }
//}

View File

@@ -53,7 +53,6 @@
<Reference Include="WindowsBase" /> <Reference Include="WindowsBase" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="AsyncPump.cs" />
<Compile Include="Data\CapReadOut.cs" /> <Compile Include="Data\CapReadOut.cs" />
<Compile Include="Data\TypeReader.cs" /> <Compile Include="Data\TypeReader.cs" />
<Compile Include="Data\TypesExtended.cs" /> <Compile Include="Data\TypesExtended.cs" />
@@ -64,6 +63,7 @@
<Compile Include="ITwainOperation.cs" /> <Compile Include="ITwainOperation.cs" />
<Compile Include="ITwainState.cs" /> <Compile Include="ITwainState.cs" />
<Compile Include="MemoryManager.cs" /> <Compile Include="MemoryManager.cs" />
<Compile Include="MessageLoop.cs" />
<Compile Include="NativeMethods.cs" /> <Compile Include="NativeMethods.cs" />
<Compile Include="Properties\Resources.Designer.cs"> <Compile Include="Properties\Resources.Designer.cs">
<AutoGen>True</AutoGen> <AutoGen>True</AutoGen>
@@ -82,8 +82,6 @@
<Compile Include="Triplets\Dsm.WinNew.cs" /> <Compile Include="Triplets\Dsm.WinNew.cs" />
<Compile Include="TwainSessionExtensions.cs" /> <Compile Include="TwainSessionExtensions.cs" />
<Compile Include="TwainSession.cs" /> <Compile Include="TwainSession.cs" />
<Compile Include="TwainSessionWPF.cs" />
<Compile Include="TwainSessionWinform.cs" />
<Compile Include="TwainStateException.cs" /> <Compile Include="TwainStateException.cs" />
<Compile Include="Data\Types.cs" /> <Compile Include="Data\Types.cs" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
@@ -125,7 +123,6 @@
<Compile Include="Triplets\DGImage\DGImage.RgbResponse.cs" /> <Compile Include="Triplets\DGImage\DGImage.RgbResponse.cs" />
<Compile Include="Triplets\Dsm.cs" /> <Compile Include="Triplets\Dsm.cs" />
<Compile Include="TwainException.cs" /> <Compile Include="TwainException.cs" />
<Compile Include="TwainSessionOld.cs" />
<Compile Include="Values\DataValues.cs" /> <Compile Include="Values\DataValues.cs" />
<Compile Include="Values\SourceEnableMode.cs" /> <Compile Include="Values\SourceEnableMode.cs" />
<Compile Include="Values\TwainConst.cs" /> <Compile Include="Values\TwainConst.cs" />

View File

@@ -14,6 +14,6 @@ namespace NTwain
// keep this same in majors releases // keep this same in majors releases
public const string Release = "0.10.0.0"; public const string Release = "0.10.0.0";
// change this for each nuget release // change this for each nuget release
public const string Build = "0.10.1"; public const string Build = "0.10.2";
} }
} }

View File

@@ -21,7 +21,7 @@ namespace NTwain.Triplets
// in essence it only exists in 64 bit systems and thus // in essence it only exists in 64 bit systems and thus
// the 2 sets of identical pinvokes for windows :( // the 2 sets of identical pinvokes for windows :(
public static readonly bool CanUseNewDSM = CheckIfCanUseNewDSM(); internal static readonly bool UseNewDSM = CheckIfCanUseNewDSM();
private static bool CheckIfCanUseNewDSM() private static bool CheckIfCanUseNewDSM()
{ {
@@ -35,7 +35,7 @@ namespace NTwain.Triplets
#endif #endif
} }
static readonly bool IsWin = Environment.OSVersion.Platform == PlatformID.Win32NT; internal static readonly bool IsWin = Environment.OSVersion.Platform == PlatformID.Win32NT;
static readonly bool IsLinux = Environment.OSVersion.Platform == PlatformID.Unix; static readonly bool IsLinux = Environment.OSVersion.Platform == PlatformID.Unix;
// define sig for each different data type since "object" doesn't work // define sig for each different data type since "object" doesn't work
@@ -52,7 +52,7 @@ namespace NTwain.Triplets
{ {
if (IsWin) if (IsWin)
{ {
if (CanUseNewDSM) { return NativeMethods.DsmWinNew(origin, destination, dg, dat, msg, ref data); } if (UseNewDSM) { return NativeMethods.DsmWinNew(origin, destination, dg, dat, msg, ref data); }
else { return NativeMethods.DsmWinOld(origin, destination, dg, dat, msg, ref data); } else { return NativeMethods.DsmWinOld(origin, destination, dg, dat, msg, ref data); }
} }
else if (IsLinux) else if (IsLinux)
@@ -72,7 +72,7 @@ namespace NTwain.Triplets
{ {
if (IsWin) if (IsWin)
{ {
if (CanUseNewDSM) { return NativeMethods.DsmWinNew(origin, destination, dg, dat, msg, ref data); } if (UseNewDSM) { return NativeMethods.DsmWinNew(origin, destination, dg, dat, msg, ref data); }
else { return NativeMethods.DsmWinOld(origin, destination, dg, dat, msg, ref data); } else { return NativeMethods.DsmWinOld(origin, destination, dg, dat, msg, ref data); }
} }
else if (IsLinux) else if (IsLinux)
@@ -90,7 +90,7 @@ namespace NTwain.Triplets
{ {
if (IsWin) if (IsWin)
{ {
if (CanUseNewDSM) { return NativeMethods.DsmWinNew(origin, destination, DataGroups.Audio, DataArgumentType.AudioInfo, msg, data); } if (UseNewDSM) { return NativeMethods.DsmWinNew(origin, destination, DataGroups.Audio, DataArgumentType.AudioInfo, msg, data); }
else { return NativeMethods.DsmWinOld(origin, destination, DataGroups.Audio, DataArgumentType.AudioInfo, msg, data); } else { return NativeMethods.DsmWinOld(origin, destination, DataGroups.Audio, DataArgumentType.AudioInfo, msg, data); }
} }
else if (IsLinux) else if (IsLinux)
@@ -109,7 +109,7 @@ namespace NTwain.Triplets
{ {
if (IsWin) if (IsWin)
{ {
if (CanUseNewDSM) { return NativeMethods.DsmWinNew(origin, destination, DataGroups.Control, DataArgumentType.Capability, msg, data); } if (UseNewDSM) { return NativeMethods.DsmWinNew(origin, destination, DataGroups.Control, DataArgumentType.Capability, msg, data); }
else { return NativeMethods.DsmWinOld(origin, destination, DataGroups.Control, DataArgumentType.Capability, msg, data); } else { return NativeMethods.DsmWinOld(origin, destination, DataGroups.Control, DataArgumentType.Capability, msg, data); }
} }
else if (IsLinux) else if (IsLinux)
@@ -128,7 +128,7 @@ namespace NTwain.Triplets
{ {
if (IsWin) if (IsWin)
{ {
if (CanUseNewDSM) { return NativeMethods.DsmWinNew(origin, destination, DataGroups.Control, DataArgumentType.CustomDSData, msg, data); } if (UseNewDSM) { return NativeMethods.DsmWinNew(origin, destination, DataGroups.Control, DataArgumentType.CustomDSData, msg, data); }
else { return NativeMethods.DsmWinOld(origin, destination, DataGroups.Control, DataArgumentType.CustomDSData, msg, data); } else { return NativeMethods.DsmWinOld(origin, destination, DataGroups.Control, DataArgumentType.CustomDSData, msg, data); }
} }
else if (IsLinux) else if (IsLinux)
@@ -147,7 +147,7 @@ namespace NTwain.Triplets
{ {
if (IsWin) if (IsWin)
{ {
if (CanUseNewDSM) { return NativeMethods.DsmWinNew(origin, destination, DataGroups.Control, DataArgumentType.DeviceEvent, msg, data); } if (UseNewDSM) { return NativeMethods.DsmWinNew(origin, destination, DataGroups.Control, DataArgumentType.DeviceEvent, msg, data); }
else { return NativeMethods.DsmWinOld(origin, destination, DataGroups.Control, DataArgumentType.DeviceEvent, msg, data); } else { return NativeMethods.DsmWinOld(origin, destination, DataGroups.Control, DataArgumentType.DeviceEvent, msg, data); }
} }
else if (IsLinux) else if (IsLinux)
@@ -166,7 +166,7 @@ namespace NTwain.Triplets
{ {
if (IsWin) if (IsWin)
{ {
if (CanUseNewDSM) { return NativeMethods.DsmWinNew(origin, destination, DataGroups.Control, DataArgumentType.Callback, msg, data); } if (UseNewDSM) { return NativeMethods.DsmWinNew(origin, destination, DataGroups.Control, DataArgumentType.Callback, msg, data); }
else { return NativeMethods.DsmWinOld(origin, destination, DataGroups.Control, DataArgumentType.Callback, msg, data); } else { return NativeMethods.DsmWinOld(origin, destination, DataGroups.Control, DataArgumentType.Callback, msg, data); }
} }
else if (IsLinux) else if (IsLinux)
@@ -185,7 +185,7 @@ namespace NTwain.Triplets
{ {
if (IsWin) if (IsWin)
{ {
if (CanUseNewDSM) { return NativeMethods.DsmWinNew(origin, destination, DataGroups.Control, DataArgumentType.Callback, msg, data); } if (UseNewDSM) { return NativeMethods.DsmWinNew(origin, destination, DataGroups.Control, DataArgumentType.Callback, msg, data); }
else { return NativeMethods.DsmWinOld(origin, destination, DataGroups.Control, DataArgumentType.Callback, msg, data); } else { return NativeMethods.DsmWinOld(origin, destination, DataGroups.Control, DataArgumentType.Callback, msg, data); }
} }
else if (IsLinux) else if (IsLinux)
@@ -204,7 +204,7 @@ namespace NTwain.Triplets
{ {
if (IsWin) if (IsWin)
{ {
if (CanUseNewDSM) { return NativeMethods.DsmWinNew(origin, destination, DataGroups.Control, DataArgumentType.EntryPoint, msg, data); } if (UseNewDSM) { return NativeMethods.DsmWinNew(origin, destination, DataGroups.Control, DataArgumentType.EntryPoint, msg, data); }
else { return NativeMethods.DsmWinOld(origin, destination, DataGroups.Control, DataArgumentType.EntryPoint, msg, data); } else { return NativeMethods.DsmWinOld(origin, destination, DataGroups.Control, DataArgumentType.EntryPoint, msg, data); }
} }
else if (IsLinux) else if (IsLinux)
@@ -223,7 +223,7 @@ namespace NTwain.Triplets
{ {
if (IsWin) if (IsWin)
{ {
if (CanUseNewDSM) { return NativeMethods.DsmWinNew(origin, destination, DataGroups.Control, DataArgumentType.Event, msg, data); } if (UseNewDSM) { return NativeMethods.DsmWinNew(origin, destination, DataGroups.Control, DataArgumentType.Event, msg, data); }
else { return NativeMethods.DsmWinOld(origin, destination, DataGroups.Control, DataArgumentType.Event, msg, data); } else { return NativeMethods.DsmWinOld(origin, destination, DataGroups.Control, DataArgumentType.Event, msg, data); }
} }
else if (IsLinux) else if (IsLinux)
@@ -242,7 +242,7 @@ namespace NTwain.Triplets
{ {
if (IsWin) if (IsWin)
{ {
if (CanUseNewDSM) { return NativeMethods.DsmWinNew(origin, destination, DataGroups.Control, DataArgumentType.FileSystem, msg, data); } if (UseNewDSM) { return NativeMethods.DsmWinNew(origin, destination, DataGroups.Control, DataArgumentType.FileSystem, msg, data); }
else { return NativeMethods.DsmWinOld(origin, destination, DataGroups.Control, DataArgumentType.FileSystem, msg, data); } else { return NativeMethods.DsmWinOld(origin, destination, DataGroups.Control, DataArgumentType.FileSystem, msg, data); }
} }
else if (IsLinux) else if (IsLinux)
@@ -259,7 +259,7 @@ namespace NTwain.Triplets
{ {
if (IsWin) if (IsWin)
{ {
if (CanUseNewDSM) { return NativeMethods.DsmWinNew(origin, IntPtr.Zero, DataGroups.Control, DataArgumentType.Identity, msg, data); } if (UseNewDSM) { return NativeMethods.DsmWinNew(origin, IntPtr.Zero, DataGroups.Control, DataArgumentType.Identity, msg, data); }
else { return NativeMethods.DsmWinOld(origin, IntPtr.Zero, DataGroups.Control, DataArgumentType.Identity, msg, data); } else { return NativeMethods.DsmWinOld(origin, IntPtr.Zero, DataGroups.Control, DataArgumentType.Identity, msg, data); }
} }
else if (IsLinux) else if (IsLinux)
@@ -278,7 +278,7 @@ namespace NTwain.Triplets
{ {
if (IsWin) if (IsWin)
{ {
if (CanUseNewDSM) { return NativeMethods.DsmWinNew(origin, destination, DataGroups.Control, DataArgumentType.PassThru, msg, data); } if (UseNewDSM) { return NativeMethods.DsmWinNew(origin, destination, DataGroups.Control, DataArgumentType.PassThru, msg, data); }
else { return NativeMethods.DsmWinOld(origin, destination, DataGroups.Control, DataArgumentType.PassThru, msg, data); } else { return NativeMethods.DsmWinOld(origin, destination, DataGroups.Control, DataArgumentType.PassThru, msg, data); }
} }
else if (IsLinux) else if (IsLinux)
@@ -297,7 +297,7 @@ namespace NTwain.Triplets
{ {
if (IsWin) if (IsWin)
{ {
if (CanUseNewDSM) { return NativeMethods.DsmWinNew(origin, destination, DataGroups.Control, DataArgumentType.PendingXfers, msg, data); } if (UseNewDSM) { return NativeMethods.DsmWinNew(origin, destination, DataGroups.Control, DataArgumentType.PendingXfers, msg, data); }
else { return NativeMethods.DsmWinOld(origin, destination, DataGroups.Control, DataArgumentType.PendingXfers, msg, data); } else { return NativeMethods.DsmWinOld(origin, destination, DataGroups.Control, DataArgumentType.PendingXfers, msg, data); }
} }
else if (IsLinux) else if (IsLinux)
@@ -316,7 +316,7 @@ namespace NTwain.Triplets
{ {
if (IsWin) if (IsWin)
{ {
if (CanUseNewDSM) { return NativeMethods.DsmWinNew(origin, destination, DataGroups.Control, DataArgumentType.SetupFileXfer, msg, data); } if (UseNewDSM) { return NativeMethods.DsmWinNew(origin, destination, DataGroups.Control, DataArgumentType.SetupFileXfer, msg, data); }
else { return NativeMethods.DsmWinOld(origin, destination, DataGroups.Control, DataArgumentType.SetupFileXfer, msg, data); } else { return NativeMethods.DsmWinOld(origin, destination, DataGroups.Control, DataArgumentType.SetupFileXfer, msg, data); }
} }
else if (IsLinux) else if (IsLinux)
@@ -335,7 +335,7 @@ namespace NTwain.Triplets
{ {
if (IsWin) if (IsWin)
{ {
if (CanUseNewDSM) { return NativeMethods.DsmWinNew(origin, destination, DataGroups.Control, DataArgumentType.SetupMemXfer, msg, data); } if (UseNewDSM) { return NativeMethods.DsmWinNew(origin, destination, DataGroups.Control, DataArgumentType.SetupMemXfer, msg, data); }
else { return NativeMethods.DsmWinOld(origin, destination, DataGroups.Control, DataArgumentType.SetupMemXfer, msg, data); } else { return NativeMethods.DsmWinOld(origin, destination, DataGroups.Control, DataArgumentType.SetupMemXfer, msg, data); }
} }
else if (IsLinux) else if (IsLinux)
@@ -354,7 +354,7 @@ namespace NTwain.Triplets
{ {
if (IsWin) if (IsWin)
{ {
if (CanUseNewDSM) { return NativeMethods.DsmWinNew(origin, destination, DataGroups.Control, DataArgumentType.StatusUtf8, msg, data); } if (UseNewDSM) { return NativeMethods.DsmWinNew(origin, destination, DataGroups.Control, DataArgumentType.StatusUtf8, msg, data); }
else { return NativeMethods.DsmWinOld(origin, destination, DataGroups.Control, DataArgumentType.StatusUtf8, msg, data); } else { return NativeMethods.DsmWinOld(origin, destination, DataGroups.Control, DataArgumentType.StatusUtf8, msg, data); }
} }
else if (IsLinux) else if (IsLinux)
@@ -373,7 +373,7 @@ namespace NTwain.Triplets
{ {
if (IsWin) if (IsWin)
{ {
if (CanUseNewDSM) { return NativeMethods.DsmWinNew(origin, destination, DataGroups.Control, DataArgumentType.UserInterface, msg, data); } if (UseNewDSM) { return NativeMethods.DsmWinNew(origin, destination, DataGroups.Control, DataArgumentType.UserInterface, msg, data); }
else { return NativeMethods.DsmWinOld(origin, destination, DataGroups.Control, DataArgumentType.UserInterface, msg, data); } else { return NativeMethods.DsmWinOld(origin, destination, DataGroups.Control, DataArgumentType.UserInterface, msg, data); }
} }
else if (IsLinux) else if (IsLinux)
@@ -392,7 +392,7 @@ namespace NTwain.Triplets
{ {
if (IsWin) if (IsWin)
{ {
if (CanUseNewDSM) { return NativeMethods.DsmWinNew(origin, destination, DataGroups.Image, DataArgumentType.CieColor, msg, data); } if (UseNewDSM) { return NativeMethods.DsmWinNew(origin, destination, DataGroups.Image, DataArgumentType.CieColor, msg, data); }
else { return NativeMethods.DsmWinOld(origin, destination, DataGroups.Image, DataArgumentType.CieColor, msg, data); } else { return NativeMethods.DsmWinOld(origin, destination, DataGroups.Image, DataArgumentType.CieColor, msg, data); }
} }
else if (IsLinux) else if (IsLinux)
@@ -411,7 +411,7 @@ namespace NTwain.Triplets
{ {
if (IsWin) if (IsWin)
{ {
if (CanUseNewDSM) { return NativeMethods.DsmWinNew(origin, destination, DataGroups.Image, DataArgumentType.ExtImageInfo, msg, data); } if (UseNewDSM) { return NativeMethods.DsmWinNew(origin, destination, DataGroups.Image, DataArgumentType.ExtImageInfo, msg, data); }
else { return NativeMethods.DsmWinOld(origin, destination, DataGroups.Image, DataArgumentType.ExtImageInfo, msg, data); } else { return NativeMethods.DsmWinOld(origin, destination, DataGroups.Image, DataArgumentType.ExtImageInfo, msg, data); }
} }
else if (IsLinux) else if (IsLinux)
@@ -429,7 +429,7 @@ namespace NTwain.Triplets
{ {
if (IsWin) if (IsWin)
{ {
if (CanUseNewDSM) { return NativeMethods.DsmWinNew(origin, destination, DataGroups.Image, DataArgumentType.Filter, msg, data); } if (UseNewDSM) { return NativeMethods.DsmWinNew(origin, destination, DataGroups.Image, DataArgumentType.Filter, msg, data); }
else { return NativeMethods.DsmWinOld(origin, destination, DataGroups.Image, DataArgumentType.Filter, msg, data); } else { return NativeMethods.DsmWinOld(origin, destination, DataGroups.Image, DataArgumentType.Filter, msg, data); }
} }
else if (IsLinux) else if (IsLinux)
@@ -447,7 +447,7 @@ namespace NTwain.Triplets
{ {
if (IsWin) if (IsWin)
{ {
if (CanUseNewDSM) { return NativeMethods.DsmWinNew(origin, destination, DataGroups.Image, DataArgumentType.GrayResponse, msg, data); } if (UseNewDSM) { return NativeMethods.DsmWinNew(origin, destination, DataGroups.Image, DataArgumentType.GrayResponse, msg, data); }
else { return NativeMethods.DsmWinOld(origin, destination, DataGroups.Image, DataArgumentType.GrayResponse, msg, data); } else { return NativeMethods.DsmWinOld(origin, destination, DataGroups.Image, DataArgumentType.GrayResponse, msg, data); }
} }
else if (IsLinux) else if (IsLinux)
@@ -466,7 +466,7 @@ namespace NTwain.Triplets
{ {
if (IsWin) if (IsWin)
{ {
if (CanUseNewDSM) { return NativeMethods.DsmWinNew(origin, destination, DataGroups.Image, DataArgumentType.ImageInfo, msg, data); } if (UseNewDSM) { return NativeMethods.DsmWinNew(origin, destination, DataGroups.Image, DataArgumentType.ImageInfo, msg, data); }
else { return NativeMethods.DsmWinOld(origin, destination, DataGroups.Image, DataArgumentType.ImageInfo, msg, data); } else { return NativeMethods.DsmWinOld(origin, destination, DataGroups.Image, DataArgumentType.ImageInfo, msg, data); }
} }
else if (IsLinux) else if (IsLinux)
@@ -485,7 +485,7 @@ namespace NTwain.Triplets
{ {
if (IsWin) if (IsWin)
{ {
if (CanUseNewDSM) { return NativeMethods.DsmWinNew(origin, destination, DataGroups.Image, DataArgumentType.ImageLayout, msg, data); } if (UseNewDSM) { return NativeMethods.DsmWinNew(origin, destination, DataGroups.Image, DataArgumentType.ImageLayout, msg, data); }
else { return NativeMethods.DsmWinOld(origin, destination, DataGroups.Image, DataArgumentType.ImageLayout, msg, data); } else { return NativeMethods.DsmWinOld(origin, destination, DataGroups.Image, DataArgumentType.ImageLayout, msg, data); }
} }
else if (IsLinux) else if (IsLinux)
@@ -504,7 +504,7 @@ namespace NTwain.Triplets
{ {
if (IsWin) if (IsWin)
{ {
if (CanUseNewDSM) { return NativeMethods.DsmWinNew(origin, destination, DataGroups.Image, DataArgumentType.ImageMemXfer, msg, data); } if (UseNewDSM) { return NativeMethods.DsmWinNew(origin, destination, DataGroups.Image, DataArgumentType.ImageMemXfer, msg, data); }
else { return NativeMethods.DsmWinOld(origin, destination, DataGroups.Image, DataArgumentType.ImageMemXfer, msg, data); } else { return NativeMethods.DsmWinOld(origin, destination, DataGroups.Image, DataArgumentType.ImageMemXfer, msg, data); }
} }
else if (IsLinux) else if (IsLinux)
@@ -523,7 +523,7 @@ namespace NTwain.Triplets
{ {
if (IsWin) if (IsWin)
{ {
if (CanUseNewDSM) { return NativeMethods.DsmWinNew(origin, destination, DataGroups.Image, DataArgumentType.JpegCompression, msg, data); } if (UseNewDSM) { return NativeMethods.DsmWinNew(origin, destination, DataGroups.Image, DataArgumentType.JpegCompression, msg, data); }
else { return NativeMethods.DsmWinOld(origin, destination, DataGroups.Image, DataArgumentType.JpegCompression, msg, data); } else { return NativeMethods.DsmWinOld(origin, destination, DataGroups.Image, DataArgumentType.JpegCompression, msg, data); }
} }
else if (IsLinux) else if (IsLinux)
@@ -542,7 +542,7 @@ namespace NTwain.Triplets
{ {
if (IsWin) if (IsWin)
{ {
if (CanUseNewDSM) { return NativeMethods.DsmWinNew(origin, destination, DataGroups.Image, DataArgumentType.Palette8, msg, data); } if (UseNewDSM) { return NativeMethods.DsmWinNew(origin, destination, DataGroups.Image, DataArgumentType.Palette8, msg, data); }
else { return NativeMethods.DsmWinOld(origin, destination, DataGroups.Image, DataArgumentType.Palette8, msg, data); } else { return NativeMethods.DsmWinOld(origin, destination, DataGroups.Image, DataArgumentType.Palette8, msg, data); }
} }
else if (IsLinux) else if (IsLinux)
@@ -561,7 +561,7 @@ namespace NTwain.Triplets
{ {
if (IsWin) if (IsWin)
{ {
if (CanUseNewDSM) { return NativeMethods.DsmWinNew(origin, destination, DataGroups.Image, DataArgumentType.RgbResponse, msg, data); } if (UseNewDSM) { return NativeMethods.DsmWinNew(origin, destination, DataGroups.Image, DataArgumentType.RgbResponse, msg, data); }
else { return NativeMethods.DsmWinOld(origin, destination, DataGroups.Image, DataArgumentType.RgbResponse, msg, data); } else { return NativeMethods.DsmWinOld(origin, destination, DataGroups.Image, DataArgumentType.RgbResponse, msg, data); }
} }
else if (IsLinux) else if (IsLinux)
@@ -580,7 +580,7 @@ namespace NTwain.Triplets
{ {
if (IsWin) if (IsWin)
{ {
if (CanUseNewDSM) { return NativeMethods.DsmWinNew(origin, destination, DataGroups.Control, DataArgumentType.Status, msg, data); } if (UseNewDSM) { return NativeMethods.DsmWinNew(origin, destination, DataGroups.Control, DataArgumentType.Status, msg, data); }
else { return NativeMethods.DsmWinOld(origin, destination, DataGroups.Control, DataArgumentType.Status, msg, data); } else { return NativeMethods.DsmWinOld(origin, destination, DataGroups.Control, DataArgumentType.Status, msg, data); }
} }
else if (IsLinux) else if (IsLinux)
@@ -600,7 +600,7 @@ namespace NTwain.Triplets
{ {
if (IsWin) if (IsWin)
{ {
if (CanUseNewDSM) { return NativeMethods.DsmWinNew(origin, destination, DataGroups.Control, dat, msg, ref data); } if (UseNewDSM) { return NativeMethods.DsmWinNew(origin, destination, DataGroups.Control, dat, msg, ref data); }
else { return NativeMethods.DsmWinOld(origin, destination, DataGroups.Control, dat, msg, ref data); } else { return NativeMethods.DsmWinOld(origin, destination, DataGroups.Control, dat, msg, ref data); }
} }
else if (IsLinux) else if (IsLinux)

View File

@@ -8,8 +8,10 @@ using System.Diagnostics;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Security.Permissions;
using System.Text; using System.Text;
using System.Threading; using System.Threading;
using System.Windows.Threading;
namespace NTwain namespace NTwain
{ {
@@ -29,11 +31,13 @@ namespace NTwain
_appId = appId; _appId = appId;
((ITwainStateInternal)this).ChangeState(1, false); ((ITwainStateInternal)this).ChangeState(1, false);
EnforceState = true; EnforceState = true;
Debug.WriteLine("current thread id =" + Thread.CurrentThread.ManagedThreadId);
MessageLoop.Instance.EnsureStarted();
} }
TWIdentity _appId; TWIdentity _appId;
IntPtr _appHandle;
SynchronizationContext _syncer;
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;
@@ -205,17 +209,14 @@ namespace NTwain
/// Opens the data source manager. This must be the first method used /// Opens the data source manager. This must be the first method used
/// before using other TWAIN functions. Calls to this must be followed by <see cref="CloseManager"/> when done with a TWAIN session. /// before using other TWAIN functions. Calls to this must be followed by <see cref="CloseManager"/> when done with a TWAIN session.
/// </summary> /// </summary>
/// <param name="appHandle">On Windows = points to the window handle (hWnd) that will act as the Sources
/// "parent". On Macintosh = should be a NULL value.</param>
/// <returns></returns> /// <returns></returns>
public ReturnCode OpenManager(IntPtr appHandle) public ReturnCode OpenManager()
{ {
Debug.WriteLine(string.Format("Thread {0}: OpenManager.", Thread.CurrentThread.ManagedThreadId)); Debug.WriteLine(string.Format("Thread {0}: OpenManager.", Thread.CurrentThread.ManagedThreadId));
var rc = DGControl.Parent.OpenDsm(appHandle); var rc = DGControl.Parent.OpenDsm(MessageLoop.Instance.LoopHandle);
if (rc == ReturnCode.Success) if (rc == ReturnCode.Success)
{ {
_appHandle = appHandle;
// if twain2 then get memory management functions // if twain2 then get memory management functions
if ((_appId.DataFunctionalities & DataFunctionalities.Dsm2) == DataFunctionalities.Dsm2) if ((_appId.DataFunctionalities & DataFunctionalities.Dsm2) == DataFunctionalities.Dsm2)
{ {
@@ -243,11 +244,7 @@ namespace NTwain
{ {
Debug.WriteLine(string.Format("Thread {0}: CloseManager.", Thread.CurrentThread.ManagedThreadId)); Debug.WriteLine(string.Format("Thread {0}: CloseManager.", Thread.CurrentThread.ManagedThreadId));
var rc = DGControl.Parent.CloseDsm(_appHandle); var rc = DGControl.Parent.CloseDsm(MessageLoop.Instance.LoopHandle);
if (rc == ReturnCode.Success)
{
_appHandle = IntPtr.Zero;
}
return rc; return rc;
} }
@@ -289,6 +286,7 @@ namespace NTwain
var rc = DGControl.Identity.CloseDS(); var rc = DGControl.Identity.CloseDS();
if (rc == ReturnCode.Success) if (rc == ReturnCode.Success)
{ {
MessageLoop.Instance.RemoveHook(HandleWndProcMessage);
_callbackObj = null; _callbackObj = null;
SupportedCaps = null; SupportedCaps = null;
} }
@@ -301,23 +299,16 @@ namespace NTwain
/// <param name="mode">The mode.</param> /// <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="modal">if set to <c>true</c> any driver UI will display as modal.</param>
/// <param name="windowHandle">The window handle if modal.</param> /// <param name="windowHandle">The window handle if modal.</param>
/// <param name="context">
/// The
/// <see cref="SynchronizationContext" /> is required if TWAIN is using callback mode
/// instead of the typical WndProc message loop.
/// It is recommended you call this method in an UI thread and pass in
/// <see cref="SynchronizationContext.Current" />
/// if you do not have a custom one setup.</param>
/// <returns></returns> /// <returns></returns>
/// <exception cref="ArgumentNullException">context</exception> /// <exception cref="ArgumentNullException">context</exception>
public ReturnCode EnableSource(SourceEnableMode mode, bool modal, IntPtr windowHandle, SynchronizationContext context) public ReturnCode EnableSource(SourceEnableMode mode, bool modal, IntPtr windowHandle)
{ {
if (context == null && _callbackObj != null) { throw new ArgumentNullException("SynchronizationContext is required when not using message loop.", "context"); }
Debug.WriteLine(string.Format("Thread {0}: EnableSource.", Thread.CurrentThread.ManagedThreadId)); Debug.WriteLine(string.Format("Thread {0}: EnableSource.", Thread.CurrentThread.ManagedThreadId));
_syncer = context; ReturnCode rc = ReturnCode.Success;
MessageLoop.Instance.Invoke(() =>
{
// app v2.2 or higher uses callback2 // app v2.2 or higher uses callback2
if (_appId.ProtocolMajor >= 2 && _appId.ProtocolMinor >= 2) if (_appId.ProtocolMajor >= 2 && _appId.ProtocolMinor >= 2)
{ {
@@ -343,6 +334,12 @@ namespace NTwain
} }
} }
if (_callbackObj == null)
{
// must use msg loop if callback is not available
MessageLoop.Instance.AddHook(HandleWndProcMessage);
}
_twui = new TWUserInterface(); _twui = new TWUserInterface();
_twui.ShowUI = mode == SourceEnableMode.ShowUI; _twui.ShowUI = mode == SourceEnableMode.ShowUI;
_twui.ModalUI = modal; _twui.ModalUI = modal;
@@ -350,13 +347,14 @@ namespace NTwain
if (mode == SourceEnableMode.ShowUIOnly) if (mode == SourceEnableMode.ShowUIOnly)
{ {
return DGControl.UserInterface.EnableDSUIOnly(_twui); rc = DGControl.UserInterface.EnableDSUIOnly(_twui);
} }
else else
{ {
return DGControl.UserInterface.EnableDS(_twui); rc = DGControl.UserInterface.EnableDS(_twui);
} }
});
return rc;
} }
/// <summary> /// <summary>
@@ -367,25 +365,29 @@ namespace NTwain
{ {
Debug.WriteLine(string.Format("Thread {0}: DisableSource.", Thread.CurrentThread.ManagedThreadId)); Debug.WriteLine(string.Format("Thread {0}: DisableSource.", Thread.CurrentThread.ManagedThreadId));
var rc = DGControl.UserInterface.DisableDS(_twui); ReturnCode rc = ReturnCode.Success;
MessageLoop.Instance.Invoke(() =>
{
rc = DGControl.UserInterface.DisableDS(_twui);
if (rc == ReturnCode.Success) if (rc == ReturnCode.Success)
{ {
OnSourceDisabled(); OnSourceDisabled();
} }
});
return rc; return rc;
} }
/// <summary> /// <summary>
/// Forces the stepping down of an opened source when things gets out of control. /// Forces the stepping down of an opened source when things gets out of control.
/// Used when session state and source state become out of sync. /// Used when session state and source state become out of sync.
/// This should be called on the Thread that originally called the <see cref="EnableSource"/>
/// method, if applicable.
/// </summary> /// </summary>
/// <param name="targetState">State of the target.</param> /// <param name="targetState">State of the target.</param>
public void ForceStepDown(int targetState) public void ForceStepDown(int targetState)
{ {
Debug.WriteLine(string.Format("Thread {0}: ForceStepDown.", Thread.CurrentThread.ManagedThreadId)); Debug.WriteLine(string.Format("Thread {0}: ForceStepDown.", Thread.CurrentThread.ManagedThreadId));
MessageLoop.Instance.Invoke(() =>
{
bool origFlag = EnforceState; bool origFlag = EnforceState;
EnforceState = false; EnforceState = false;
@@ -425,6 +427,7 @@ namespace NTwain
CloseManager(); CloseManager();
} }
EnforceState = origFlag; EnforceState = origFlag;
});
} }
#endregion #endregion
@@ -583,14 +586,13 @@ namespace NTwain
#region TWAIN logic during xfer work #region TWAIN logic during xfer work
/// <summary> //[EnvironmentPermissionAttribute(SecurityAction.LinkDemand)]
/// Handles the message from a typical WndProc message loop and check if it's from the TWAIN source. IntPtr HandleWndProcMessage(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
/// </summary>
/// <param name="message">The message.</param>
/// <returns>True if handled by TWAIN.</returns>
protected bool HandleWndProcMessage(ref MESSAGE message)
{ {
var handled = false; // this handles the message from a typical WndProc message loop and check if it's from the TWAIN source.
var winmsg = new MESSAGE(hwnd, msg, wParam, lParam);
if (State >= 4) // technically we should only handle on state >= 5 but there might be missed msgs if we wait until state changes after enabling ds if (State >= 4) // technically we should only handle on state >= 5 but there might be missed msgs if we wait until state changes after enabling ds
{ {
// transform it into a pointer for twain // transform it into a pointer for twain
@@ -598,15 +600,19 @@ namespace NTwain
try try
{ {
// no need to do another lock call when using marshal alloc // no need to do another lock call when using marshal alloc
msgPtr = Marshal.AllocHGlobal(Marshal.SizeOf(message)); msgPtr = Marshal.AllocHGlobal(Marshal.SizeOf(winmsg));
Marshal.StructureToPtr(message, msgPtr, false); Marshal.StructureToPtr(winmsg, msgPtr, false);
TWEvent evt = new TWEvent(); TWEvent evt = new TWEvent();
evt.pEvent = msgPtr; evt.pEvent = msgPtr;
if (handled = DGControl.Event.ProcessEvent(evt) == ReturnCode.DSEvent) if (handled = (DGControl.Event.ProcessEvent(evt) == ReturnCode.DSEvent))
{ {
Debug.WriteLine(string.Format("Thread {0}: HandleWndProcMessage at state {1} with MSG={2}.", Thread.CurrentThread.ManagedThreadId, State, evt.TWMessage)); Debug.WriteLine(string.Format("Thread {0}: HandleWndProcMessage at state {1} with MSG={2}.", Thread.CurrentThread.ManagedThreadId, State, evt.TWMessage));
MessageLoop.Instance.BeginInvoke(() =>
{
HandleSourceMsg(evt.TWMessage); HandleSourceMsg(evt.TWMessage);
});
} }
} }
finally finally
@@ -614,7 +620,8 @@ namespace NTwain
if (msgPtr != IntPtr.Zero) { Marshal.FreeHGlobal(msgPtr); } if (msgPtr != IntPtr.Zero) { Marshal.FreeHGlobal(msgPtr); }
} }
} }
return handled;
return IntPtr.Zero;
} }
ReturnCode HandleCallback(TWIdentity origin, TWIdentity destination, DataGroups dg, DataArgumentType dat, Message msg, IntPtr data) ReturnCode HandleCallback(TWIdentity origin, TWIdentity destination, DataGroups dg, DataArgumentType dat, Message msg, IntPtr data)
@@ -622,28 +629,13 @@ namespace NTwain
if (origin != null && SourceId != null && origin.Id == SourceId.Id) if (origin != null && SourceId != null && origin.Id == SourceId.Id)
{ {
Debug.WriteLine(string.Format("Thread {0}: CallbackHandler at state {1} with MSG={2}.", Thread.CurrentThread.ManagedThreadId, State, msg)); Debug.WriteLine(string.Format("Thread {0}: CallbackHandler at state {1} with MSG={2}.", Thread.CurrentThread.ManagedThreadId, State, msg));
// spec says we must handle this on the thread that enabled the DS, // spec says we must handle this on the thread that enabled the DS.
// but it's usually already the same thread and doesn't work (failure + seqError) w/o jumping to another thread and back. // by using the internal dispatcher this will be the case.
// My guess is the DS needs to see the Success return code first before letting transfer happen
// so this is an hack to make it happen.
// TODO: find a better method without needing a SynchronizationContext. MessageLoop.Instance.BeginInvoke(() =>
ThreadPool.QueueUserWorkItem(o =>
{
var ctx = o as SynchronizationContext;
if (ctx != null)
{
_syncer.Post(blah =>
{ {
HandleSourceMsg(msg); HandleSourceMsg(msg);
}, null); });
}
else
{
// no context? better hope for the best!
HandleSourceMsg(msg);
}
}, _syncer);
return ReturnCode.Success; return ReturnCode.Success;
} }
return ReturnCode.Failure; return ReturnCode.Failure;

View File

@@ -1,229 +0,0 @@
using System;
using NTwain.Triplets;
using NTwain.Data;
using NTwain.Values;
using System.Windows.Forms;
using System.Security.Permissions;
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 : TwainSession, 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) { }
protected override 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);
var args = new TransferReadyEventArgs
{
PendingImageInfo = imgInfo,
PendingTransferCount = pending.Count,
EndOfJob = pending.EndOfJob == 0
};
args.CancelCurrent = skip;
OnTransferReady(args);
if (!args.CancelAll && !args.CancelCurrent)
{
Values.XferMech mech = this.GetCurrentCap(CapabilityId.ICapXferMech).ConvertToEnum<XferMech>();
//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
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 { NativeData = lockedPtr, FileDataPath = 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
/// <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)
{
var winmsg = new MESSAGE(m.HWnd, m.Msg, m.WParam, m.LParam);
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)
{
var winmsg = new MESSAGE(hwnd, msg, wParam, lParam);
handled = base.HandleWndProcMessage(ref winmsg);
return IntPtr.Zero;
}
#endregion
}
}

View File

@@ -1,39 +0,0 @@
using NTwain.Data;
using System;
using System.Security.Permissions;
namespace NTwain
{
/// <summary>
/// A customized TWAIN session for use in WPF environment.
/// Use this by using <see cref="PreFilterMessage"/> method as the target of <see cref="System.Windows.Interop.HwndSource.AddHook"/> delegate.
/// </summary>
public class TwainSessionWPF : TwainSession
{
/// <summary>
/// Initializes a new instance of the <see cref="TwainSessionWPF" /> class.
/// </summary>
/// <param name="appId">The app id.</param>
/// <exception cref="System.ArgumentNullException"></exception>
public TwainSessionWPF(TWIdentity appId) : base(appId) { }
/// <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)
{
var winmsg = new MESSAGE(hwnd, msg, wParam, lParam);
handled = base.HandleWndProcMessage(ref winmsg);
return IntPtr.Zero;
}
}
}

View File

@@ -1,32 +0,0 @@
using NTwain.Data;
using System.Security.Permissions;
using System.Windows.Forms;
namespace NTwain
{
/// <summary>
/// A customized TWAIN session for use in winform environment.
/// Use this by adding this as an <see cref="IMessageFilter "/> via <see cref="Application.AddMessageFilter"/>.
/// </summary>
public class TwainSessionWinform : TwainSession, IMessageFilter
{
/// <summary>
/// Initializes a new instance of the <see cref="TwainSessionWinform" /> class.
/// </summary>
/// <param name="appId">The app id.</param>
/// <exception cref="System.ArgumentNullException"></exception>
public TwainSessionWinform(TWIdentity appId) : base(appId) { }
#region IMessageFilter Members
[SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)]
public bool PreFilterMessage(ref Message m)
{
var winmsg = new MESSAGE(m.HWnd, m.Msg, m.WParam, m.LParam);
return HandleWndProcMessage(ref winmsg);
}
#endregion
}
}

View File

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

View File

@@ -17,14 +17,9 @@ namespace Tester
{ {
static void Main(string[] args) static void Main(string[] args)
{ {
// just an amusing example to do twain in console without UI, but may not work in real life // just an amusing example to do twain in console without UI
DoTwainWork();
Console.WriteLine("Running Main on thread {0}", Thread.CurrentThread.ManagedThreadId); Console.WriteLine("Test completed, press Enter to exit.");
new Thread(new ParameterizedThreadStart(DoTwainWork)).Start(Dispatcher.CurrentDispatcher);
// basically just needs a msg loop to act as the UI thread
Dispatcher.Run();
Console.WriteLine("Test completed.");
Console.ReadLine(); Console.ReadLine();
} }
@@ -41,19 +36,12 @@ namespace Tester
} }
static void DoTwainWork(object obj) static void DoTwainWork()
{ {
Console.WriteLine("Getting ready to do twain stuff on thread {0}", Thread.CurrentThread.ManagedThreadId); Console.WriteLine("Getting ready to do twain stuff on thread {0}", Thread.CurrentThread.ManagedThreadId);
Thread.Sleep(1000); Thread.Sleep(1000);
var mySyncer = SynchronizationContext.Current; var rc = twain.OpenManager();
if (mySyncer == null)
{
mySyncer = new DispatcherSynchronizationContext(obj as Dispatcher);
}
var rc = twain.OpenManager(IntPtr.Zero);
if (rc == ReturnCode.Success) if (rc == ReturnCode.Success)
{ {
@@ -61,20 +49,13 @@ namespace Tester
if (rc == ReturnCode.Success) if (rc == ReturnCode.Success)
{ {
// enablesource must be on the thread the sync context works on rc = twain.EnableSource(SourceEnableMode.NoUI, false, IntPtr.Zero);
mySyncer.Post(blah =>
{
rc = twain.EnableSource(SourceEnableMode.NoUI, false, IntPtr.Zero, blah as SynchronizationContext);
}, mySyncer);
return;
} }
else else
{ {
twain.CloseManager(); twain.CloseManager();
} }
} }
Dispatcher.ExitAllFrames();
} }
static void twain_SourceDisabled(object sender, EventArgs e) static void twain_SourceDisabled(object sender, EventArgs e)
@@ -82,8 +63,6 @@ namespace Tester
Console.WriteLine("Source disabled on thread {0}", Thread.CurrentThread.ManagedThreadId); Console.WriteLine("Source disabled on thread {0}", Thread.CurrentThread.ManagedThreadId);
var rc = twain.CloseSource(); var rc = twain.CloseSource();
rc = twain.CloseManager(); rc = twain.CloseManager();
Dispatcher.ExitAllFrames();
} }
static void twain_TransferReady(object sender, TransferReadyEventArgs e) static void twain_TransferReady(object sender, TransferReadyEventArgs e)

View File

@@ -68,12 +68,7 @@ namespace Tester.WPF
{ {
base.OnSourceInitialized(e); base.OnSourceInitialized(e);
var hwnd = new WindowInteropHelper(this).Handle; var rc = _twainVM.OpenManager();
// this line is unnecessary if using twain 2 dsm but doesn't hurt to use it
HwndSource.FromHwnd(hwnd).AddHook(_twainVM.PreFilterMessage);
var rc = _twainVM.OpenManager(hwnd);
if (rc == ReturnCode.Success) if (rc == ReturnCode.Success)
{ {
SrcList.ItemsSource = _twainVM.GetSources().Select(s => new DSVM { DS = s }); SrcList.ItemsSource = _twainVM.GetSources().Select(s => new DSVM { DS = s });

View File

@@ -17,7 +17,7 @@ namespace Tester.WPF
/// <summary> /// <summary>
/// Wraps the twain session as a view model for databinding. /// Wraps the twain session as a view model for databinding.
/// </summary> /// </summary>
class TwainVM : TwainSessionWPF class TwainVM : TwainSession
{ {
public TwainVM() public TwainVM()
: base(TWIdentity.CreateFromAssembly(DataGroups.Image | DataGroups.Audio, Assembly.GetEntryAssembly())) : base(TWIdentity.CreateFromAssembly(DataGroups.Image | DataGroups.Audio, Assembly.GetEntryAssembly()))
@@ -86,6 +86,8 @@ namespace Tester.WPF
} }
protected override void OnDataTransferred(DataTransferredEventArgs e) protected override void OnDataTransferred(DataTransferredEventArgs e)
{
App.Current.Dispatcher.Invoke(new Action(() =>
{ {
if (e.NativeData != IntPtr.Zero) if (e.NativeData != IntPtr.Zero)
{ {
@@ -96,6 +98,7 @@ namespace Tester.WPF
var img = new BitmapImage(new Uri(e.FileDataPath)); var img = new BitmapImage(new Uri(e.FileDataPath));
Image = img; Image = img;
} }
}));
base.OnDataTransferred(e); base.OnDataTransferred(e);
} }
@@ -113,7 +116,7 @@ namespace Tester.WPF
this.CapSetImageXferMech(XferMech.File); this.CapSetImageXferMech(XferMech.File);
} }
var rc = EnableSource(SourceEnableMode.NoUI, false, hwnd, SynchronizationContext.Current); var rc = EnableSource(SourceEnableMode.NoUI, false, hwnd);
} }
} }
} }

View File

@@ -20,7 +20,7 @@ namespace Tester.Winform
sealed partial class TestForm : Form sealed partial class TestForm : Form
{ {
ImageCodecInfo _tiffCodecInfo; ImageCodecInfo _tiffCodecInfo;
TwainSessionWinform _twain; TwainSession _twain;
bool _stopScan; bool _stopScan;
bool _loadingCaps; bool _loadingCaps;
@@ -61,8 +61,10 @@ namespace Tester.Winform
private void SetupTwain() private void SetupTwain()
{ {
var appId = TWIdentity.CreateFromAssembly(DataGroups.Image, Assembly.GetEntryAssembly()); var appId = TWIdentity.CreateFromAssembly(DataGroups.Image, Assembly.GetEntryAssembly());
_twain = new TwainSessionWinform(appId); _twain = new TwainSession(appId);
_twain.DataTransferred += (s, e) => _twain.DataTransferred += (s, e) =>
{
this.Invoke(new Action(() =>
{ {
if (pictureBox1.Image != null) if (pictureBox1.Image != null)
{ {
@@ -81,24 +83,26 @@ namespace Tester.Winform
var img = new Bitmap(e.FileDataPath); var img = new Bitmap(e.FileDataPath);
pictureBox1.Image = img; pictureBox1.Image = img;
} }
}));
}; };
_twain.SourceDisabled += (s, e) => _twain.SourceDisabled += (s, e) =>
{
this.Invoke(new Action(() =>
{ {
btnStopScan.Enabled = false; btnStopScan.Enabled = false;
btnStartCapture.Enabled = true; btnStartCapture.Enabled = true;
panelOptions.Enabled = true; panelOptions.Enabled = true;
LoadSourceCaps(); LoadSourceCaps();
}));
}; };
_twain.TransferReady += (s, e) => _twain.TransferReady += (s, e) =>
{ {
e.CancelAll = _stopScan; e.CancelAll = _stopScan;
}; };
Application.AddMessageFilter(_twain);
} }
private void CleanupTwain() private void CleanupTwain()
{ {
Application.RemoveMessageFilter(_twain);
if (_twain.State == 4) if (_twain.State == 4)
{ {
_twain.CloseSource(); _twain.CloseSource();
@@ -164,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, this.Handle, SynchronizationContext.Current) == ReturnCode.Success) if (_twain.EnableSource(SourceEnableMode.NoUI, false, this.Handle) == ReturnCode.Success)
{ {
btnStopScan.Enabled = true; btnStopScan.Enabled = true;
btnStartCapture.Enabled = false; btnStartCapture.Enabled = false;
@@ -173,7 +177,7 @@ namespace Tester.Winform
} }
else else
{ {
if (_twain.EnableSource(SourceEnableMode.ShowUI, true, this.Handle, SynchronizationContext.Current) == ReturnCode.Success) if (_twain.EnableSource(SourceEnableMode.ShowUI, true, this.Handle) == ReturnCode.Success)
{ {
btnStopScan.Enabled = true; btnStopScan.Enabled = true;
btnStartCapture.Enabled = false; btnStartCapture.Enabled = false;
@@ -229,7 +233,7 @@ namespace Tester.Winform
{ {
if (_twain.State < 3) if (_twain.State < 3)
{ {
_twain.OpenManager(this.Handle); _twain.OpenManager();
} }
if (_twain.State >= 3) if (_twain.State >= 3)
@@ -356,7 +360,7 @@ namespace Tester.Winform
private void btnAllSettings_Click(object sender, EventArgs e) private void btnAllSettings_Click(object sender, EventArgs e)
{ {
_twain.EnableSource(SourceEnableMode.ShowUIOnly, true, this.Handle, SynchronizationContext.Current); _twain.EnableSource(SourceEnableMode.ShowUIOnly, true, this.Handle);
} }
#endregion #endregion