ntwain/Tests/Tester.WPF/ViewModels/TwainVM.cs

321 lines
10 KiB
C#

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 Tester.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.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.ICapXferMech.GetCurrent() == XferMech.File)
{
var formats = _session.CurrentSource.ICapImageFileFormat.Get();
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)
{
img = e.NativeData.GetWPFBitmap();
}
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();
}
}
}