using ComPDFKit.Controls.Printer; using ComPDFKit.Import; using ComPDFKit.PDFPage; using System; using System.Collections.Generic; using System.ComponentModel; using System.Drawing; using System.Printing; using System.Runtime.CompilerServices; using System.Windows; using System.Windows.Controls; using System.Windows.Input; using System.Windows.Media.Imaging; using Color = System.Drawing.Color; using Point = System.Drawing.Point; using Rectangle = System.Drawing.Rectangle; namespace ComPDFKit.Controls.PDFControl { /// /// Interaction logic for PrintPreviewControl.xaml /// public partial class PrintPreviewControl : UserControl, INotifyPropertyChanged { private double PDFToMediaDpiRatio = 100.0 / 72.0; private double mmToDpiRatio = 100 / 25.4; private PrintSettingsInfo printSettingsInfo; private int originalPaperIndex; private string _paperIndex = "1"; public string PaperIndex { get { return _paperIndex; } set { if (int.TryParse(value, out int paperIndex)) { if (paperIndex > 0 && paperIndex <= printSettingsInfo.TargetPaperList.Count) { originalPaperIndex = paperIndex; if (UpdateProper(ref _paperIndex, value)) { TargetPaperIndex = paperIndex - 1; } } else { OnPropertyChanged(); } } else if (value == string.Empty) { _paperIndex = value; } } } private int _printedPageCount; public int PrintedPageCount { get => _printedPageCount; set => UpdateProper(ref _printedPageCount, value); } private string _paperType; public string PaperKind { get => _paperType; set => UpdateProper(ref _paperType, value); } private string _paperWidth; public string PaperWidth { get => _paperWidth; set => UpdateProper(ref _paperWidth, value); } private string _paperHeight; public string PaperHeight { get => _paperHeight; set => UpdateProper(ref _paperHeight, value); } private string _viewBoxWidth = "0"; public string ViewBoxWidth { get => _viewBoxWidth; set => UpdateProper(ref _viewBoxWidth, value); } private string _viewBoxHeight = "0"; public string ViewBoxHeight { get => _viewBoxHeight; set => UpdateProper(ref _viewBoxHeight, value); } private BitmapSource _priviewBitmapSource; public BitmapSource PreviewBitmapSource { get => _priviewBitmapSource; set => UpdateProper(ref _priviewBitmapSource, value); } private Thickness _margins; public Thickness Margins { get => _margins; set => UpdateProper(ref _margins, value); } private int _targetPaperIndex = 0; private Bitmap blankPageBitmap; public int TargetPaperIndex { get => _targetPaperIndex; set { if (UpdateProper(ref _targetPaperIndex, value)) { JumpToSelectedPage(); } } } public void SetViewBox(double height, double width) { if (height / width >= (248.0 / 180.0)) { ViewBoxHeight = "248.0"; ViewBoxWidth = (width / height * 248.0).ToString(); Margins = new Thickness() { Left = printSettingsInfo.Margins.Left * (248.0 / printSettingsInfo.PaperSize.Height), Right = printSettingsInfo.Margins.Right * (248.0 / printSettingsInfo.PaperSize.Height), Top = printSettingsInfo.Margins.Top * (248.0 / printSettingsInfo.PaperSize.Height), Bottom = printSettingsInfo.Margins.Bottom * (248.0 / printSettingsInfo.PaperSize.Height) }; } else { ViewBoxWidth = "180.0"; ViewBoxHeight = (height / width * 180.0).ToString(); Margins = new Thickness() { Left = printSettingsInfo.Margins.Left * (180.0 / printSettingsInfo.PaperSize.Width), Right = printSettingsInfo.Margins.Right * (180.0 / printSettingsInfo.PaperSize.Width), Top = printSettingsInfo.Margins.Top * (180.0 / printSettingsInfo.PaperSize.Width), Bottom = printSettingsInfo.Margins.Bottom * (180.0 / printSettingsInfo.PaperSize.Width) }; } } private void SetPreviewBox() { PaperKind = printSettingsInfo.PaperSize.Kind.ToString(); if (printSettingsInfo.PrintOrientation == PageOrientation.Portrait) { SetPortrait(); } else if (printSettingsInfo.PrintOrientation == PageOrientation.Landscape) { SetLandscape(); } else { CPDFPage page = printSettingsInfo.Document.PageAtIndex(printSettingsInfo.TargetPaperList[TargetPaperIndex]); if (page.PageSize.height > page.PageSize.width) { SetPortrait(); } else { SetLandscape(); } } if (!(printSettingsInfo.PrintMode is PosterModeInfo)) { SetViewBox(double.Parse(PaperHeight), double.Parse(PaperWidth)); } void SetPortrait() { PaperWidth = string.Format("{0:F1}", (printSettingsInfo.PaperSize.Width)); PaperHeight = string.Format("{0:F1}", (printSettingsInfo.PaperSize.Height)); } void SetLandscape() { PaperWidth = string.Format("{0:F1}", (printSettingsInfo.PaperSize.Height)); PaperHeight = string.Format("{0:F1}", (printSettingsInfo.PaperSize.Width)); } } internal void Init(PrintSettingsInfo printSettingsInfo, bool needPageReset = false) { this.printSettingsInfo = printSettingsInfo; PrintedPageCount = PrintHelper.CaculatePrintedPageCount(printSettingsInfo); CalculatePaperCollection(needPageReset); SetPreviewBox(); PaintPageByCurrentPreviewIndex(); } private void CreateBlankBitmap() { CPDFPage page = printSettingsInfo.Document.PageAtIndex(printSettingsInfo.TargetPaperList[TargetPaperIndex]); double height = 0; double width = 0; width = printSettingsInfo.PrintOrientation == PageOrientation.Portrait ? printSettingsInfo.ActualWidth : printSettingsInfo.ActualHeight; height = printSettingsInfo.PrintOrientation == PageOrientation.Portrait ? printSettingsInfo.ActualHeight : printSettingsInfo.ActualWidth; blankPageBitmap = new Bitmap((int)width, (int)height); using (Graphics g = Graphics.FromImage(blankPageBitmap)) { g.Clear(Color.White); } } public void CalculatePaperCollection(bool needPageReset = false) { printSettingsInfo.TargetPaperList = new List(printSettingsInfo.PageRangeList); if (printSettingsInfo.IsReverseOrder) { printSettingsInfo.TargetPaperList.Reverse(); } if (needPageReset) { PaperIndex = "1"; } } public PrintPreviewControl() { InitializeComponent(); DataContext = this; } private readonly object lockObject = new object(); private void PaintPageByCurrentPreviewIndex() { lock (lockObject) { CreateBlankBitmap(); PreviewPageBySizeMode(printSettingsInfo.TargetPaperList[TargetPaperIndex]); } } [System.Runtime.InteropServices.DllImport("gdi32.dll")] public static extern bool DeleteObject(IntPtr hObject); public BitmapSource ToBitmapSource(System.Drawing.Bitmap bmp) { IntPtr ptr = bmp.GetHbitmap();//obtain the Hbitmap try { BitmapSource bmpsrc = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap ( ptr, IntPtr.Zero, new Int32Rect(0, 0, bmp.Width, bmp.Height), System.Windows.Media.Imaging.BitmapSizeOptions.FromEmptyOptions() ); return bmpsrc; } finally { DeleteObject(ptr); } } public Bitmap Resize(Bitmap input, int targetWidth, int targetHeight) { try { var actualBitmap = new Bitmap(targetWidth, targetHeight); var g = Graphics.FromImage(actualBitmap); g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic; g.DrawImage(input, new Rectangle(0, 0, targetWidth, targetHeight), new Rectangle(0, 0, input.Width, input.Height), GraphicsUnit.Pixel); g.Dispose(); return actualBitmap; } catch (Exception ex) { return null; } } private void PreviewPageBySizeMode(int index) { if (!(printSettingsInfo.PrintMode is SizeModeInfo sizeModeInfo)) { return; } Bitmap printBitmap = new Bitmap((int)double.Parse(PaperWidth), (int)double.Parse(PaperHeight)); CPDFPage page = printSettingsInfo.Document.PageAtIndex(index); CSize cSize = page.PageSize; System.Drawing.Size pageSize = new System.Drawing.Size((int)cSize.width, (int)cSize.height); CRect pageRect = new CRect(0, (int)(pageSize.Height), (int)(pageSize.Width), 0); byte[] bmpData = new byte[(int)(pageRect.width() * pageRect.height() * 4)]; if (page != null) { page.RenderPageBitmapWithMatrix((float)1, pageRect, 0xFFFFFFFF, bmpData, printSettingsInfo.IsPrintAnnot ? 1 : 0, printSettingsInfo.IsPrintForm); Point startPoint = new Point(0, 0); Bitmap bitmap = PrintHelper.BuildBmp((int)pageRect.width(), (int)pageRect.height(), bmpData); if (printSettingsInfo.IsGrayscale) { bitmap = PrintHelper.ToGray(bitmap, 0); } if (sizeModeInfo.SizeType == SizeType.Adaptive) { int resizedHeight = 0; int resizedWidth = 0; if (bitmap.Height / bitmap.Width >= (printSettingsInfo.ActualHeight / printSettingsInfo.ActualWidth)) { if (printSettingsInfo.PrintOrientation == PageOrientation.Portrait) { resizedHeight = (int)printSettingsInfo.ActualHeight; resizedWidth = (int)(printSettingsInfo.ActualHeight / bitmap.Height * bitmap.Width); } else { resizedWidth = (int)printSettingsInfo.ActualHeight; resizedHeight = (int)(printSettingsInfo.ActualHeight / bitmap.Height * bitmap.Width); } } else { if (printSettingsInfo.PrintOrientation == PageOrientation.Portrait) { resizedWidth = (int)printSettingsInfo.ActualWidth; resizedHeight = (int)(printSettingsInfo.ActualWidth / bitmap.Width * bitmap.Height); } else { resizedHeight = (int)printSettingsInfo.ActualWidth; resizedWidth = (int)(printSettingsInfo.ActualWidth / bitmap.Height * bitmap.Width); } } bitmap = Resize(bitmap, resizedWidth, resizedHeight); startPoint.X = (blankPageBitmap.Width - resizedWidth) / 2; startPoint.Y = (blankPageBitmap.Height - resizedHeight) / 2; printBitmap = PrintHelper.CombineBitmap(blankPageBitmap, bitmap, startPoint); } else if (sizeModeInfo.SizeType == SizeType.Actural) { bitmap = PrintHelper.ResizeBitmap(bitmap, 100); startPoint.X = (blankPageBitmap.Width - bitmap.Width) / 2; startPoint.Y = (blankPageBitmap.Height - bitmap.Height) / 2; printBitmap = PrintHelper.CombineBitmap(blankPageBitmap, bitmap, startPoint); } else { float scale = sizeModeInfo.SizeType == SizeType.Customized ? sizeModeInfo.Scale : 1; bitmap = PrintHelper.ResizeBitmap(bitmap, scale); startPoint.X = (blankPageBitmap.Width - bitmap.Width) / 2; startPoint.Y = (blankPageBitmap.Height - bitmap.Height) / 2; printBitmap = PrintHelper.CombineBitmap(blankPageBitmap, bitmap, startPoint); } } PreviewBitmapSource = ToBitmapSource(printBitmap); } public void JumpToSelectedPage() { PaintPageByCurrentPreviewIndex(); } public event PropertyChangedEventHandler PropertyChanged; protected bool UpdateProper(ref T properValue, T newValue, [CallerMemberName] string properName = "") { if (object.Equals(properValue, newValue)) return false; properValue = newValue; OnPropertyChanged(properName); return true; } protected void OnPropertyChanged([CallerMemberName] string propertyName = "") => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); private void btnPreButton_Click(object sender, RoutedEventArgs e) { if (!int.TryParse(PaperIndex, out int _)) { _paperIndex = originalPaperIndex.ToString(); } PaperIndex = (int.Parse(PaperIndex) - 1).ToString(); } private void btnNextButton_Click(object sender, RoutedEventArgs e) { if (!int.TryParse(PaperIndex, out int _)) { _paperIndex = originalPaperIndex.ToString(); } PaperIndex = (int.Parse(PaperIndex) + 1).ToString(); } private void txbPageIndex_LostFocus(object sender, RoutedEventArgs e) { if (PaperIndex == string.Empty) { PaperIndex = (originalPaperIndex).ToString(); } } private void txbPageIndex_PreviewLostKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e) { if (e.NewFocus is Button button && (button == btnNextButton || button == btnPreButton)) { e.Handled = true; } } } }