mirror of
https://github.com/soukoku/ntwain.git
synced 2025-09-18 17:47:57 +08:00
Changeset 2 for swappable message loop hook implementations.
This commit is contained in:
@@ -39,7 +39,9 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Reference Include="PresentationCore" />
|
<Reference Include="PresentationCore" />
|
||||||
|
<Reference Include="PresentationFramework" />
|
||||||
<Reference Include="System" />
|
<Reference Include="System" />
|
||||||
|
<Reference Include="System.Windows.Forms" />
|
||||||
<Reference Include="WindowsBase" />
|
<Reference Include="WindowsBase" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
@@ -76,15 +78,18 @@
|
|||||||
<Compile Include="..\NTwain\Internals\ICommittable.cs">
|
<Compile Include="..\NTwain\Internals\ICommittable.cs">
|
||||||
<Link>Internals\ICommittable.cs</Link>
|
<Link>Internals\ICommittable.cs</Link>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
<Compile Include="..\NTwain\Internals\InternalMessageLoopHook.cs">
|
||||||
|
<Link>Internals\InternalMessageLoopHook.cs</Link>
|
||||||
|
</Compile>
|
||||||
<Compile Include="..\NTwain\Internals\ITwainSessionInternal.cs">
|
<Compile Include="..\NTwain\Internals\ITwainSessionInternal.cs">
|
||||||
<Link>Internals\ITwainSessionInternal.cs</Link>
|
<Link>Internals\ITwainSessionInternal.cs</Link>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
<Compile Include="..\NTwain\Internals\IWinMessageFilter.cs">
|
||||||
|
<Link>Internals\IWinMessageFilter.cs</Link>
|
||||||
|
</Compile>
|
||||||
<Compile Include="..\NTwain\Internals\MESSAGE.cs">
|
<Compile Include="..\NTwain\Internals\MESSAGE.cs">
|
||||||
<Link>Internals\MESSAGE.cs</Link>
|
<Link>Internals\MESSAGE.cs</Link>
|
||||||
</Compile>
|
</Compile>
|
||||||
<Compile Include="..\NTwain\Internals\MessageLoop.cs">
|
|
||||||
<Link>Internals\MessageLoop.cs</Link>
|
|
||||||
</Compile>
|
|
||||||
<Compile Include="..\NTwain\Internals\TentativeStateCommitable.cs">
|
<Compile Include="..\NTwain\Internals\TentativeStateCommitable.cs">
|
||||||
<Link>Internals\TentativeStateCommitable.cs</Link>
|
<Link>Internals\TentativeStateCommitable.cs</Link>
|
||||||
</Compile>
|
</Compile>
|
||||||
@@ -106,8 +111,8 @@
|
|||||||
<Compile Include="..\NTwain\ITwainSession.cs">
|
<Compile Include="..\NTwain\ITwainSession.cs">
|
||||||
<Link>ITwainSession.cs</Link>
|
<Link>ITwainSession.cs</Link>
|
||||||
</Compile>
|
</Compile>
|
||||||
<Compile Include="..\NTwain\IWinMessageFilter.cs">
|
<Compile Include="..\NTwain\MessageLoopHooks.cs">
|
||||||
<Link>IWinMessageFilter.cs</Link>
|
<Link>MessageLoopHooks.cs</Link>
|
||||||
</Compile>
|
</Compile>
|
||||||
<Compile Include="..\NTwain\Platform.cs">
|
<Compile Include="..\NTwain\Platform.cs">
|
||||||
<Link>Platform.cs</Link>
|
<Link>Platform.cs</Link>
|
||||||
|
@@ -44,13 +44,24 @@ namespace NTwain
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
TwainSource ShowSourceSelector();
|
TwainSource ShowSourceSelector();
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 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="Close"/> when done with a TWAIN session.
|
/// before using other TWAIN functions. Calls to this must be followed by
|
||||||
|
/// <see cref="Close" /> when done with a TWAIN session.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
ReturnCode Open();
|
ReturnCode Open();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 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="Close" /> when done with a TWAIN session.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="messageLoopHook">The message loop hook.</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
ReturnCode Open(MessageLoopHook messageLoopHook);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Closes the data source manager.
|
/// Closes the data source manager.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@@ -14,7 +14,7 @@ namespace NTwain.Internals
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
TWIdentity AppId { get; }
|
TWIdentity AppId { get; }
|
||||||
|
|
||||||
MessageLoop SelfMessageLoop { get; }
|
MessageLoopHook MessageLoopHook { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets a value indicating whether calls to triplets will verify the current twain session state.
|
/// Gets or sets a value indicating whether calls to triplets will verify the current twain session state.
|
||||||
|
@@ -3,7 +3,7 @@ using System.Collections.Generic;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
namespace NTwain
|
namespace NTwain.Internals
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Interface for checking whether messages from WndProc is a TWAIN message and is handled
|
/// Interface for checking whether messages from WndProc is a TWAIN message and is handled
|
@@ -1,28 +1,27 @@
|
|||||||
using NTwain.Properties;
|
using NTwain.Properties;
|
||||||
using NTwain.Triplets;
|
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Windows.Threading;
|
using System.Windows.Threading;
|
||||||
|
|
||||||
namespace NTwain.Internals
|
namespace NTwain.Internals
|
||||||
{
|
{
|
||||||
/// <summary>
|
sealed class InternalMessageLoopHook : MessageLoopHook
|
||||||
/// Provides a message loop for old TWAIN to post or new TWAIN to synchronize callbacks.
|
|
||||||
/// </summary>
|
|
||||||
class MessageLoop
|
|
||||||
{
|
{
|
||||||
Dispatcher _dispatcher;
|
Dispatcher _dispatcher;
|
||||||
WindowsHook _hook;
|
WindowsHook _hook;
|
||||||
|
|
||||||
public void Stop()
|
internal override void Stop()
|
||||||
{
|
{
|
||||||
if (_dispatcher != null)
|
if (_dispatcher != null)
|
||||||
{
|
{
|
||||||
_dispatcher.InvokeShutdown();
|
_dispatcher.InvokeShutdown();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public void Start(IWinMessageFilter filter)
|
internal override void Start(IWinMessageFilter filter)
|
||||||
{
|
{
|
||||||
if (_dispatcher == null)
|
if (_dispatcher == null)
|
||||||
{
|
{
|
||||||
@@ -36,6 +35,7 @@ namespace NTwain.Internals
|
|||||||
if (!Platform.IsOnMono)
|
if (!Platform.IsOnMono)
|
||||||
{
|
{
|
||||||
_hook = new WindowsHook(filter);
|
_hook = new WindowsHook(filter);
|
||||||
|
Handle = _hook.Handle;
|
||||||
}
|
}
|
||||||
hack.Set();
|
hack.Set();
|
||||||
Dispatcher.Run();
|
Dispatcher.Run();
|
||||||
@@ -55,22 +55,14 @@ namespace NTwain.Internals
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public IntPtr LoopHandle
|
internal override void BeginInvoke(Action action)
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return _hook == null ? IntPtr.Zero : _hook.Handle;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void BeginInvoke(Action action)
|
|
||||||
{
|
{
|
||||||
if (_dispatcher == null) { throw new InvalidOperationException(Resources.MsgLoopUnavailble); }
|
if (_dispatcher == null) { throw new InvalidOperationException(Resources.MsgLoopUnavailble); }
|
||||||
|
|
||||||
_dispatcher.BeginInvoke(DispatcherPriority.Normal, action);
|
_dispatcher.BeginInvoke(DispatcherPriority.Normal, action);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Invoke(Action action)
|
internal override void Invoke(Action action)
|
||||||
{
|
{
|
||||||
if (_dispatcher == null) { throw new InvalidOperationException(Resources.MsgLoopUnavailble); }
|
if (_dispatcher == null) { throw new InvalidOperationException(Resources.MsgLoopUnavailble); }
|
||||||
|
|
189
NTwain/MessageLoopHooks.cs
Normal file
189
NTwain/MessageLoopHooks.cs
Normal file
@@ -0,0 +1,189 @@
|
|||||||
|
using NTwain.Internals;
|
||||||
|
using System;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Windows.Interop;
|
||||||
|
|
||||||
|
namespace NTwain
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// An abstract class for TWAIN to hook into windows message loops.
|
||||||
|
/// </summary>
|
||||||
|
public abstract class MessageLoopHook
|
||||||
|
{
|
||||||
|
internal IntPtr Handle { get; set; }
|
||||||
|
internal SynchronizationContext SyncContext { get; set; }
|
||||||
|
|
||||||
|
internal abstract void Start(IWinMessageFilter filter);
|
||||||
|
internal abstract void Stop();
|
||||||
|
|
||||||
|
internal virtual void BeginInvoke(Action action)
|
||||||
|
{
|
||||||
|
if (SyncContext == null)
|
||||||
|
{
|
||||||
|
action();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SyncContext.Post(o =>
|
||||||
|
{
|
||||||
|
action();
|
||||||
|
}, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
internal virtual void Invoke(Action action)
|
||||||
|
{
|
||||||
|
if (SyncContext == null)
|
||||||
|
{
|
||||||
|
action();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SyncContext.Send(o =>
|
||||||
|
{
|
||||||
|
action();
|
||||||
|
}, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void ThrowInvalidOp()
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException(InvalidMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal virtual string InvalidMessage { get { return string.Empty; } }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A <see cref="MessageLoopHook"/> for use in winform applications.
|
||||||
|
/// </summary>
|
||||||
|
public sealed class WindowsFormsMessageLoopHook : MessageLoopHook, System.Windows.Forms.IMessageFilter
|
||||||
|
{
|
||||||
|
IWinMessageFilter _filter;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="WindowsFormsMessageLoopHook"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="hwnd">The handle to the app window.</param>
|
||||||
|
/// <exception cref="System.ArgumentException">A valid window handle is required.</exception>
|
||||||
|
public WindowsFormsMessageLoopHook(IntPtr hwnd)
|
||||||
|
{
|
||||||
|
if (hwnd == IntPtr.Zero) { throw new ArgumentException("A valid window handle is required."); }
|
||||||
|
|
||||||
|
if (!System.Windows.Forms.Application.MessageLoop)
|
||||||
|
{
|
||||||
|
ThrowInvalidOp();
|
||||||
|
}
|
||||||
|
var sync = SynchronizationContext.Current;
|
||||||
|
if (sync == null)
|
||||||
|
{
|
||||||
|
ThrowInvalidOp();
|
||||||
|
}
|
||||||
|
Handle = hwnd;
|
||||||
|
SyncContext = sync;
|
||||||
|
}
|
||||||
|
internal override string InvalidMessage
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return "This can only be created on the Windows Forms UI thread.";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal override void Start(IWinMessageFilter filter)
|
||||||
|
{
|
||||||
|
//Invoke(() =>
|
||||||
|
//{
|
||||||
|
_filter = filter;
|
||||||
|
System.Windows.Forms.Application.AddMessageFilter(this);
|
||||||
|
//});
|
||||||
|
}
|
||||||
|
|
||||||
|
internal override void Stop()
|
||||||
|
{
|
||||||
|
//Invoke(() =>
|
||||||
|
//{
|
||||||
|
System.Windows.Forms.Application.RemoveMessageFilter(this);
|
||||||
|
_filter = null;
|
||||||
|
//});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#region IMessageFilter Members
|
||||||
|
|
||||||
|
bool System.Windows.Forms.IMessageFilter.PreFilterMessage(ref System.Windows.Forms.Message m)
|
||||||
|
{
|
||||||
|
if (_filter != null)
|
||||||
|
{
|
||||||
|
return _filter.IsTwainMessage(m.HWnd, m.Msg, m.WParam, m.LParam);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A <see cref="MessageLoopHook"/> for use in WPF applications.
|
||||||
|
/// </summary>
|
||||||
|
public sealed class WpfMessageLoopHook : MessageLoopHook
|
||||||
|
{
|
||||||
|
HwndSource _hooker;
|
||||||
|
IWinMessageFilter _filter;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="WpfMessageLoopHook"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="hwnd">The handle to the app window.</param>
|
||||||
|
/// <exception cref="System.ArgumentException">A valid window handle is required.</exception>
|
||||||
|
public WpfMessageLoopHook(IntPtr hwnd)
|
||||||
|
{
|
||||||
|
if (hwnd == IntPtr.Zero) { throw new ArgumentException("A valid window handle is required."); }
|
||||||
|
|
||||||
|
if (System.Windows.Application.Current == null ||
|
||||||
|
!System.Windows.Application.Current.Dispatcher.CheckAccess())
|
||||||
|
{
|
||||||
|
ThrowInvalidOp();
|
||||||
|
}
|
||||||
|
var sync = SynchronizationContext.Current;
|
||||||
|
if (sync == null)
|
||||||
|
{
|
||||||
|
ThrowInvalidOp();
|
||||||
|
}
|
||||||
|
Handle = hwnd;
|
||||||
|
SyncContext = sync;
|
||||||
|
}
|
||||||
|
internal override string InvalidMessage
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return "This can only be created on the WPF UI thread.";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal override void Start(IWinMessageFilter filter)
|
||||||
|
{
|
||||||
|
_filter = filter;
|
||||||
|
_hooker = HwndSource.FromHwnd(Handle);
|
||||||
|
_hooker.AddHook(FilterMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
private IntPtr FilterMessage(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
|
||||||
|
{
|
||||||
|
if (_filter != null)
|
||||||
|
{
|
||||||
|
handled = _filter.IsTwainMessage(hwnd, msg, wParam, lParam);
|
||||||
|
}
|
||||||
|
return IntPtr.Zero;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal override void Stop()
|
||||||
|
{
|
||||||
|
if (_hooker != null)
|
||||||
|
{
|
||||||
|
_hooker.RemoveHook(FilterMessage);
|
||||||
|
_hooker.Dispose();
|
||||||
|
_hooker = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -48,7 +48,10 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Reference Include="PresentationCore" />
|
<Reference Include="PresentationCore" />
|
||||||
|
<Reference Include="PresentationFramework" />
|
||||||
<Reference Include="System" />
|
<Reference Include="System" />
|
||||||
|
<Reference Include="System.Windows.Forms" />
|
||||||
|
<Reference Include="System.Xaml" />
|
||||||
<Reference Include="WindowsBase" />
|
<Reference Include="WindowsBase" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
@@ -60,6 +63,7 @@
|
|||||||
<Compile Include="DataTransferredEventArgs.cs" />
|
<Compile Include="DataTransferredEventArgs.cs" />
|
||||||
<Compile Include="IMemoryManager.cs" />
|
<Compile Include="IMemoryManager.cs" />
|
||||||
<Compile Include="Internals\ICommittable.cs" />
|
<Compile Include="Internals\ICommittable.cs" />
|
||||||
|
<Compile Include="Internals\InternalMessageLoopHook.cs" />
|
||||||
<Compile Include="Internals\ITwainSessionInternal.cs" />
|
<Compile Include="Internals\ITwainSessionInternal.cs" />
|
||||||
<Compile Include="Internals\MESSAGE.cs" />
|
<Compile Include="Internals\MESSAGE.cs" />
|
||||||
<Compile Include="Internals\TransferLogic.cs" />
|
<Compile Include="Internals\TransferLogic.cs" />
|
||||||
@@ -67,9 +71,9 @@
|
|||||||
<Compile Include="Internals\WrappedManualResetEvent.cs" />
|
<Compile Include="Internals\WrappedManualResetEvent.cs" />
|
||||||
<Compile Include="ITwainSession.cs" />
|
<Compile Include="ITwainSession.cs" />
|
||||||
<Compile Include="Internals\WinMemoryManager.cs" />
|
<Compile Include="Internals\WinMemoryManager.cs" />
|
||||||
<Compile Include="Internals\MessageLoop.cs" />
|
|
||||||
<Compile Include="Internals\UnsafeNativeMethods.cs" />
|
<Compile Include="Internals\UnsafeNativeMethods.cs" />
|
||||||
<Compile Include="IWinMessageFilter.cs" />
|
<Compile Include="Internals\IWinMessageFilter.cs" />
|
||||||
|
<Compile Include="MessageLoopHooks.cs" />
|
||||||
<Compile Include="Platform.cs" />
|
<Compile Include="Platform.cs" />
|
||||||
<Compile Include="Properties\Resources.Designer.cs">
|
<Compile Include="Properties\Resources.Designer.cs">
|
||||||
<AutoGen>True</AutoGen>
|
<AutoGen>True</AutoGen>
|
||||||
|
@@ -41,15 +41,13 @@ namespace NTwain
|
|||||||
_appId = appId;
|
_appId = appId;
|
||||||
((ITwainSessionInternal)this).ChangeState(1, false);
|
((ITwainSessionInternal)this).ChangeState(1, false);
|
||||||
EnforceState = true;
|
EnforceState = true;
|
||||||
|
|
||||||
_selfMsgLoop = new MessageLoop();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
|
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
|
||||||
object _callbackObj; // kept around so it doesn't get gc'ed
|
object _callbackObj; // kept around so it doesn't get gc'ed
|
||||||
TWIdentity _appId;
|
TWIdentity _appId;
|
||||||
TWUserInterface _twui;
|
TWUserInterface _twui;
|
||||||
|
|
||||||
|
|
||||||
static readonly Dictionary<string, TwainSource> __ownedSources = new Dictionary<string, TwainSource>();
|
static readonly Dictionary<string, TwainSource> __ownedSources = new Dictionary<string, TwainSource>();
|
||||||
|
|
||||||
@@ -64,9 +62,8 @@ namespace NTwain
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the optional synchronization context.
|
/// Gets or sets the optional synchronization context when not specifying a <see cref="MessageLoopHook"/> on <see cref="Open"/>.
|
||||||
/// This allows events to be raised on the thread
|
/// This allows events to be raised on the thread associated with the context. This is experimental is not recommended for use.
|
||||||
/// associated with the context.
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>
|
/// <value>
|
||||||
/// The synchronization context.
|
/// The synchronization context.
|
||||||
@@ -76,8 +73,8 @@ namespace NTwain
|
|||||||
|
|
||||||
#region ITwainSessionInternal Members
|
#region ITwainSessionInternal Members
|
||||||
|
|
||||||
MessageLoop _selfMsgLoop;
|
MessageLoopHook _msgLoopHook;
|
||||||
MessageLoop ITwainSessionInternal.SelfMessageLoop { get { return _selfMsgLoop; } }
|
MessageLoopHook ITwainSessionInternal.MessageLoopHook { get { return _msgLoopHook; } }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the app id used for the session.
|
/// Gets the app id used for the session.
|
||||||
@@ -246,18 +243,35 @@ namespace NTwain
|
|||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 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="Close"/> when done with a TWAIN session.
|
/// before using other TWAIN functions. Calls to this must be followed by
|
||||||
|
/// <see cref="Close" /> when done with a TWAIN session.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns
|
||||||
public ReturnCode Open()
|
public ReturnCode Open()
|
||||||
{
|
{
|
||||||
_selfMsgLoop.Start(this);
|
return Open(new InternalMessageLoopHook());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 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="Close" /> when done with a TWAIN session.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="messageLoopHook">The message loop hook.</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
/// <exception cref="System.ArgumentNullException">messageLoopHook</exception>
|
||||||
|
public ReturnCode Open(MessageLoopHook messageLoopHook)
|
||||||
|
{
|
||||||
|
if (messageLoopHook == null) { throw new ArgumentNullException("messageLoopHook"); }
|
||||||
|
|
||||||
|
_msgLoopHook = messageLoopHook;
|
||||||
|
_msgLoopHook.Start(this);
|
||||||
var rc = ReturnCode.Failure;
|
var rc = ReturnCode.Failure;
|
||||||
_selfMsgLoop.Invoke(() =>
|
_msgLoopHook.Invoke(() =>
|
||||||
{
|
{
|
||||||
Debug.WriteLine(string.Format(CultureInfo.InvariantCulture, "Thread {0}: OpenManager.", Thread.CurrentThread.ManagedThreadId));
|
Debug.WriteLine(string.Format(CultureInfo.InvariantCulture, "Thread {0}: OpenManager.", Thread.CurrentThread.ManagedThreadId));
|
||||||
|
|
||||||
rc = ((ITwainSessionInternal)this).DGControl.Parent.OpenDsm(_selfMsgLoop.LoopHandle);
|
rc = ((ITwainSessionInternal)this).DGControl.Parent.OpenDsm(_msgLoopHook.Handle);
|
||||||
if (rc == ReturnCode.Success)
|
if (rc == ReturnCode.Success)
|
||||||
{
|
{
|
||||||
// if twain2 then get memory management functions
|
// if twain2 then get memory management functions
|
||||||
@@ -287,15 +301,15 @@ namespace NTwain
|
|||||||
public ReturnCode Close()
|
public ReturnCode Close()
|
||||||
{
|
{
|
||||||
var rc = ReturnCode.Failure;
|
var rc = ReturnCode.Failure;
|
||||||
_selfMsgLoop.Invoke(() =>
|
_msgLoopHook.Invoke(() =>
|
||||||
{
|
{
|
||||||
Debug.WriteLine(string.Format(CultureInfo.InvariantCulture, "Thread {0}: CloseManager.", Thread.CurrentThread.ManagedThreadId));
|
Debug.WriteLine(string.Format(CultureInfo.InvariantCulture, "Thread {0}: CloseManager.", Thread.CurrentThread.ManagedThreadId));
|
||||||
|
|
||||||
rc = ((ITwainSessionInternal)this).DGControl.Parent.CloseDsm(_selfMsgLoop.LoopHandle);
|
rc = ((ITwainSessionInternal)this).DGControl.Parent.CloseDsm(_msgLoopHook.Handle);
|
||||||
if (rc == ReturnCode.Success)
|
if (rc == ReturnCode.Success)
|
||||||
{
|
{
|
||||||
Platform.MemoryManager = null;
|
Platform.MemoryManager = null;
|
||||||
_selfMsgLoop.Stop();
|
_msgLoopHook.Stop();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return rc;
|
return rc;
|
||||||
@@ -396,7 +410,7 @@ namespace NTwain
|
|||||||
{
|
{
|
||||||
var rc = ReturnCode.Failure;
|
var rc = ReturnCode.Failure;
|
||||||
|
|
||||||
_selfMsgLoop.Invoke(() =>
|
_msgLoopHook.Invoke(() =>
|
||||||
{
|
{
|
||||||
Debug.WriteLine(string.Format(CultureInfo.InvariantCulture, "Thread {0}: EnableSource.", Thread.CurrentThread.ManagedThreadId));
|
Debug.WriteLine(string.Format(CultureInfo.InvariantCulture, "Thread {0}: EnableSource.", Thread.CurrentThread.ManagedThreadId));
|
||||||
|
|
||||||
@@ -451,7 +465,7 @@ namespace NTwain
|
|||||||
{
|
{
|
||||||
var rc = ReturnCode.Failure;
|
var rc = ReturnCode.Failure;
|
||||||
|
|
||||||
_selfMsgLoop.Invoke(() =>
|
_msgLoopHook.Invoke(() =>
|
||||||
{
|
{
|
||||||
Debug.WriteLine(string.Format(CultureInfo.InvariantCulture, "Thread {0}: DisableSource.", Thread.CurrentThread.ManagedThreadId));
|
Debug.WriteLine(string.Format(CultureInfo.InvariantCulture, "Thread {0}: DisableSource.", Thread.CurrentThread.ManagedThreadId));
|
||||||
|
|
||||||
@@ -492,7 +506,7 @@ namespace NTwain
|
|||||||
// success, the return status from DG_CONTROL / DAT_PENDINGXFERS / MSG_ENDXFER may
|
// success, the return status from DG_CONTROL / DAT_PENDINGXFERS / MSG_ENDXFER may
|
||||||
// be ignored.
|
// be ignored.
|
||||||
|
|
||||||
_selfMsgLoop.Invoke(() =>
|
_msgLoopHook.Invoke(() =>
|
||||||
{
|
{
|
||||||
if (targetState < 7)
|
if (targetState < 7)
|
||||||
{
|
{
|
||||||
@@ -721,7 +735,7 @@ namespace NTwain
|
|||||||
// 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.
|
||||||
// by using the internal dispatcher this will be the case.
|
// by using the internal dispatcher this will be the case.
|
||||||
|
|
||||||
_selfMsgLoop.BeginInvoke(() =>
|
_msgLoopHook.BeginInvoke(() =>
|
||||||
{
|
{
|
||||||
HandleSourceMsg(msg);
|
HandleSourceMsg(msg);
|
||||||
});
|
});
|
||||||
|
@@ -32,7 +32,7 @@ namespace NTwain
|
|||||||
public ReturnCode Open()
|
public ReturnCode Open()
|
||||||
{
|
{
|
||||||
var rc = ReturnCode.Failure;
|
var rc = ReturnCode.Failure;
|
||||||
_session.SelfMessageLoop.Invoke(() =>
|
_session.MessageLoopHook.Invoke(() =>
|
||||||
{
|
{
|
||||||
Debug.WriteLine(string.Format(CultureInfo.InvariantCulture, "Thread {0}: OpenSource.", Thread.CurrentThread.ManagedThreadId));
|
Debug.WriteLine(string.Format(CultureInfo.InvariantCulture, "Thread {0}: OpenSource.", Thread.CurrentThread.ManagedThreadId));
|
||||||
|
|
||||||
@@ -48,7 +48,7 @@ namespace NTwain
|
|||||||
public ReturnCode Close()
|
public ReturnCode Close()
|
||||||
{
|
{
|
||||||
var rc = ReturnCode.Failure;
|
var rc = ReturnCode.Failure;
|
||||||
_session.SelfMessageLoop.Invoke(() =>
|
_session.MessageLoopHook.Invoke(() =>
|
||||||
{
|
{
|
||||||
Debug.WriteLine(string.Format(CultureInfo.InvariantCulture, "Thread {0}: CloseSource.", Thread.CurrentThread.ManagedThreadId));
|
Debug.WriteLine(string.Format(CultureInfo.InvariantCulture, "Thread {0}: CloseSource.", Thread.CurrentThread.ManagedThreadId));
|
||||||
|
|
||||||
|
@@ -65,7 +65,11 @@ namespace Tester.WPF
|
|||||||
{
|
{
|
||||||
base.OnSourceInitialized(e);
|
base.OnSourceInitialized(e);
|
||||||
|
|
||||||
var rc = _twainVM.Open();
|
// use this for internal msg loop
|
||||||
|
//var rc = _twainVM.Open();
|
||||||
|
// use this to hook into current app loop
|
||||||
|
var rc = _twainVM.Open(new WpfMessageLoopHook(new WindowInteropHelper(this).Handle));
|
||||||
|
|
||||||
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 });
|
||||||
|
@@ -3,17 +3,17 @@ using System.Windows.Forms;
|
|||||||
|
|
||||||
namespace Tester.Winform
|
namespace Tester.Winform
|
||||||
{
|
{
|
||||||
static class Program
|
static class Program
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The main entry point for the application.
|
/// The main entry point for the application.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[STAThread]
|
[STAThread]
|
||||||
static void Main()
|
static void Main()
|
||||||
{
|
{
|
||||||
Application.EnableVisualStyles();
|
Application.EnableVisualStyles();
|
||||||
Application.SetCompatibleTextRenderingDefault(false);
|
Application.SetCompatibleTextRenderingDefault(false);
|
||||||
Application.Run(new TestForm());
|
Application.Run(new TestForm());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -239,7 +239,10 @@ namespace Tester.Winform
|
|||||||
}
|
}
|
||||||
if (_twain.State < 3)
|
if (_twain.State < 3)
|
||||||
{
|
{
|
||||||
|
// use this for internal msg loop
|
||||||
_twain.Open();
|
_twain.Open();
|
||||||
|
// use this to hook into current app loop
|
||||||
|
//_twain.Open(new WinformMessageLoopHook(this.Handle));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_twain.State >= 3)
|
if (_twain.State >= 3)
|
||||||
|
Reference in New Issue
Block a user