PreviewControl.xaml.cs 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324
  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. renderThread.Start(Document.PageAtIndex(pageIndex));
  175. }
  176. protected readonly object queueLock = new object();
  177. protected void LoadImage(object pageObject)
  178. {
  179. CPDFPage pdfPage = (CPDFPage)pageObject;
  180. Size pageSize = pdfPage.PageSize;
  181. double ratio = CalculateThumbnailSize(pageSize) * 3;
  182. Rect pageRect = new Rect(0, 0, (int)(pageSize.Width * ratio), (int)(pageSize.Height * ratio));
  183. byte[] bmpData = new byte[(int)(pageRect.Width * pageRect.Height * 4)];
  184. lock (queueLock)
  185. {
  186. if(pdfPage.IsValid() == false)
  187. {
  188. pdfPage = Document.PageAtIndex(pdfPage.PageIndex);
  189. }
  190. pdfPage.RenderPageBitmapWithMatrix((float)ratio, pageRect, 0xFFFFFFFF, bmpData, 0, true);
  191. }
  192. WriteableBitmap writeableBitmap = new WriteableBitmap((int)pageRect.Width, (int)pageRect.Height, 96, 96, PixelFormats.Bgra32, null);
  193. writeableBitmap.WritePixels(new Int32Rect(0, 0, (int)pageRect.Width, (int)pageRect.Height), bmpData, writeableBitmap.BackBufferStride, 0);
  194. writeableBitmap.Freeze();
  195. Application.Current.Dispatcher.Invoke(new Action(() =>
  196. {
  197. ImageSource = writeableBitmap;
  198. }));
  199. }
  200. private double CalculateThumbnailSize(Size size)
  201. {
  202. if (size.Height / size.Width > aspectRatio)
  203. {
  204. return (thumbnailWidth) / size.Width;
  205. }
  206. else
  207. {
  208. return (thumbnailHeight) / size.Height;
  209. }
  210. }
  211. private async void UserControl_Loaded(object sender, RoutedEventArgs eventArgs)
  212. {
  213. if (Document == null)
  214. {
  215. return;
  216. }
  217. try
  218. {
  219. await Dispatcher.InvokeAsync(() =>
  220. {
  221. aspectRatio = ImageGd.ActualHeight / ImageGd.ActualWidth;
  222. thumbnailWidth = ImageGd.ActualWidth - 20;
  223. thumbnailHeight = ImageGd.ActualHeight - 20;
  224. });
  225. CurrentIndexChanged += (s, e) =>
  226. {
  227. BeginLoadImageThread(PageRangeList[CurrentIndex - 1] - 1);
  228. };
  229. AttachLoaded();
  230. }
  231. catch (Exception ex)
  232. {
  233. }
  234. }
  235. virtual public void AttachLoaded()
  236. {
  237. BeginLoadImageThread(0);
  238. }
  239. private void CurrentIndexTxt_CanExecute(object sender, CanExecuteRoutedEventArgs e)
  240. {
  241. try
  242. {
  243. if (e.Command == ApplicationCommands.Paste && Clipboard.ContainsText())
  244. {
  245. string checkText = Clipboard.GetText();
  246. if (int.TryParse(checkText, out int value))
  247. {
  248. e.CanExecute = true;
  249. }
  250. e.Handled = true;
  251. }
  252. }
  253. catch (Exception ex)
  254. {
  255. }
  256. }
  257. private void PageBtn_Click(object sender, RoutedEventArgs e)
  258. {
  259. var button = sender as Button;
  260. if (button != null)
  261. {
  262. if (button.Name == "PrePageBtn")
  263. {
  264. CurrentIndex--;
  265. }
  266. else
  267. {
  268. CurrentIndex++;
  269. }
  270. }
  271. }
  272. private void ScaleBtn_Click(object sender, RoutedEventArgs e)
  273. {
  274. var button = sender as Button;
  275. if (button != null)
  276. {
  277. if (button.Name == "ZoomInBtn")
  278. {
  279. Scale -= 0.1;
  280. }
  281. else
  282. {
  283. Scale += 0.1;
  284. }
  285. }
  286. }
  287. }
  288. }