CreateFromScannerDialogsViewModel.cs 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271
  1. using NTwain;
  2. using NTwain.Data;
  3. using PDF_Master.Model;
  4. using Prism.Commands;
  5. using Prism.Mvvm;
  6. using Prism.Services.Dialogs;
  7. using System;
  8. using System.Collections.Generic;
  9. using System.IO;
  10. using System.Linq;
  11. using System.Reflection;
  12. using System.Text;
  13. using System.Threading.Tasks;
  14. using System.Windows;
  15. using System.Windows.Interop;
  16. using System.Windows.Media;
  17. using System.Windows.Media.Imaging;
  18. namespace PDF_Master.ViewModels.Dialog.HomePageToolsDialogs
  19. {
  20. //扫描仪设备
  21. public class ScannerItem : BindableBase
  22. {
  23. public DataSource DataSourceItem { get; set; }
  24. public ScannerItem(DataSource dataSource)
  25. {
  26. DataSourceItem = dataSource;
  27. ScannerName = dataSource.Name;
  28. }
  29. public string ScannerName { get; set; }
  30. }
  31. public class CreateFromScannerDialogsViewModel : BindableBase, IDialogAware
  32. {
  33. private List<ScannerItem> _scanners = new List<ScannerItem>();
  34. public List<ScannerItem> Scanners
  35. {
  36. get { return _scanners; }
  37. set => SetProperty(ref _scanners, value);
  38. }
  39. //图片
  40. private ImageSource _img;
  41. public ImageSource Img
  42. {
  43. get { return _img; }
  44. set => SetProperty(ref _img, value);
  45. }
  46. //没有检测到扫描仪
  47. private bool _isEmptyScanner;
  48. public bool IsEmptyScanner
  49. {
  50. get { return _isEmptyScanner; }
  51. set => SetProperty(ref _isEmptyScanner, value);
  52. }
  53. //没有生成图片
  54. private bool isEmptyImg;
  55. public bool IsEmptyImg
  56. {
  57. get { return isEmptyImg; }
  58. set => SetProperty(ref isEmptyImg, value);
  59. }
  60. public string Title => "";
  61. //图片路径
  62. public string FilePath { get; private set; }
  63. private bool IsScanner = false;
  64. public event Action<IDialogResult> RequestClose;
  65. private TwainSession twain;
  66. public DelegateCommand CancelCommand { get; set; }
  67. public DelegateCommand CreateCommand { get; set; }
  68. public DelegateCommand<object> SelectedScannerCommand { get; set; }
  69. public CreateFromScannerDialogsViewModel()
  70. {
  71. CancelCommand = new DelegateCommand(cancel);
  72. CreateCommand = new DelegateCommand(createFile, CanExcuteCreateFile).ObservesProperty(() => Img);
  73. SelectedScannerCommand = new DelegateCommand<object>(SelectedScanner);
  74. SetupTwain();
  75. if (Scanners.Count > 0)
  76. IsEmptyScanner = false;
  77. else
  78. IsEmptyScanner = true;
  79. }
  80. //选择扫描仪
  81. private void SelectedScanner(object obj)
  82. {
  83. if(obj != null)
  84. {
  85. if (twain.State == 4)
  86. {
  87. twain.CurrentSource.Close();
  88. }
  89. Img = null;
  90. OpenSaveScanner();
  91. var result = obj as ScannerItem;
  92. if (result.DataSourceItem.Open() != ReturnCode.Success)
  93. MessageBox.Show("连接失败");
  94. else
  95. {
  96. }
  97. Preview();
  98. }
  99. }
  100. //启动检测扫描仪
  101. private void SetupTwain()
  102. {
  103. var appId = TWIdentity.CreateFromAssembly(DataGroups.Image, Assembly.GetEntryAssembly());
  104. twain = new TwainSession(appId);
  105. twain.Open();
  106. //Todo:在程序32位时,可正常扫描;
  107. //在程序64位时,不能正常获取扫描仪,并崩溃:找不到TWAINDSM.DLL模块。
  108. foreach (var s in twain.Select(s => new { DS = s }))
  109. {
  110. var item = new ScannerItem(s.DS);
  111. Scanners.Add(item);
  112. }
  113. twain.TransferError += (s, e) =>
  114. {
  115. CloseSaveScanner();
  116. // MessageBox.Show("图片传输错误:" + e.Exception.Message);
  117. };
  118. twain.DataTransferred += _session_DataTransferred;
  119. twain.SourceDisabled += (s, e) =>
  120. {
  121. //MessageBox.Show("源数据已清除");
  122. };
  123. twain.TransferReady += (s, e) =>
  124. {
  125. //MessageBox.Show("数据传输就绪");
  126. };
  127. twain.SynchronizationContext = System.Threading.SynchronizationContext.Current;
  128. }
  129. //生成图片+预览图片
  130. private void _session_DataTransferred(object sender, DataTransferredEventArgs e)
  131. {
  132. if (IsScanner)
  133. {
  134. string docPath = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
  135. FilePath = docPath + "\\" + DateTime.Now.ToString("yyyy-MM-dd_hh-mm-ss") + ".png";
  136. var encoder = new PngBitmapEncoder();
  137. encoder.Frames.Add(BitmapFrame.Create(e.GetNativeImageStream().ConvertToWpfBitmap(300, 0)));
  138. var test = encoder.Frames[0];
  139. FileStream fileStream = new FileStream(FilePath, FileMode.Create, FileAccess.ReadWrite);
  140. encoder.Save(fileStream);
  141. fileStream.Close();
  142. CloseSaveScanner();
  143. }
  144. ImageSource img = GenerateThumbnail(e);
  145. if (img != null)
  146. {
  147. App.Current.Dispatcher.BeginInvoke(new Action(() =>
  148. {
  149. Img = img;
  150. }));
  151. }
  152. }
  153. //图片缩略图
  154. private ImageSource GenerateThumbnail(DataTransferredEventArgs e)
  155. {
  156. BitmapSource img = null;
  157. switch (e.TransferType)
  158. {
  159. case XferMech.Native:
  160. using (var stream = e.GetNativeImageStream())
  161. {
  162. if (stream != null)
  163. {
  164. // twain.CurrentSource.Capabilities.ICapYResolution.SetValue();
  165. img = stream.ConvertToWpfBitmap(300, 0);
  166. }
  167. }
  168. break;
  169. case XferMech.File:
  170. img = new BitmapImage(new Uri(e.FileDataPath));
  171. if (img.CanFreeze)
  172. {
  173. img.Freeze();
  174. }
  175. break;
  176. case XferMech.Memory:
  177. // TODO: build current image from multiple data-xferred event
  178. break;
  179. }
  180. return img;
  181. }
  182. //预览图片
  183. private void Preview()
  184. {
  185. if (twain.CurrentSource == null) return;
  186. var windowsPtr = new WindowInteropHelper(Window.GetWindow(App.Current.MainWindow)).Handle;
  187. twain.CurrentSource.Enable(SourceEnableMode.NoUI, false, windowsPtr);
  188. }
  189. private void CloseSaveScanner()
  190. {
  191. IsScanner = false;
  192. }
  193. private void OpenSaveScanner()
  194. {
  195. IsScanner = true;
  196. }
  197. /// <summary>
  198. /// 是否可以创建
  199. /// </summary>
  200. /// <returns></returns>
  201. private bool CanExcuteCreateFile()
  202. {
  203. if (Img == null)
  204. IsEmptyImg = true;
  205. else
  206. IsEmptyImg = false;
  207. return (Img != null);
  208. }
  209. //扫描,创建文件
  210. private void createFile()
  211. {
  212. DialogParameters valuePairs = new DialogParameters();
  213. valuePairs.Add(ParameterNames.DataModel, FilePath);
  214. RequestClose.Invoke(new DialogResult(ButtonResult.OK, valuePairs));
  215. }
  216. private void cancel()
  217. {
  218. RequestClose.Invoke(new DialogResult(ButtonResult.Cancel));
  219. }
  220. #region 框架
  221. public bool CanCloseDialog()
  222. {
  223. return true;
  224. }
  225. public void OnDialogClosed()
  226. {
  227. }
  228. public void OnDialogOpened(IDialogParameters parameters)
  229. {
  230. }
  231. #endregion
  232. }
  233. }