From 2dc64224ae8de97eddde6d8b7895c24ec259789e Mon Sep 17 00:00:00 2001 From: soukoku Date: Fri, 23 May 2014 19:01:18 -0400 Subject: [PATCH 1/2] Exposed public triplets through twain source class instead. --- NTwain/ITwainSession.cs | 20 -------- NTwain/Internals/ITwainSessionInternal.cs | 21 ++++++++ NTwain/Triplets/DGAudio/DGAudio.cs | 2 +- NTwain/TwainSession.cs | 59 ++++++++++------------- NTwain/TwainSource.cs | 35 ++++++++++++++ 5 files changed, 83 insertions(+), 54 deletions(-) diff --git a/NTwain/ITwainSession.cs b/NTwain/ITwainSession.cs index 8669769..4bc9b3a 100644 --- a/NTwain/ITwainSession.cs +++ b/NTwain/ITwainSession.cs @@ -37,26 +37,6 @@ namespace NTwain /// The state. int State { get; } - /// - /// Gets the triplet operations defined for audio data group. - /// - DGAudio DGAudio { get; } - - /// - /// Gets the triplet operations defined for control data group. - /// - DGControl DGControl { get; } - - /// - /// Gets the triplet operations defined for image data group. - /// - DGImage DGImage { get; } - - /// - /// Gets the direct triplet operation entry for custom values. - /// - DGCustom DGCustom { get; } - /// /// Try to show the built-in source selector dialog and return the selected source. /// This is not recommended and is only included for completeness. diff --git a/NTwain/Internals/ITwainSessionInternal.cs b/NTwain/Internals/ITwainSessionInternal.cs index 32e837d..f9c9603 100644 --- a/NTwain/Internals/ITwainSessionInternal.cs +++ b/NTwain/Internals/ITwainSessionInternal.cs @@ -1,4 +1,5 @@ using NTwain.Data; +using NTwain.Triplets; using System; using System.Collections.Generic; using System.Threading; @@ -46,5 +47,25 @@ namespace NTwain.Internals ReturnCode EnableSource(SourceEnableMode mode, bool modal, IntPtr windowHandle); SynchronizationContext SynchronizationContext { get; set; } + + /// + /// Gets the triplet operations defined for audio data group. + /// + DGAudio DGAudio { get; } + + /// + /// Gets the triplet operations defined for control data group. + /// + DGControl DGControl { get; } + + /// + /// Gets the triplet operations defined for image data group. + /// + DGImage DGImage { get; } + + /// + /// Gets the direct triplet operation entry for custom values. + /// + DGCustom DGCustom { get; } } } diff --git a/NTwain/Triplets/DGAudio/DGAudio.cs b/NTwain/Triplets/DGAudio/DGAudio.cs index 8d6ff17..a644eda 100644 --- a/NTwain/Triplets/DGAudio/DGAudio.cs +++ b/NTwain/Triplets/DGAudio/DGAudio.cs @@ -6,7 +6,7 @@ namespace NTwain.Triplets /// /// Represents . /// - public sealed class DGAudio + sealed class DGAudio { ITwainSessionInternal _session; internal DGAudio(ITwainSessionInternal session) diff --git a/NTwain/TwainSession.cs b/NTwain/TwainSession.cs index be6e649..9c0e4e9 100644 --- a/NTwain/TwainSession.cs +++ b/NTwain/TwainSession.cs @@ -62,7 +62,7 @@ namespace NTwain return __ownedSources[key] = new TwainSource(session, sourceId); } - + /// /// Gets or sets the optional synchronization context. @@ -151,7 +151,7 @@ namespace NTwain get { TWIdentity id; - if (DGControl.Identity.GetDefault(out id) == ReturnCode.Success) + if (((ITwainSessionInternal)this).DGControl.Identity.GetDefault(out id) == ReturnCode.Success) { return GetSourceInstance(this, id); } @@ -161,7 +161,7 @@ namespace NTwain { if (value != null) { - DGControl.Identity.Set(value.Identity); + ((ITwainSessionInternal)this).DGControl.Identity.Set(value.Identity); } } } @@ -174,7 +174,7 @@ namespace NTwain public TwainSource ShowSourceSelector() { TWIdentity id; - if (DGControl.Identity.UserSelect(out id) == ReturnCode.Success) + if (((ITwainSessionInternal)this).DGControl.Identity.UserSelect(out id) == ReturnCode.Success) { return GetSourceInstance(this, id); } @@ -210,7 +210,7 @@ namespace NTwain /// /// Gets the triplet operations defined for audio data group. /// - public DGAudio DGAudio + DGAudio ITwainSessionInternal.DGAudio { get { @@ -220,10 +220,7 @@ namespace NTwain } DGControl _dgControl; - /// - /// Gets the triplet operations defined for control data group. - /// - public DGControl DGControl + DGControl ITwainSessionInternal.DGControl { get { @@ -233,10 +230,7 @@ namespace NTwain } DGImage _dgImage; - /// - /// Gets the triplet operations defined for image data group. - /// - public DGImage DGImage + DGImage ITwainSessionInternal.DGImage { get { @@ -246,10 +240,7 @@ namespace NTwain } DGCustom _dgCustom; - /// - /// Gets the direct triplet operation entry for custom values. - /// - public DGCustom DGCustom + DGCustom ITwainSessionInternal.DGCustom { get { @@ -257,6 +248,7 @@ namespace NTwain return _dgCustom; } } + /// /// Opens the data source manager. This must be the first method used /// before using other TWAIN functions. Calls to this must be followed by when done with a TWAIN session. @@ -269,14 +261,14 @@ namespace NTwain { Debug.WriteLine(string.Format(CultureInfo.InvariantCulture, "Thread {0}: OpenManager.", Thread.CurrentThread.ManagedThreadId)); - rc = DGControl.Parent.OpenDsm(MessageLoop.Instance.LoopHandle); + rc = ((ITwainSessionInternal)this).DGControl.Parent.OpenDsm(MessageLoop.Instance.LoopHandle); if (rc == ReturnCode.Success) { // if twain2 then get memory management functions if ((_appId.DataFunctionalities & DataFunctionalities.Dsm2) == DataFunctionalities.Dsm2) { TWEntryPoint entry; - rc = DGControl.EntryPoint.Get(out entry); + rc = ((ITwainSessionInternal)this).DGControl.EntryPoint.Get(out entry); if (rc == ReturnCode.Success) { Platform.MemoryManager = entry; @@ -303,7 +295,7 @@ namespace NTwain { Debug.WriteLine(string.Format(CultureInfo.InvariantCulture, "Thread {0}: CloseManager.", Thread.CurrentThread.ManagedThreadId)); - rc = DGControl.Parent.CloseDsm(MessageLoop.Instance.LoopHandle); + rc = ((ITwainSessionInternal)this).DGControl.Parent.CloseDsm(MessageLoop.Instance.LoopHandle); if (rc == ReturnCode.Success) { Platform.MemoryManager = null; @@ -321,13 +313,14 @@ namespace NTwain public IEnumerable GetSources() { TWIdentity srcId; - var rc = DGControl.Identity.GetFirst(out srcId); + var rc = ((ITwainSessionInternal)this).DGControl.Identity.GetFirst(out srcId); while (rc == ReturnCode.Success) { yield return GetSourceInstance(this, srcId); - rc = DGControl.Identity.GetNext(out srcId); + rc = ((ITwainSessionInternal)this).DGControl.Identity.GetNext(out srcId); } } + /// /// Gets the manager status. Only call this at state 2 or higher. /// @@ -335,7 +328,7 @@ namespace NTwain public TWStatus GetStatus() { TWStatus stat; - DGControl.Status.GetManager(out stat); + ((ITwainSessionInternal)this).DGControl.Status.GetManager(out stat); return stat; } @@ -346,7 +339,7 @@ namespace NTwain public TWStatusUtf8 GetStatusUtf8() { TWStatusUtf8 stat; - DGControl.StatusUtf8.GetManager(out stat); + ((ITwainSessionInternal)this).DGControl.StatusUtf8.GetManager(out stat); return stat; } @@ -414,7 +407,7 @@ namespace NTwain if (_appId.ProtocolMajor >= 2 && _appId.ProtocolMinor >= 2) { var cb = new TWCallback2(HandleCallback); - var rc2 = DGControl.Callback2.RegisterCallback(cb); + var rc2 = ((ITwainSessionInternal)this).DGControl.Callback2.RegisterCallback(cb); if (rc2 == ReturnCode.Success) { @@ -426,7 +419,7 @@ namespace NTwain { var cb = new TWCallback(HandleCallback); - var rc2 = DGControl.Callback.RegisterCallback(cb); + var rc2 = ((ITwainSessionInternal)this).DGControl.Callback.RegisterCallback(cb); if (rc2 == ReturnCode.Success) { @@ -442,11 +435,11 @@ namespace NTwain if (mode == SourceEnableMode.ShowUIOnly) { - rc = DGControl.UserInterface.EnableDSUIOnly(_twui); + rc = ((ITwainSessionInternal)this).DGControl.UserInterface.EnableDSUIOnly(_twui); } else { - rc = DGControl.UserInterface.EnableDS(_twui); + rc = ((ITwainSessionInternal)this).DGControl.UserInterface.EnableDS(_twui); } if (rc != ReturnCode.Success) @@ -465,7 +458,7 @@ namespace NTwain { Debug.WriteLine(string.Format(CultureInfo.InvariantCulture, "Thread {0}: DisableSource.", Thread.CurrentThread.ManagedThreadId)); - rc = DGControl.UserInterface.DisableDS(_twui); + rc = ((ITwainSessionInternal)this).DGControl.UserInterface.DisableDS(_twui); if (rc == ReturnCode.Success) { _callbackObj = null; @@ -506,11 +499,11 @@ namespace NTwain { if (targetState < 7) { - DGControl.PendingXfers.EndXfer(new TWPendingXfers()); + ((ITwainSessionInternal)this).DGControl.PendingXfers.EndXfer(new TWPendingXfers()); } if (targetState < 6) { - DGControl.PendingXfers.Reset(new TWPendingXfers()); + ((ITwainSessionInternal)this).DGControl.PendingXfers.Reset(new TWPendingXfers()); } if (targetState < 5) { @@ -690,7 +683,7 @@ namespace NTwain var evt = new TWEvent(); evt.pEvent = msgPtr; - if (handled = (DGControl.Event.ProcessEvent(evt) == ReturnCode.DSEvent)) + if (handled = (((ITwainSessionInternal)this).DGControl.Event.ProcessEvent(evt) == ReturnCode.DSEvent)) { Debug.WriteLine(string.Format(CultureInfo.InvariantCulture, "Thread {0}: HandleWndProcMessage at state {1} with MSG={2}.", Thread.CurrentThread.ManagedThreadId, State, evt.TWMessage)); @@ -735,7 +728,7 @@ namespace NTwain break; case Message.DeviceEvent: TWDeviceEvent de; - var rc = DGControl.DeviceEvent.Get(out de); + var rc = ((ITwainSessionInternal)this).DGControl.DeviceEvent.Get(out de); if (rc == ReturnCode.Success) { SafeSyncableRaiseOnEvent(OnDeviceEvent, DeviceEvent, new DeviceEventArgs(de)); diff --git a/NTwain/TwainSource.cs b/NTwain/TwainSource.cs index 0eac398..2e514d8 100644 --- a/NTwain/TwainSource.cs +++ b/NTwain/TwainSource.cs @@ -1,5 +1,6 @@ using NTwain.Data; using NTwain.Internals; +using NTwain.Triplets; using System; using System.Collections.Generic; using System.ComponentModel; @@ -182,6 +183,40 @@ namespace NTwain } } + + /// + /// Gets the triplet operations defined for control data group. + /// + public DGControl DGControl + { + get + { + return _session.DGControl; + } + } + + /// + /// Gets the triplet operations defined for image data group. + /// + public DGImage DGImage + { + get + { + return _session.DGImage; + } + } + + /// + /// Gets the direct triplet operation entry for custom values. + /// + public DGCustom DGCustom + { + get + { + return _session.DGCustom; + } + } + #endregion #region INotifyPropertyChanged Members From ebb75526017836b0939e1df8ad416805afe96e09 Mon Sep 17 00:00:00 2001 From: soukoku Date: Fri, 23 May 2014 19:18:07 -0400 Subject: [PATCH 2/2] Updated readme to refect new things. --- README.md | 79 +++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 50 insertions(+), 29 deletions(-) diff --git a/README.md b/README.md index 1d46a43..9e0108f 100644 --- a/README.md +++ b/README.md @@ -19,10 +19,9 @@ To properly use this lib you will need to be reasonably familiar with the TWAIN and how it works in general (especially capability). The spec can be downloaded from [twain.org](http://twain.org/). -Except for certain "important" state-changing calls that have been -abstract away, most triplet operations are +Except for those that have been abstracted away with .net equivalents, most triplet operations are provided as-is so you will need to know when and how to use them. -There are no high-level, single-line scan-a-page-for-me-now functions. +There are no high-level, single-line scan-a-page-for-me-now functions yet. The main class to use is TwainSession. You can either use it directly by subscribing to the important events or sub-class it and override the OnMethods related to those events. @@ -40,6 +39,9 @@ var session = new TwainSession(appId); session.TransferReady += ... session.DataTransferred += ... +// finally open it +session.Open(); + ``` TwainSession class provides many events, but these 2 are the most important @@ -50,23 +52,44 @@ or all subsequent transfers using the event object. what you've specified using the TWAIN API before starting the transfer. -To get into transfer mode, you'll have to call these methods after setting up the session: - -1. OpenManager() - opens the TWAIN data source manager (DSM). You can really keep this open throughout the app life time with no ill effect. -2. OpenSource() - opens a target device. You can continue to open and close sources as long as DSM is open. -3. EnableSource() - starts transferring - -After transfer has completed (you are notified of this with the SourceDisabled event) -and you're done with TWAIN, you can call their equivalents in correct hierarchical order like html - -1. CloseSource() -2. CloseManager() +Once you've setup and opened the session, you can get available sources, pick one to use, +and call Open() to start using it. -While most TWAIN APIs are done via the low-level triplet calls, this lib does provide some -commonly used functions as extension methods to TwainSession (especially capability functions). -This should make setting simple things such as DPI, bitdepth, or paper size easier. -More of these extensions may come in later versions. +``` +#!c# + +// choose and open a source +IEnumerable sources = session.GetSources(); +var myDS = sources.First(); +myDS.Open(); + +``` + +At this point you can negotiate with the source using all the typical TWAIN triplet API. +The TwainSource class itself has some handy pre-defined methods for common capability negotiation +such as DPI, bitdepth, or paper size to get you started. + +When you're ready to get into transfer mode, just call StartTransfer() on the source object. + +``` +#!c# + +var myDS = sources.StartTransfer(...); + +``` + +After transfer has completed (you are notified of this with the SourceDisabled event from session) +and you're done with TWAIN, you can close the source and the session in sequence to clean things up. + +``` +#!c# + +myDS.Close(); +session.Close(); + +``` + Caveats -------------------------------------- @@ -74,12 +97,9 @@ At the moment this lib does not provide ways to parse transferred image data and consumers to do the conversion themselves. The winform project contains one such example for handling DIB image in native transfer using the CommonWin32 lib. -Because it hosts its own message thread, the events will likely be raised from another thread. +Because it hosts its own message thread, the events will be raised from another thread. If you would like things marshalled to a UI thread then set the SynchronizationContext property -to the one from the UI thread. Note that on certain consumer-grade scanner drivers this may hang the -event, so if you find yourself in that position you'll have to find another way -to synchronize data to UI threads. - +to the one from the UI thread. ``` #!c# @@ -87,17 +107,18 @@ to synchronize data to UI threads. session.SynchronizationContext = SynchronizationContext.Current; ``` +Note that on certain scanner drivers this may hang the +application due to their use of modal dialogs, so if you find yourself in that position +you'll have to find another way to synchronize data to UI threads. + 64-bit OS -------------------------------------- If the application process is running in 64-bit then you will need to make sure you have the newer data source manager (twaindsm.dll) from below installed. + [DSM from TWAIN.org](http://sourceforge.net/projects/twain-dsm/files/TWAIN%20DSM%202%20Win/) Otherwise just compile and run the app as x86 and it'll use the 32-bit version (twain_32.dll) that comes with Windows. - -Note that there are no known 64-bit TWAIN DS drivers at the time of writing, so most likely you will have to -compile the application as x86 or run on 32-bit OS to work with a real device. -If you really want to test in 64-bit for whatever reason, you can use -the test one from TWAIN.org below. -[Sample DS from TWAIN.org](http://sourceforge.net/projects/twain-samples/files/TWAIN%202%20Sample%20Data%20Source/TWAIN%20DS%202.1.3/) \ No newline at end of file +If your scanner driver is still 32-bit (and most likely it will be) you'll have no choice but to +compile as x86 anyway, even if you have installed the newer dsm dll.