mirror of
https://github.com/soukoku/ntwain.git
synced 2026-01-26 21:48:36 +08:00
Reorged source tree.
This commit is contained in:
102
samples/Sample.WPF/ViewModels/CapVM.cs
Normal file
102
samples/Sample.WPF/ViewModels/CapVM.cs
Normal file
@@ -0,0 +1,102 @@
|
||||
using NTwain;
|
||||
using NTwain.Data;
|
||||
using System.Collections;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Sample.WPF
|
||||
{
|
||||
/// <summary>
|
||||
/// Wraps a capability as a view model.
|
||||
/// </summary>
|
||||
class CapVM
|
||||
{
|
||||
DataSource _ds;
|
||||
object _wrapper;
|
||||
MethodInfo _getMethod;
|
||||
MethodInfo _getCurrentMethod;
|
||||
MethodInfo _setMethod;
|
||||
|
||||
public CapVM(DataSource ds, CapabilityId cap)
|
||||
{
|
||||
_ds = ds;
|
||||
Cap = cap;
|
||||
|
||||
|
||||
var capName = cap.ToString();
|
||||
var wrapProperty = ds.Capabilities.GetType().GetProperty(capName);
|
||||
if (wrapProperty != null)
|
||||
{
|
||||
_wrapper = wrapProperty.GetGetMethod().Invoke(ds.Capabilities, null);
|
||||
var wrapperType = _wrapper.GetType();
|
||||
_getMethod = wrapperType.GetMethod("GetValues");
|
||||
_getCurrentMethod = wrapperType.GetMethod("GetCurrent");
|
||||
_setMethod = wrapperType.GetMethods().FirstOrDefault(m => m.Name == "SetValue");
|
||||
}
|
||||
|
||||
var supportTest = ds.Capabilities.QuerySupport(cap);
|
||||
if (supportTest.HasValue)
|
||||
{
|
||||
Supports = supportTest.Value;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_wrapper != null)
|
||||
{
|
||||
var wrapperType = _wrapper.GetType();
|
||||
QuerySupports? supports = (QuerySupports?)wrapperType.GetProperty("SupportedActions").GetGetMethod().Invoke(_wrapper, null);
|
||||
Supports = supports.GetValueOrDefault();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public IEnumerable Get()
|
||||
{
|
||||
if (_getMethod == null)
|
||||
{
|
||||
return _ds.Capabilities.GetValues(Cap);
|
||||
}
|
||||
return _getMethod.Invoke(_wrapper, null) as IEnumerable;
|
||||
}
|
||||
public object GetCurrent()
|
||||
{
|
||||
if (_getMethod == null)
|
||||
{
|
||||
return _ds.Capabilities.GetCurrent(Cap);
|
||||
}
|
||||
return _getCurrentMethod.Invoke(_wrapper, null);
|
||||
}
|
||||
public void Set(object value)
|
||||
{
|
||||
if (_setMethod != null && value != null)
|
||||
{
|
||||
_setMethod.Invoke(_wrapper, new object[] { value });
|
||||
}
|
||||
}
|
||||
|
||||
public object MyProperty { get; set; }
|
||||
|
||||
public CapabilityId Cap { get; private set; }
|
||||
|
||||
public string Name
|
||||
{
|
||||
get
|
||||
{
|
||||
if (Cap > CapabilityId.CustomBase)
|
||||
{
|
||||
return "[Custom] " + ((int)Cap - (int)CapabilityId.CustomBase);
|
||||
}
|
||||
return Cap.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
public QuerySupports Supports { get; private set; }
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return Name;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
73
samples/Sample.WPF/ViewModels/DataSourceVM.cs
Normal file
73
samples/Sample.WPF/ViewModels/DataSourceVM.cs
Normal file
@@ -0,0 +1,73 @@
|
||||
using GalaSoft.MvvmLight;
|
||||
using NTwain;
|
||||
using NTwain.Data;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using System.Windows.Data;
|
||||
|
||||
namespace Sample.WPF
|
||||
{
|
||||
/// <summary>
|
||||
/// Wraps a data source as view model.
|
||||
/// </summary>
|
||||
class DataSourceVM : ViewModelBase
|
||||
{
|
||||
public DataSource DS { get; set; }
|
||||
|
||||
public string Name { get { return DS.Name; } }
|
||||
public string Version { get { return DS.Version.Info; } }
|
||||
public string Protocol { get { return DS.ProtocolVersion.ToString(); } }
|
||||
|
||||
ICollectionView _capView;
|
||||
public DataSourceVM()
|
||||
{
|
||||
Caps = new ObservableCollection<CapVM>();
|
||||
_capView = CollectionViewSource.GetDefaultView(Caps);
|
||||
_capView.SortDescriptions.Add(new System.ComponentModel.SortDescription("Name", System.ComponentModel.ListSortDirection.Ascending));
|
||||
_capView.Filter = FilterCapRoutine;
|
||||
}
|
||||
|
||||
private bool FilterCapRoutine(object obj)
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(CapFilter))
|
||||
{
|
||||
var vm = obj as CapVM;
|
||||
if (vm != null)
|
||||
{
|
||||
return vm.Name.IndexOf(CapFilter, System.StringComparison.OrdinalIgnoreCase) > -1;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public void Open()
|
||||
{
|
||||
Caps.Clear();
|
||||
var rc = DS.Open();
|
||||
//rc = DGControl.Status.Get(dsId, ref stat);
|
||||
if (rc == ReturnCode.Success)
|
||||
{
|
||||
foreach (var c in DS.Capabilities.CapSupportedCaps.GetValues().Select(o => new CapVM(DS, o)))
|
||||
{
|
||||
Caps.Add(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private string _capFilter;
|
||||
|
||||
public string CapFilter
|
||||
{
|
||||
get { return _capFilter; }
|
||||
set
|
||||
{
|
||||
_capFilter = value;
|
||||
_capView.Refresh();
|
||||
}
|
||||
}
|
||||
|
||||
public ObservableCollection<CapVM> Caps { get; private set; }
|
||||
}
|
||||
}
|
||||
326
samples/Sample.WPF/ViewModels/TwainVM.cs
Normal file
326
samples/Sample.WPF/ViewModels/TwainVM.cs
Normal file
@@ -0,0 +1,326 @@
|
||||
using CommonWin32;
|
||||
using GalaSoft.MvvmLight.Messaging;
|
||||
using NTwain;
|
||||
using NTwain.Data;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Threading;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
using System.Collections.ObjectModel;
|
||||
using GalaSoft.MvvmLight;
|
||||
using System.Windows.Input;
|
||||
using GalaSoft.MvvmLight.Command;
|
||||
using ModernWPF;
|
||||
using ModernWPF.Messages;
|
||||
|
||||
namespace Sample.WPF
|
||||
{
|
||||
/// <summary>
|
||||
/// Wraps the twain session as a view model for databinding.
|
||||
/// </summary>
|
||||
class TwainVM : ViewModelBase
|
||||
{
|
||||
public TwainVM()
|
||||
{
|
||||
DataSources = new ObservableCollection<DataSourceVM>();
|
||||
CapturedImages = new ObservableCollection<ImageSource>();
|
||||
|
||||
//this.SynchronizationContext = SynchronizationContext.Current;
|
||||
var appId = TWIdentity.CreateFromAssembly(DataGroups.Image | DataGroups.Audio, Assembly.GetEntryAssembly());
|
||||
_session = new TwainSession(appId);
|
||||
_session.TransferError += _session_TransferError;
|
||||
_session.TransferReady += _session_TransferReady;
|
||||
_session.DataTransferred += _session_DataTransferred;
|
||||
_session.SourceDisabled += _session_SourceDisabled;
|
||||
_session.StateChanged += (s, e) => { RaisePropertyChanged(() => State); };
|
||||
}
|
||||
|
||||
TwainSession _session;
|
||||
|
||||
#region properties
|
||||
|
||||
public string AppTitle
|
||||
{
|
||||
get
|
||||
{
|
||||
if (NTwain.PlatformInfo.Current.IsApp64Bit)
|
||||
{
|
||||
return "TWAIN Data Source Tester (64bit)";
|
||||
}
|
||||
else
|
||||
{
|
||||
return "TWAIN Data Source Tester (32bit)";
|
||||
}
|
||||
}
|
||||
}
|
||||
public ObservableCollection<DataSourceVM> DataSources { get; private set; }
|
||||
private DataSourceVM _selectedSource;
|
||||
|
||||
public DataSourceVM SelectedSource
|
||||
{
|
||||
get { return _selectedSource; }
|
||||
set
|
||||
{
|
||||
if (_session.State == 4)
|
||||
{
|
||||
_session.CurrentSource.Close();
|
||||
}
|
||||
_selectedSource = value;
|
||||
RaisePropertyChanged(() => SelectedSource);
|
||||
if (_selectedSource != null)
|
||||
{
|
||||
_selectedSource.Open();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int State { get { return _session.State; } }
|
||||
|
||||
private IntPtr _winHandle;
|
||||
public IntPtr WindowHandle
|
||||
{
|
||||
get { return _winHandle; }
|
||||
set
|
||||
{
|
||||
_winHandle = value;
|
||||
if (value == IntPtr.Zero)
|
||||
{
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
// use this for internal msg loop
|
||||
var rc = _session.Open();
|
||||
|
||||
// use this to hook into current app loop
|
||||
//var rc = _session.Open(new WpfMessageLoopHook(value));
|
||||
|
||||
if (rc == ReturnCode.Success)
|
||||
{
|
||||
ReloadSourcesCommand.Execute(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private ICommand _showDriverCommand;
|
||||
public ICommand ShowDriverCommand
|
||||
{
|
||||
get
|
||||
{
|
||||
return _showDriverCommand ?? (_showDriverCommand = new RelayCommand(() =>
|
||||
{
|
||||
if (_session.State == 4)
|
||||
{
|
||||
var rc = _session.CurrentSource.Enable(SourceEnableMode.ShowUIOnly, false, WindowHandle);
|
||||
}
|
||||
}, () =>
|
||||
{
|
||||
return _session.State == 4 && _session.CurrentSource.Capabilities.CapEnableDSUIOnly.GetCurrent() == BoolType.True;
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
private ICommand _captureCommand;
|
||||
public ICommand CaptureCommand
|
||||
{
|
||||
get
|
||||
{
|
||||
return _captureCommand ?? (_captureCommand = new RelayCommand(() =>
|
||||
{
|
||||
if (_session.State == 4)
|
||||
{
|
||||
//if (this.CurrentSource.ICapPixelType.Get().Contains(PixelType.BlackWhite))
|
||||
//{
|
||||
// this.CurrentSource.ICapPixelType.Set(PixelType.BlackWhite);
|
||||
//}
|
||||
|
||||
//if (this.CurrentSource.ICapXferMech.Get().Contains(XferMech.File))
|
||||
//{
|
||||
// this.CurrentSource.ICapXferMech.Set(XferMech.File);
|
||||
//}
|
||||
|
||||
var rc = _session.CurrentSource.Enable(SourceEnableMode.NoUI, false, WindowHandle);
|
||||
}
|
||||
}, () =>
|
||||
{
|
||||
return _session.State == 4;
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private ICommand _clearCommand;
|
||||
public ICommand ClearCommand
|
||||
{
|
||||
get
|
||||
{
|
||||
return _clearCommand ?? (_clearCommand = new RelayCommand(() =>
|
||||
{
|
||||
CapturedImages.Clear();
|
||||
}, () =>
|
||||
{
|
||||
return CapturedImages.Count > 0;
|
||||
}));
|
||||
}
|
||||
}
|
||||
private ICommand _reloadSrc;
|
||||
public ICommand ReloadSourcesCommand
|
||||
{
|
||||
get
|
||||
{
|
||||
return _reloadSrc ?? (_reloadSrc = new RelayCommand(() =>
|
||||
{
|
||||
DataSources.Clear();
|
||||
foreach (var s in _session.Select(s => new DataSourceVM { DS = s }))
|
||||
{
|
||||
DataSources.Add(s);
|
||||
}
|
||||
}, () =>
|
||||
{
|
||||
return _session.State > 2;
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the captured images.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The captured images.
|
||||
/// </value>
|
||||
public ObservableCollection<ImageSource> CapturedImages { get; private set; }
|
||||
|
||||
public double MinThumbnailSize { get { return 50; } }
|
||||
public double MaxThumbnailSize { get { return 300; } }
|
||||
|
||||
private double _thumbSize = 150;
|
||||
public double ThumbnailSize
|
||||
{
|
||||
get { return _thumbSize; }
|
||||
set
|
||||
{
|
||||
if (value > MaxThumbnailSize) { value = MaxThumbnailSize; }
|
||||
else if (value < MinThumbnailSize) { value = MinThumbnailSize; }
|
||||
_thumbSize = value;
|
||||
RaisePropertyChanged(() => ThumbnailSize);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
void _session_SourceDisabled(object sender, EventArgs e)
|
||||
{
|
||||
Messenger.Default.Send(new RefreshCommandsMessage());
|
||||
}
|
||||
|
||||
void _session_TransferError(object sender, TransferErrorEventArgs e)
|
||||
{
|
||||
App.Current.Dispatcher.BeginInvoke(new Action(() =>
|
||||
{
|
||||
if (e.Exception != null)
|
||||
{
|
||||
Messenger.Default.Send(new DialogMessage(e.Exception.Message, null)
|
||||
{
|
||||
Caption = "Transfer Error Exception",
|
||||
Icon = System.Windows.MessageBoxImage.Error,
|
||||
Button = System.Windows.MessageBoxButton.OK
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
Messenger.Default.Send(new DialogMessage(string.Format("Return Code: {0}\nCondition Code: {1}", e.ReturnCode, e.SourceStatus.ConditionCode), null)
|
||||
{
|
||||
Caption = "Transfer Error",
|
||||
Icon = System.Windows.MessageBoxImage.Error,
|
||||
Button = System.Windows.MessageBoxButton.OK
|
||||
});
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
void _session_TransferReady(object sender, TransferReadyEventArgs e)
|
||||
{
|
||||
if (_session.CurrentSource.Capabilities.ICapXferMech.GetCurrent() == XferMech.File)
|
||||
{
|
||||
var formats = _session.CurrentSource.Capabilities.ICapImageFileFormat.GetValues();
|
||||
var wantFormat = formats.Contains(FileFormat.Tiff) ? FileFormat.Tiff : FileFormat.Bmp;
|
||||
|
||||
var fileSetup = new TWSetupFileXfer
|
||||
{
|
||||
Format = wantFormat,
|
||||
FileName = GetUniqueName(Path.GetTempPath(), "twain-test", "." + wantFormat)
|
||||
};
|
||||
var rc = _session.CurrentSource.DGControl.SetupFileXfer.Set(fileSetup);
|
||||
}
|
||||
}
|
||||
|
||||
string GetUniqueName(string dir, string name, string ext)
|
||||
{
|
||||
var filePath = Path.Combine(dir, name + ext);
|
||||
int next = 1;
|
||||
while (File.Exists(filePath))
|
||||
{
|
||||
filePath = Path.Combine(dir, string.Format("{0} ({1}){2}", name, next++, ext));
|
||||
}
|
||||
return filePath;
|
||||
}
|
||||
|
||||
void _session_DataTransferred(object sender, DataTransferredEventArgs e)
|
||||
{
|
||||
ImageSource img = GenerateThumbnail(e);
|
||||
if (img != null)
|
||||
{
|
||||
App.Current.Dispatcher.BeginInvoke(new Action(() =>
|
||||
{
|
||||
CapturedImages.Add(img);
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ImageSource GenerateThumbnail(DataTransferredEventArgs e)
|
||||
{
|
||||
BitmapSource img = null;
|
||||
if (e.NativeData != IntPtr.Zero)
|
||||
{
|
||||
using (var stream = e.GetNativeImageStream())
|
||||
{
|
||||
if (stream != null)
|
||||
{
|
||||
img = stream.ConvertToWpfBitmap(300, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (!string.IsNullOrEmpty(e.FileDataPath))
|
||||
{
|
||||
img = new BitmapImage(new Uri(e.FileDataPath));
|
||||
}
|
||||
|
||||
//if (img != null)
|
||||
//{
|
||||
// // from http://stackoverflow.com/questions/18189501/create-thumbnail-image-directly-from-header-less-image-byte-array
|
||||
// var scale = MaxThumbnailSize / img.PixelWidth;
|
||||
// var transform = new ScaleTransform(scale, scale);
|
||||
// var thumbnail = new TransformedBitmap(img, transform);
|
||||
// img = new WriteableBitmap(new TransformedBitmap(img, transform));
|
||||
// img.Freeze();
|
||||
//}
|
||||
return img;
|
||||
}
|
||||
|
||||
internal void CloseDown()
|
||||
{
|
||||
if (_session.State == 4)
|
||||
{
|
||||
_session.CurrentSource.Close();
|
||||
}
|
||||
_session.Close();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user