Merged wrapper-idea into master

This commit is contained in:
Eugene Wang
2014-05-23 19:23:26 -04:00
6 changed files with 133 additions and 83 deletions
-20
View File
@@ -37,26 +37,6 @@ namespace NTwain
/// <value>The state.</value> /// <value>The state.</value>
int State { get; } int State { get; }
/// <summary>
/// Gets the triplet operations defined for audio data group.
/// </summary>
DGAudio DGAudio { get; }
/// <summary>
/// Gets the triplet operations defined for control data group.
/// </summary>
DGControl DGControl { get; }
/// <summary>
/// Gets the triplet operations defined for image data group.
/// </summary>
DGImage DGImage { get; }
/// <summary>
/// Gets the direct triplet operation entry for custom values.
/// </summary>
DGCustom DGCustom { get; }
/// <summary> /// <summary>
/// Try to show the built-in source selector dialog and return the selected source. /// Try to show the built-in source selector dialog and return the selected source.
/// This is not recommended and is only included for completeness. /// This is not recommended and is only included for completeness.
+21
View File
@@ -1,4 +1,5 @@
using NTwain.Data; using NTwain.Data;
using NTwain.Triplets;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Threading; using System.Threading;
@@ -46,5 +47,25 @@ namespace NTwain.Internals
ReturnCode EnableSource(SourceEnableMode mode, bool modal, IntPtr windowHandle); ReturnCode EnableSource(SourceEnableMode mode, bool modal, IntPtr windowHandle);
SynchronizationContext SynchronizationContext { get; set; } SynchronizationContext SynchronizationContext { get; set; }
/// <summary>
/// Gets the triplet operations defined for audio data group.
/// </summary>
DGAudio DGAudio { get; }
/// <summary>
/// Gets the triplet operations defined for control data group.
/// </summary>
DGControl DGControl { get; }
/// <summary>
/// Gets the triplet operations defined for image data group.
/// </summary>
DGImage DGImage { get; }
/// <summary>
/// Gets the direct triplet operation entry for custom values.
/// </summary>
DGCustom DGCustom { get; }
} }
} }
+1 -1
View File
@@ -6,7 +6,7 @@ namespace NTwain.Triplets
/// <summary> /// <summary>
/// Represents <see cref="DataGroups.Audio"/>. /// Represents <see cref="DataGroups.Audio"/>.
/// </summary> /// </summary>
public sealed class DGAudio sealed class DGAudio
{ {
ITwainSessionInternal _session; ITwainSessionInternal _session;
internal DGAudio(ITwainSessionInternal session) internal DGAudio(ITwainSessionInternal session)
+26 -33
View File
@@ -62,7 +62,7 @@ namespace NTwain
return __ownedSources[key] = new TwainSource(session, sourceId); return __ownedSources[key] = new TwainSource(session, sourceId);
} }
/// <summary> /// <summary>
/// Gets or sets the optional synchronization context. /// Gets or sets the optional synchronization context.
@@ -151,7 +151,7 @@ namespace NTwain
get get
{ {
TWIdentity id; TWIdentity id;
if (DGControl.Identity.GetDefault(out id) == ReturnCode.Success) if (((ITwainSessionInternal)this).DGControl.Identity.GetDefault(out id) == ReturnCode.Success)
{ {
return GetSourceInstance(this, id); return GetSourceInstance(this, id);
} }
@@ -161,7 +161,7 @@ namespace NTwain
{ {
if (value != null) if (value != null)
{ {
DGControl.Identity.Set(value.Identity); ((ITwainSessionInternal)this).DGControl.Identity.Set(value.Identity);
} }
} }
} }
@@ -174,7 +174,7 @@ namespace NTwain
public TwainSource ShowSourceSelector() public TwainSource ShowSourceSelector()
{ {
TWIdentity id; TWIdentity id;
if (DGControl.Identity.UserSelect(out id) == ReturnCode.Success) if (((ITwainSessionInternal)this).DGControl.Identity.UserSelect(out id) == ReturnCode.Success)
{ {
return GetSourceInstance(this, id); return GetSourceInstance(this, id);
} }
@@ -210,7 +210,7 @@ namespace NTwain
/// <summary> /// <summary>
/// Gets the triplet operations defined for audio data group. /// Gets the triplet operations defined for audio data group.
/// </summary> /// </summary>
public DGAudio DGAudio DGAudio ITwainSessionInternal.DGAudio
{ {
get get
{ {
@@ -220,10 +220,7 @@ namespace NTwain
} }
DGControl _dgControl; DGControl _dgControl;
/// <summary> DGControl ITwainSessionInternal.DGControl
/// Gets the triplet operations defined for control data group.
/// </summary>
public DGControl DGControl
{ {
get get
{ {
@@ -233,10 +230,7 @@ namespace NTwain
} }
DGImage _dgImage; DGImage _dgImage;
/// <summary> DGImage ITwainSessionInternal.DGImage
/// Gets the triplet operations defined for image data group.
/// </summary>
public DGImage DGImage
{ {
get get
{ {
@@ -246,10 +240,7 @@ namespace NTwain
} }
DGCustom _dgCustom; DGCustom _dgCustom;
/// <summary> DGCustom ITwainSessionInternal.DGCustom
/// Gets the direct triplet operation entry for custom values.
/// </summary>
public DGCustom DGCustom
{ {
get get
{ {
@@ -257,6 +248,7 @@ namespace NTwain
return _dgCustom; return _dgCustom;
} }
} }
/// <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.
@@ -269,14 +261,14 @@ namespace NTwain
{ {
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 = DGControl.Parent.OpenDsm(MessageLoop.Instance.LoopHandle); rc = ((ITwainSessionInternal)this).DGControl.Parent.OpenDsm(MessageLoop.Instance.LoopHandle);
if (rc == ReturnCode.Success) if (rc == ReturnCode.Success)
{ {
// 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)
{ {
TWEntryPoint entry; TWEntryPoint entry;
rc = DGControl.EntryPoint.Get(out entry); rc = ((ITwainSessionInternal)this).DGControl.EntryPoint.Get(out entry);
if (rc == ReturnCode.Success) if (rc == ReturnCode.Success)
{ {
Platform.MemoryManager = entry; Platform.MemoryManager = entry;
@@ -303,7 +295,7 @@ namespace NTwain
{ {
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 = DGControl.Parent.CloseDsm(MessageLoop.Instance.LoopHandle); rc = ((ITwainSessionInternal)this).DGControl.Parent.CloseDsm(MessageLoop.Instance.LoopHandle);
if (rc == ReturnCode.Success) if (rc == ReturnCode.Success)
{ {
Platform.MemoryManager = null; Platform.MemoryManager = null;
@@ -321,13 +313,14 @@ namespace NTwain
public IEnumerable<TwainSource> GetSources() public IEnumerable<TwainSource> GetSources()
{ {
TWIdentity srcId; TWIdentity srcId;
var rc = DGControl.Identity.GetFirst(out srcId); var rc = ((ITwainSessionInternal)this).DGControl.Identity.GetFirst(out srcId);
while (rc == ReturnCode.Success) while (rc == ReturnCode.Success)
{ {
yield return GetSourceInstance(this, srcId); yield return GetSourceInstance(this, srcId);
rc = DGControl.Identity.GetNext(out srcId); rc = ((ITwainSessionInternal)this).DGControl.Identity.GetNext(out srcId);
} }
} }
/// <summary> /// <summary>
/// Gets the manager status. Only call this at state 2 or higher. /// Gets the manager status. Only call this at state 2 or higher.
/// </summary> /// </summary>
@@ -335,7 +328,7 @@ namespace NTwain
public TWStatus GetStatus() public TWStatus GetStatus()
{ {
TWStatus stat; TWStatus stat;
DGControl.Status.GetManager(out stat); ((ITwainSessionInternal)this).DGControl.Status.GetManager(out stat);
return stat; return stat;
} }
@@ -346,7 +339,7 @@ namespace NTwain
public TWStatusUtf8 GetStatusUtf8() public TWStatusUtf8 GetStatusUtf8()
{ {
TWStatusUtf8 stat; TWStatusUtf8 stat;
DGControl.StatusUtf8.GetManager(out stat); ((ITwainSessionInternal)this).DGControl.StatusUtf8.GetManager(out stat);
return stat; return stat;
} }
@@ -414,7 +407,7 @@ namespace NTwain
if (_appId.ProtocolMajor >= 2 && _appId.ProtocolMinor >= 2) if (_appId.ProtocolMajor >= 2 && _appId.ProtocolMinor >= 2)
{ {
var cb = new TWCallback2(HandleCallback); var cb = new TWCallback2(HandleCallback);
var rc2 = DGControl.Callback2.RegisterCallback(cb); var rc2 = ((ITwainSessionInternal)this).DGControl.Callback2.RegisterCallback(cb);
if (rc2 == ReturnCode.Success) if (rc2 == ReturnCode.Success)
{ {
@@ -426,7 +419,7 @@ namespace NTwain
{ {
var cb = new TWCallback(HandleCallback); var cb = new TWCallback(HandleCallback);
var rc2 = DGControl.Callback.RegisterCallback(cb); var rc2 = ((ITwainSessionInternal)this).DGControl.Callback.RegisterCallback(cb);
if (rc2 == ReturnCode.Success) if (rc2 == ReturnCode.Success)
{ {
@@ -442,11 +435,11 @@ namespace NTwain
if (mode == SourceEnableMode.ShowUIOnly) if (mode == SourceEnableMode.ShowUIOnly)
{ {
rc = DGControl.UserInterface.EnableDSUIOnly(_twui); rc = ((ITwainSessionInternal)this).DGControl.UserInterface.EnableDSUIOnly(_twui);
} }
else else
{ {
rc = DGControl.UserInterface.EnableDS(_twui); rc = ((ITwainSessionInternal)this).DGControl.UserInterface.EnableDS(_twui);
} }
if (rc != ReturnCode.Success) if (rc != ReturnCode.Success)
@@ -465,7 +458,7 @@ namespace NTwain
{ {
Debug.WriteLine(string.Format(CultureInfo.InvariantCulture, "Thread {0}: DisableSource.", Thread.CurrentThread.ManagedThreadId)); 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) if (rc == ReturnCode.Success)
{ {
_callbackObj = null; _callbackObj = null;
@@ -506,11 +499,11 @@ namespace NTwain
{ {
if (targetState < 7) if (targetState < 7)
{ {
DGControl.PendingXfers.EndXfer(new TWPendingXfers()); ((ITwainSessionInternal)this).DGControl.PendingXfers.EndXfer(new TWPendingXfers());
} }
if (targetState < 6) if (targetState < 6)
{ {
DGControl.PendingXfers.Reset(new TWPendingXfers()); ((ITwainSessionInternal)this).DGControl.PendingXfers.Reset(new TWPendingXfers());
} }
if (targetState < 5) if (targetState < 5)
{ {
@@ -690,7 +683,7 @@ namespace NTwain
var evt = new TWEvent(); var evt = new TWEvent();
evt.pEvent = msgPtr; 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)); 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; break;
case Message.DeviceEvent: case Message.DeviceEvent:
TWDeviceEvent de; TWDeviceEvent de;
var rc = DGControl.DeviceEvent.Get(out de); var rc = ((ITwainSessionInternal)this).DGControl.DeviceEvent.Get(out de);
if (rc == ReturnCode.Success) if (rc == ReturnCode.Success)
{ {
SafeSyncableRaiseOnEvent(OnDeviceEvent, DeviceEvent, new DeviceEventArgs(de)); SafeSyncableRaiseOnEvent(OnDeviceEvent, DeviceEvent, new DeviceEventArgs(de));
+35
View File
@@ -1,5 +1,6 @@
using NTwain.Data; using NTwain.Data;
using NTwain.Internals; using NTwain.Internals;
using NTwain.Triplets;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.ComponentModel; using System.ComponentModel;
@@ -182,6 +183,40 @@ namespace NTwain
} }
} }
/// <summary>
/// Gets the triplet operations defined for control data group.
/// </summary>
public DGControl DGControl
{
get
{
return _session.DGControl;
}
}
/// <summary>
/// Gets the triplet operations defined for image data group.
/// </summary>
public DGImage DGImage
{
get
{
return _session.DGImage;
}
}
/// <summary>
/// Gets the direct triplet operation entry for custom values.
/// </summary>
public DGCustom DGCustom
{
get
{
return _session.DGCustom;
}
}
#endregion #endregion
#region INotifyPropertyChanged Members #region INotifyPropertyChanged Members
+50 -29
View File
@@ -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). and how it works in general (especially capability).
The spec can be downloaded from [twain.org](http://twain.org/). The spec can be downloaded from [twain.org](http://twain.org/).
Except for certain "important" state-changing calls that have been Except for those that have been abstracted away with .net equivalents, most triplet operations are
abstract away, most triplet operations are
provided as-is so you will need to know when and how to use them. 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 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. 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.TransferReady += ...
session.DataTransferred += ... session.DataTransferred += ...
// finally open it
session.Open();
``` ```
TwainSession class provides many events, but these 2 are the most important 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. 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: Once you've setup and opened the session, you can get available sources, pick one to use,
and call Open() to start using it.
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()
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). #!c#
This should make setting simple things such as DPI, bitdepth, or paper size easier.
More of these extensions may come in later versions. // choose and open a source
IEnumerable<TwainSources> 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 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 consumers to do the conversion themselves. The winform project contains one such
example for handling DIB image in native transfer using the CommonWin32 lib. 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 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 to the one from the UI thread.
event, so if you find yourself in that position you'll have to find another way
to synchronize data to UI threads.
``` ```
#!c# #!c#
@@ -87,17 +107,18 @@ to synchronize data to UI threads.
session.SynchronizationContext = SynchronizationContext.Current; 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 64-bit OS
-------------------------------------- --------------------------------------
If the application process is running in 64-bit then you will need to make sure you have the 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. newer data source manager (twaindsm.dll) from below installed.
[DSM from TWAIN.org](http://sourceforge.net/projects/twain-dsm/files/TWAIN%20DSM%202%20Win/) [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. Otherwise just compile and run the app as x86 and it'll use the 32-bit version (twain_32.dll) that comes with Windows.
If your scanner driver is still 32-bit (and most likely it will be) you'll have no choice but to
Note that there are no known 64-bit TWAIN DS drivers at the time of writing, so most likely you will have to compile as x86 anyway, even if you have installed the newer dsm dll.
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/)