Merged wrapper-idea into master

This commit is contained in:
Eugene Wang 2014-05-23 19:23:26 -04:00
commit f69698f90a
6 changed files with 133 additions and 83 deletions

View File

@ -37,26 +37,6 @@ namespace NTwain
/// <value>The state.</value>
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>
/// Try to show the built-in source selector dialog and return the selected source.
/// This is not recommended and is only included for completeness.

View File

@ -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; }
/// <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; }
}
}

View File

@ -6,7 +6,7 @@ namespace NTwain.Triplets
/// <summary>
/// Represents <see cref="DataGroups.Audio"/>.
/// </summary>
public sealed class DGAudio
sealed class DGAudio
{
ITwainSessionInternal _session;
internal DGAudio(ITwainSessionInternal session)

View File

@ -62,7 +62,7 @@ namespace NTwain
return __ownedSources[key] = new TwainSource(session, sourceId);
}
/// <summary>
/// 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
/// <summary>
/// Gets the triplet operations defined for audio data group.
/// </summary>
public DGAudio DGAudio
DGAudio ITwainSessionInternal.DGAudio
{
get
{
@ -220,10 +220,7 @@ namespace NTwain
}
DGControl _dgControl;
/// <summary>
/// Gets the triplet operations defined for control data group.
/// </summary>
public DGControl DGControl
DGControl ITwainSessionInternal.DGControl
{
get
{
@ -233,10 +230,7 @@ namespace NTwain
}
DGImage _dgImage;
/// <summary>
/// Gets the triplet operations defined for image data group.
/// </summary>
public DGImage DGImage
DGImage ITwainSessionInternal.DGImage
{
get
{
@ -246,10 +240,7 @@ namespace NTwain
}
DGCustom _dgCustom;
/// <summary>
/// Gets the direct triplet operation entry for custom values.
/// </summary>
public DGCustom DGCustom
DGCustom ITwainSessionInternal.DGCustom
{
get
{
@ -257,6 +248,7 @@ namespace NTwain
return _dgCustom;
}
}
/// <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.
@ -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<TwainSource> 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);
}
}
/// <summary>
/// Gets the manager status. Only call this at state 2 or higher.
/// </summary>
@ -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));

View File

@ -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
}
}
/// <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
#region INotifyPropertyChanged Members

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).
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<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
--------------------------------------
@ -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/)
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.