PreviewControl.xaml.cs 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326
  1. using ComPDFKit.PDFDocument;
  2. using ComPDFKit.PDFPage;
  3. using System;
  4. using System.Collections.Generic;
  5. using System.ComponentModel;
  6. using System.IO;
  7. using System.Linq;
  8. using System.Runtime.CompilerServices;
  9. using System.Text;
  10. using System.Threading;
  11. using System.Threading.Tasks;
  12. using System.Windows;
  13. using System.Windows.Controls;
  14. using System.Windows.Data;
  15. using System.Windows.Documents;
  16. using System.Windows.Input;
  17. using System.Windows.Media;
  18. using System.Windows.Media.Imaging;
  19. using System.Windows.Navigation;
  20. using System.Windows.Shapes;
  21. using System.Xml.Linq;
  22. namespace Compdfkit_Tools.PDFControl
  23. {
  24. /// <summary>
  25. /// Interaction logic for PreviewControl.xaml
  26. /// </summary>
  27. public partial class PreviewControl : UserControl, INotifyPropertyChanged
  28. {
  29. private Point lastMousePosition;
  30. private double startVerticalOffset;
  31. private double startHorizontalOffset;
  32. private List<int> _pageIndexList = new List<int>();
  33. public List<int> PageRangeList
  34. {
  35. get => _pageIndexList;
  36. set
  37. {
  38. CurrentIndex = 1;
  39. _pageIndexList = value;
  40. PageCount = _pageIndexList.Count;
  41. }
  42. }
  43. private int _pageCount = 1;
  44. public int PageCount
  45. {
  46. get => _pageCount;
  47. set
  48. {
  49. UpdateProper(ref _pageCount, value);
  50. }
  51. }
  52. private int _currentIndex = 1;
  53. public int CurrentIndex
  54. {
  55. get => _currentIndex;
  56. set
  57. {
  58. if (value < 1)
  59. {
  60. value = 1;
  61. }
  62. else if (value > PageCount)
  63. {
  64. value = PageCount;
  65. }
  66. if (UpdateProper(ref _currentIndex, value))
  67. {
  68. OnCurrentIndexChanged();
  69. }
  70. }
  71. }
  72. private void OnCurrentIndexChanged()
  73. {
  74. CurrentIndexChanged?.Invoke(this, EventArgs.Empty);
  75. }
  76. private double _scale = 0.3;
  77. public double Scale
  78. {
  79. get => _scale;
  80. set
  81. {
  82. UpdateProper(ref _scale, Math.Min((Math.Max(value, 0.1)), 1));
  83. }
  84. }
  85. private WriteableBitmap _imageSource;
  86. public WriteableBitmap ImageSource
  87. {
  88. get => _imageSource;
  89. set
  90. {
  91. UpdateProper(ref _imageSource, value);
  92. }
  93. }
  94. private CPDFDocument _document;
  95. public CPDFDocument Document
  96. {
  97. get { return _document; }
  98. set
  99. {
  100. _document = value;
  101. }
  102. }
  103. protected double aspectRatio;
  104. protected double thumbnailWidth;
  105. protected double thumbnailHeight;
  106. public event EventHandler CurrentIndexChanged;
  107. public PreviewControl()
  108. {
  109. InitializeComponent();
  110. DataContext = this;
  111. }
  112. public void InitPreview(CPDFDocument document)
  113. {
  114. Document = document;
  115. }
  116. private void Image_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
  117. {
  118. lastMousePosition = e.GetPosition(ImageSv);
  119. startVerticalOffset = ImageSv.VerticalOffset;
  120. startHorizontalOffset = ImageSv.HorizontalOffset;
  121. Image.CaptureMouse();
  122. this.Cursor = Cursors.Hand;
  123. }
  124. private void Image_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
  125. {
  126. Image.ReleaseMouseCapture();
  127. this.Cursor = Cursors.Arrow;
  128. }
  129. private void Image_MouseMove(object sender, MouseEventArgs e)
  130. {
  131. if (ImageSv.Visibility == Visibility.Visible && Image.IsMouseCaptured)
  132. {
  133. Point currentMousePosition = e.GetPosition(ImageSv);
  134. double deltaVerticalOffset = lastMousePosition.Y - currentMousePosition.Y;
  135. double deltaHorizontalOffset = lastMousePosition.X - currentMousePosition.X;
  136. double newVerticalOffset = startVerticalOffset + deltaVerticalOffset;
  137. double newHorizontalOffset = startHorizontalOffset + deltaHorizontalOffset;
  138. ImageSv.ScrollToVerticalOffset(newVerticalOffset);
  139. ImageSv.ScrollToHorizontalOffset(newHorizontalOffset);
  140. }
  141. }
  142. public event PropertyChangedEventHandler PropertyChanged;
  143. protected virtual void OnPropertyChanged(string propertyName = null)
  144. {
  145. PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
  146. }
  147. protected bool UpdateProper<T>(ref T properValue,
  148. T newValue,
  149. [CallerMemberName] string properName = "")
  150. {
  151. if (object.Equals(properValue, newValue))
  152. return false;
  153. properValue = newValue;
  154. OnPropertyChanged(properName);
  155. return true;
  156. }
  157. private void CurrentIndexTxt_PreviewTextInput(object sender, TextCompositionEventArgs e)
  158. {
  159. TextBox textBox = sender as TextBox;
  160. if (textBox != null)
  161. {
  162. if (!System.Text.RegularExpressions.Regex.IsMatch(e.Text, @"^[0-9]$"))
  163. {
  164. e.Handled = true;
  165. }
  166. }
  167. }
  168. private Thread renderThread = null;
  169. public virtual void BeginLoadImageThread(int pageIndex)
  170. {
  171. if (renderThread != null && renderThread.ThreadState == ThreadState.Running)
  172. return;
  173. renderThread = new Thread(new ParameterizedThreadStart(LoadImage));
  174. if(Document != null)
  175. {
  176. renderThread.Start(Document.PageAtIndex(pageIndex));
  177. }
  178. }
  179. protected readonly object queueLock = new object();
  180. protected void LoadImage(object pageObject)
  181. {
  182. CPDFPage pdfPage = (CPDFPage)pageObject;
  183. Size pageSize = pdfPage.PageSize;
  184. double ratio = CalculateThumbnailSize(pageSize) * 3;
  185. Rect pageRect = new Rect(0, 0, (int)(pageSize.Width * ratio), (int)(pageSize.Height * ratio));
  186. byte[] bmpData = new byte[(int)(pageRect.Width * pageRect.Height * 4)];
  187. lock (queueLock)
  188. {
  189. if(pdfPage.IsValid() == false)
  190. {
  191. pdfPage = Document.PageAtIndex(pdfPage.PageIndex);
  192. }
  193. pdfPage.RenderPageBitmapWithMatrix((float)ratio, pageRect, 0xFFFFFFFF, bmpData, 0, true);
  194. }
  195. WriteableBitmap writeableBitmap = new WriteableBitmap((int)pageRect.Width, (int)pageRect.Height, 96, 96, PixelFormats.Bgra32, null);
  196. writeableBitmap.WritePixels(new Int32Rect(0, 0, (int)pageRect.Width, (int)pageRect.Height), bmpData, writeableBitmap.BackBufferStride, 0);
  197. writeableBitmap.Freeze();
  198. Application.Current.Dispatcher.Invoke(new Action(() =>
  199. {
  200. ImageSource = writeableBitmap;
  201. }));
  202. }
  203. private double CalculateThumbnailSize(Size size)
  204. {
  205. if (size.Height / size.Width > aspectRatio)
  206. {
  207. return (thumbnailWidth) / size.Width;
  208. }
  209. else
  210. {
  211. return (thumbnailHeight) / size.Height;
  212. }
  213. }
  214. private async void UserControl_Loaded(object sender, RoutedEventArgs eventArgs)
  215. {
  216. if (Document == null)
  217. {
  218. return;
  219. }
  220. try
  221. {
  222. await Dispatcher.InvokeAsync(() =>
  223. {
  224. aspectRatio = ImageGd.ActualHeight / ImageGd.ActualWidth;
  225. thumbnailWidth = ImageGd.ActualWidth - 20;
  226. thumbnailHeight = ImageGd.ActualHeight - 20;
  227. });
  228. CurrentIndexChanged += (s, e) =>
  229. {
  230. BeginLoadImageThread(PageRangeList[CurrentIndex - 1] - 1);
  231. };
  232. AttachLoaded();
  233. }
  234. catch (Exception ex)
  235. {
  236. }
  237. }
  238. virtual public void AttachLoaded()
  239. {
  240. BeginLoadImageThread(0);
  241. }
  242. private void CurrentIndexTxt_CanExecute(object sender, CanExecuteRoutedEventArgs e)
  243. {
  244. try
  245. {
  246. if (e.Command == ApplicationCommands.Paste && Clipboard.ContainsText())
  247. {
  248. string checkText = Clipboard.GetText();
  249. if (int.TryParse(checkText, out int value))
  250. {
  251. e.CanExecute = true;
  252. }
  253. e.Handled = true;
  254. }
  255. }
  256. catch (Exception ex)
  257. {
  258. }
  259. }
  260. private void PageBtn_Click(object sender, RoutedEventArgs e)
  261. {
  262. var button = sender as Button;
  263. if (button != null)
  264. {
  265. if (button.Name == "PrePageBtn")
  266. {
  267. CurrentIndex--;
  268. }
  269. else
  270. {
  271. CurrentIndex++;
  272. }
  273. }
  274. }
  275. private void ScaleBtn_Click(object sender, RoutedEventArgs e)
  276. {
  277. var button = sender as Button;
  278. if (button != null)
  279. {
  280. if (button.Name == "ZoomInBtn")
  281. {
  282. Scale -= 0.1;
  283. }
  284. else
  285. {
  286. Scale += 0.1;
  287. }
  288. }
  289. }
  290. }
  291. }