using NTwain; using NTwain.Data; using PDF_Master.Model; using Prism.Commands; using Prism.Mvvm; using Prism.Services.Dialogs; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Reflection; using System.Text; using System.Threading.Tasks; using System.Windows; using System.Windows.Interop; using System.Windows.Media; using System.Windows.Media.Imaging; namespace PDF_Master.ViewModels.Dialog.HomePageToolsDialogs { //扫描仪设备 public class ScannerItem : BindableBase { public DataSource DataSourceItem { get; set; } public ScannerItem(DataSource dataSource) { DataSourceItem = dataSource; ScannerName = dataSource.Name; } public string ScannerName { get; set; } } public class CreateFromScannerDialogsViewModel : BindableBase, IDialogAware { private List _scanners = new List(); public List Scanners { get { return _scanners; } set => SetProperty(ref _scanners, value); } //图片 private ImageSource _img; public ImageSource Img { get { return _img; } set => SetProperty(ref _img, value); } //没有检测到扫描仪 private bool _isEmptyScanner; public bool IsEmptyScanner { get { return _isEmptyScanner; } set => SetProperty(ref _isEmptyScanner, value); } //没有生成图片 private bool isEmptyImg; public bool IsEmptyImg { get { return isEmptyImg; } set => SetProperty(ref isEmptyImg, value); } public string Title => ""; //图片路径 public string FilePath { get; private set; } private bool IsScanner = false; public event Action RequestClose; private TwainSession twain; public DelegateCommand CancelCommand { get; set; } public DelegateCommand CreateCommand { get; set; } public DelegateCommand SelectedScannerCommand { get; set; } public CreateFromScannerDialogsViewModel() { CancelCommand = new DelegateCommand(cancel); CreateCommand = new DelegateCommand(createFile, CanExcuteCreateFile).ObservesProperty(() => Img); SelectedScannerCommand = new DelegateCommand(SelectedScanner); SetupTwain(); if (Scanners.Count > 0) IsEmptyScanner = false; else IsEmptyScanner = true; } //选择扫描仪 private void SelectedScanner(object obj) { if(obj != null) { if (twain.State == 4) { twain.CurrentSource.Close(); } Img = null; OpenSaveScanner(); var result = obj as ScannerItem; if (result.DataSourceItem.Open() != ReturnCode.Success) MessageBox.Show("连接失败"); else { } Preview(); } } //启动检测扫描仪 private void SetupTwain() { var appId = TWIdentity.CreateFromAssembly(DataGroups.Image, Assembly.GetEntryAssembly()); twain = new TwainSession(appId); twain.Open(); //Todo:在程序32位时,可正常扫描; //在程序64位时,不能正常获取扫描仪,并崩溃:找不到TWAINDSM.DLL模块。 foreach (var s in twain.Select(s => new { DS = s })) { var item = new ScannerItem(s.DS); Scanners.Add(item); } twain.TransferError += (s, e) => { CloseSaveScanner(); // MessageBox.Show("图片传输错误:" + e.Exception.Message); }; twain.DataTransferred += _session_DataTransferred; twain.SourceDisabled += (s, e) => { //MessageBox.Show("源数据已清除"); }; twain.TransferReady += (s, e) => { //MessageBox.Show("数据传输就绪"); }; twain.SynchronizationContext = System.Threading.SynchronizationContext.Current; } //生成图片+预览图片 private void _session_DataTransferred(object sender, DataTransferredEventArgs e) { if (IsScanner) { string docPath = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments); FilePath = docPath + "\\" + DateTime.Now.ToString("yyyy-MM-dd_hh-mm-ss") + ".png"; var encoder = new PngBitmapEncoder(); encoder.Frames.Add(BitmapFrame.Create(e.GetNativeImageStream().ConvertToWpfBitmap(300, 0))); var test = encoder.Frames[0]; FileStream fileStream = new FileStream(FilePath, FileMode.Create, FileAccess.ReadWrite); encoder.Save(fileStream); fileStream.Close(); CloseSaveScanner(); } ImageSource img = GenerateThumbnail(e); if (img != null) { App.Current.Dispatcher.BeginInvoke(new Action(() => { Img = img; })); } } //图片缩略图 private ImageSource GenerateThumbnail(DataTransferredEventArgs e) { BitmapSource img = null; switch (e.TransferType) { case XferMech.Native: using (var stream = e.GetNativeImageStream()) { if (stream != null) { // twain.CurrentSource.Capabilities.ICapYResolution.SetValue(); img = stream.ConvertToWpfBitmap(300, 0); } } break; case XferMech.File: img = new BitmapImage(new Uri(e.FileDataPath)); if (img.CanFreeze) { img.Freeze(); } break; case XferMech.Memory: // TODO: build current image from multiple data-xferred event break; } return img; } //预览图片 private void Preview() { if (twain.CurrentSource == null) return; var windowsPtr = new WindowInteropHelper(Window.GetWindow(App.Current.MainWindow)).Handle; twain.CurrentSource.Enable(SourceEnableMode.NoUI, false, windowsPtr); } private void CloseSaveScanner() { IsScanner = false; } private void OpenSaveScanner() { IsScanner = true; } /// /// 是否可以创建 /// /// private bool CanExcuteCreateFile() { if (Img == null) IsEmptyImg = true; else IsEmptyImg = false; return (Img != null); } //扫描,创建文件 private void createFile() { DialogParameters valuePairs = new DialogParameters(); valuePairs.Add(ParameterNames.DataModel, FilePath); RequestClose.Invoke(new DialogResult(ButtonResult.OK, valuePairs)); } private void cancel() { RequestClose.Invoke(new DialogResult(ButtonResult.Cancel)); } #region 框架 public bool CanCloseDialog() { return true; } public void OnDialogClosed() { } public void OnDialogOpened(IDialogParameters parameters) { } #endregion } }