using ComPDFKit.PDFDocument; using ComPDFKit.PDFPage; using ComPDFKitViewer.PdfViewer; using Dropbox.Api.TeamLog; using Microsoft.Office.Interop.Word; using Microsoft.Win32; using PDF_Master.CustomControl; using PDF_Master.EventAggregators; using PDF_Master.Helper; using PDF_Master.Model; using PDF_Master.Model.Dialog.ToolsDialogs; using PDF_Master.Properties; using PDF_Master.Views.Dialog; using Prism.Commands; using Prism.Events; using Prism.Mvvm; using Prism.Services.Dialogs; using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.IO; using System.Linq; using System.Reflection; using System.Text; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Media; using System.Windows.Media.Imaging; using static Dropbox.Api.TeamLog.PaperDownloadFormat; using static PDF_Master.Model.Dialog.ToolsDialogs.SaftyDialogs.DeleteSafetySettintgsModel; namespace PDF_Master.ViewModels.Dialog.ToolsDialogs { class MergeDialogViewModel : BindableBase, IDialogAware { // Fix:存储当前程序加载的文档的路径和tag, //如果路径相同则用tag里的密码解锁, //解锁失败再另行提权 private string CurrentFilePath = string.Empty; private string currentLoadedPassword = string.Empty; private IEventAggregator eventAggregator; enum PageSizeType { kDefault = 0, A4 = 1, A3 = 2, Letter = 3, Legal = 4, Customized = 5, } #region 框架内容 public string Title => ""; public event Action RequestClose; public bool CanCloseDialog() { return true; } public void OnDialogClosed() { } public void OnDialogOpened(IDialogParameters parameters) { CPDFViewer pdfViewer = null; if (parameters.TryGetValue(ParameterNames.PDFViewer, out pdfViewer) && pdfViewer != null && pdfViewer.Document != null) { VerifyPasswordResult condition = SecurityHelper.VerifyPasswordByPasswordKind(pdfViewer.Document, EnumPasswordKind.StatusPermissionsPassword, dialogs); if (condition.IsDiscryptied) { if (!string.IsNullOrEmpty(condition.Password)) { if (pdfViewer.Document.UnlockWithPassword(condition.Password)) { pdfViewer.Document.CheckOwnerPassword(condition.Password); } } string unicode; if (parameters.TryGetValue(ParameterNames.Unicode, out unicode)) { this.eventAggregator.GetEvent().Publish(new ShowTipEventArgs() { enumTipKind = EnumTipKind.StatusNone, Unicode = unicode }); } } currentLoadedPassword = pdfViewer.Document.Password; } if (pdfViewer != null && pdfViewer.Document != null) { CurrentFilePath = pdfViewer.Document.FilePath; List list = new List(); list.Add(CurrentFilePath); AddFiles(list.ToArray()); } string[] Paths; parameters.TryGetValue(ParameterNames.FilePath, out Paths); if (Paths != null) { AddFiles(Paths); } } #endregion #region 定义与初始化 public ObservableCollection MergeObjectlist { get; set; } public DelegateCommand CancelCommand { get; set; } public DelegateCommand PreviewCancelDownCommand { get; set; } public DelegateCommand MergeCommand { get; set; } public DelegateCommand AddFilesCommand { get; set; } public DelegateCommand ClearCommand { get; set; } public DelegateCommand SetPageSizeTypeCommand { get; set; } public IDialogService dialogs; private PageSizeType pageSizeType = PageSizeType.kDefault; private string inputWidth; public string InputWidth { get { return inputWidth; } set { SetProperty(ref inputWidth, value); } } private string inputHeight; public string InputHeight { get { return inputHeight; } set { SetProperty(ref inputHeight, value); } } private int comboBoxSelectedIndex = 0; public int ComboBoxSelectedIndex { get { return comboBoxSelectedIndex; } set { SetProperty(ref comboBoxSelectedIndex, value); } } public MergeDialogViewModel(IDialogService dialogService, IEventAggregator eventAggregator) { this.eventAggregator = eventAggregator; dialogs = dialogService; MergeObjectlist = new ObservableCollection(); CancelCommand = new DelegateCommand(Cancel); PreviewCancelDownCommand = new DelegateCommand(PreviewCancelDown); AddFilesCommand = new DelegateCommand(ButtonAddFiles); MergeCommand = new DelegateCommand(Merge); ClearCommand = new DelegateCommand(Clear); SetPageSizeTypeCommand = new DelegateCommand(SetPageSizeType); } #endregion #region 私有方法 private void UpDataMergeObjectIndex() { for (int i = 0; i < MergeObjectlist.Count; i++) { MergeObjectlist[i].ItemIndex = i + 1; } } private void Cancel() { Clear(); RequestClose.Invoke(new DialogResult(ButtonResult.Cancel)); } /// /// 点击取消页面范围控件使失去焦点不生效 /// private void PreviewCancelDown(object e) { var listView = e as ListView; if (listView != null) { if (listView.ItemsSource != null) { foreach (var item in listView.ItemsSource) { var pagerange= listView.ItemContainerGenerator.ContainerFromItem(item) as ListViewItem; if (pagerange != null) { var pagerangecombobox= CommonHelper.FindVisualChild(pagerange); if(pagerangecombobox!=null) pagerangecombobox.IsloseFocus = false; } } } } } public void ButtonAddFiles(object data) { int index = Convert.ToInt32(data); switch (index) { case 0: //打开文件 ComboBoxSelectedIndex = 0;//打开文件弹窗会影响UI更新,所以手动更新 AddFiles(OpenFile()); break; case 1: //打开文件夹 ComboBoxSelectedIndex = 1;//打开文件夹弹窗会影响UI更新,所以手动更新 AddFiles(OpenFileFolder()); break; case 2: //打开当前文件 List list = new List(); for (int i = 0; i < App.OpenedFileList.Count; i++) { list.Add(App.OpenedFileList[i]); } AddFiles(list.ToArray()); break; default: break; } } private string[] OpenFileFolder() { System.Windows.Forms.FolderBrowserDialog openFile = new System.Windows.Forms.FolderBrowserDialog(); if (openFile.ShowDialog() == System.Windows.Forms.DialogResult.Cancel) { return null; } DirectoryInfo tempfolder = new DirectoryInfo(openFile.SelectedPath); FileInfo[] fileInfos = tempfolder.GetFiles(); List list = new List(); foreach (FileInfo item in fileInfos) { list.Add(item.FullName); } DirectoryInfo[] directoryInfos = tempfolder.GetDirectories(); foreach (DirectoryInfo fileInfo in directoryInfos) { FileInfo[] fileinfo = fileInfo.GetFiles(); foreach (FileInfo item in fileinfo) { list.Add(item.FullName); } } return list.ToArray(); } private string[] OpenFile() { OpenFileDialog openFile = new OpenFileDialog(); openFile.Multiselect = true; openFile.Filter = Properties.Resources.imageex.ToLower() + "|*"; if (openFile.ShowDialog() == false) { return null; } return openFile.FileNames; } private void Merge() { bool result = true; CPDFDocument SaveDoc = CPDFDocument.CreateDocument(); for (int i = 0; i < MergeObjectlist.Count; i++) { List listnum = new List(); if (MergeObjectlist[i].SetPageRange == null || MergeObjectlist[i].SetPageRange.Count == 0) { AlertsMessage alertsMessage = new AlertsMessage(); alertsMessage.ShowDialog("", App.MainPageLoader.GetString("PageRangeWarning"), App.ServiceLoader.GetString("Text_ok")); return; } } for (int i = 0; i < MergeObjectlist.Count; i++) { if (MergeObjectlist[i].SetPageRange == null) { AlertsMessage alertsMessage = new AlertsMessage(); alertsMessage.ShowDialog("", App.MainPageLoader.GetString("PageRangeWarning"), App.ServiceLoader.GetString("Text_ok")); } //图片 if (Path.GetExtension(MergeObjectlist[i].FilePath).Trim().ToLower() != ".pdf") { if (Path.GetExtension(MergeObjectlist[i].FilePath).Trim().ToLower() == ".gif") {//GIF下面方法产生虚影改成与图片转PDF一致 System.Drawing.Image img = System.Drawing.Image.FromFile(MergeObjectlist[i].FilePath); string tempFileName = Path.GetTempPath() + "pngtemp.jpg"; if (!PictureConverter.SaveJpeg(MergeObjectlist[i].FilePath, tempFileName)) { MessageBoxEx.Show("图片格式有问题"); } // 之前插入位置为零点导致插入为第一页,改为尾插 2023/5/24 result = SaveDoc.InsertPage(SaveDoc.PageCount, img.Width, img.Height, tempFileName); try { if (File.Exists(tempFileName)) File.Delete(tempFileName); } catch { } if (!result) { SaveDoc.Release(); return; } continue; } else { BitmapSource frame = MergeObjectlist[i].DocThumbnail; byte[] imageData = new byte[frame.PixelWidth * frame.PixelHeight * 4]; if (frame.Format != PixelFormats.Bgra32) { FormatConvertedBitmap covert = new FormatConvertedBitmap(frame, PixelFormats.Bgra32, frame.Palette, 0); covert.CopyPixels(imageData, frame.PixelWidth * 4, 0); } else { frame.CopyPixels(imageData, frame.PixelWidth * 4, 0); } frame.CopyPixels(imageData, frame.PixelWidth * 4, 0); // 之前插入位置为零点导致插入为第一页,改为尾插 2023/5/24 result = SaveDoc.InsertPage(SaveDoc.PageCount, frame.PixelWidth, frame.PixelHeight, imageData, CPDFDocumentImageMode.CPDFDocumentImageModeScaleToFill); if (!result) { SaveDoc.Release(); return; } continue; } } else { CPDFDocument tempDoc = CPDFDocument.InitWithFilePath(MergeObjectlist[i].FilePath); if (!string.IsNullOrEmpty(MergeObjectlist[i].Password)) { tempDoc.UnlockWithPassword(MergeObjectlist[i].Password); } if (!string.IsNullOrEmpty(MergeObjectlist[i].SetPageRangeStr)) { result = SaveDoc.ImportPages(tempDoc, MergeObjectlist[i].SetPageRangeStr); } else { //下拉框控件传出来的list是页面索引集合, //此处传给SDK的合并接口的是页码集合,因此需要将集合项遍历+1,只有合并接口是接收页码集合,其余接口是接受页面索引集合 List pageIndexs = new List(); for (int j = 0; j < MergeObjectlist[i].SetPageRange.Count; j++) { pageIndexs.Add(MergeObjectlist[i].SetPageRange[j] + 1); } result = SaveDoc.ImportPages(tempDoc, CommonHelper.GetPageParmFromList(pageIndexs)); } if (!result) { SaveDoc.Release(); tempDoc.Release(); return; } tempDoc.Release(); } } SaveFileDialog saveFileDialog = new SaveFileDialog(); saveFileDialog.FileName = "Untitle"; saveFileDialog.Filter = "PDF|*.pdf;"; if (saveFileDialog.ShowDialog() == false) { return; } string path = saveFileDialog.FileName; System.Windows.Rect rect = new System.Windows.Rect(); switch (pageSizeType) { case PageSizeType.kDefault: break; case PageSizeType.A4: rect.Width = CommonHelper.GetPageSizeFomrUnit(210); rect.Height = CommonHelper.GetPageSizeFomrUnit(297); break; case PageSizeType.A3: rect.Width = CommonHelper.GetPageSizeFomrUnit(297); rect.Height = CommonHelper.GetPageSizeFomrUnit(420); break; case PageSizeType.Letter: rect.Width = CommonHelper.GetPageSizeFomrUnit(216); rect.Height = CommonHelper.GetPageSizeFomrUnit(279); break; case PageSizeType.Legal: rect.Width = CommonHelper.GetPageSizeFomrUnit(216); rect.Height = CommonHelper.GetPageSizeFomrUnit(356); break; case PageSizeType.Customized: if (!string.IsNullOrEmpty(InputWidth) && !string.IsNullOrEmpty(InputHeight)) { rect.Width = CommonHelper.GetPageSizeFomrUnit(Convert.ToInt32(InputWidth)); rect.Height = CommonHelper.GetPageSizeFomrUnit(Convert.ToInt32(InputHeight)); } else { rect.Width = CommonHelper.GetPageSizeFomrUnit(595); rect.Height = CommonHelper.GetPageSizeFomrUnit(841); } break; default: break; } if (rect.Width > 0 && rect.Height > 0) { //裁剪 for (int i = 0; i < SaveDoc.PageCount; i++) { CPDFPage page = SaveDoc.PageAtIndex(i); page.CropPage(CPDFDisplayBox.MediaBox, rect); } } bool saveResult = SaveDoc.WriteToFilePath(path); SaveDoc.Release(); CommonHelper.ShowFileBrowser(path); DialogParameters valuePairs = new DialogParameters(); valuePairs.Add(ParameterNames.FilePath, path); RequestClose.Invoke(new DialogResult(ButtonResult.OK, valuePairs)); } private void Clear() { MergeObjectlist.Clear(); } private void SetPageSizeType(object button) { if (button is RadioButton) { pageSizeType = (PageSizeType)Convert.ToInt32((button as RadioButton).Tag); } } #endregion #region 公开方法 public void DeleteItem(MergeObject merge) { MergeObjectlist.Remove(merge); UpDataMergeObjectIndex(); } /// /// 拖拽插入 /// public void MoveMerge(MergeObject targetNode, MergeObject soureNode) { int targetindex = MergeObjectlist.IndexOf(targetNode); MergeObjectlist.Remove(soureNode); if (targetNode.IsForward) { if (targetindex + 1 < MergeObjectlist.Count) { MergeObjectlist.Insert(targetindex + 1, soureNode); } else { MergeObjectlist.Add(soureNode); } } else { MergeObjectlist.Insert(targetindex, soureNode); } UpDataMergeObjectIndex(); } public void AddFiles(string[] FilePath) { if (FilePath == null) { return; } bool showDialog = false; for (int i = 0; i < FilePath.Length; i++) { MergeObject mergeObject = new MergeObject(); mergeObject.FilePath = FilePath[i]; //通过路径判断文件是否已添加 bool IsExists = false; for (int j = 0; j < MergeObjectlist.Count; j++) { if (MergeObjectlist[j].FilePath == mergeObject.FilePath) { IsExists = true; } } if (IsExists) { continue; } string FileType = Path.GetExtension(mergeObject.FilePath).Trim().ToLower(); if (string.IsNullOrEmpty(FileType)) { showDialog = true; //获取不到文件类型 continue; } if (FileType != ".pdf") { string imagetype = "*" + FileType; string[] x = Properties.Resources.imageex.ToLower().Split(';'); List list = x.ToList(); int imageindex = list.IndexOf(imagetype); if (imageindex < 0) { showDialog = true; //图片格式不支持 continue; }; mergeObject.DocName = Path.GetFileName(mergeObject.FilePath); mergeObject.DocPageCount = 1 + " " + App.MainPageLoader.GetString("Merge_ItemPages"); mergeObject.SDKPageCount = 1; mergeObject.DocSize = CommonHelper.GetFileSize(mergeObject.FilePath); try { mergeObject.DocThumbnail = new BitmapImage(new Uri(mergeObject.FilePath)); } catch (Exception) { showDialog = true; //解码错误 continue; } } else { CPDFDocument doc = CPDFDocument.InitWithFilePath(mergeObject.FilePath); if (doc == null) { showDialog = true; //PDF打开失败 continue; } ///Fix: ///情况分为: ///开启路径是当前路径: ///已解锁或本身就无密码->直接加入 ///未解锁-> release /// /// 不是当前路径 ///解锁或取消-> /// if (CurrentFilePath == doc.FilePath) { if ((!(!doc.IsLocked && (SecurityHelper.CheckHaveAllPermissions(doc)))) && (!(!string.IsNullOrEmpty(currentLoadedPassword) && doc.UnlockWithPassword(currentLoadedPassword) && (doc.CheckOwnerPassword(currentLoadedPassword) || SecurityHelper.CheckHaveAllPermissions(doc))))) { doc.Release(); continue; } //添加的第一个文档有权限密码时,保存密码,避免合并时因没有密码导致合并失败 //表现为在首页打开一个带权限的文档进入合并,点击合并按钮没有反应 if (!string.IsNullOrEmpty(currentLoadedPassword)) { mergeObject.Password = currentLoadedPassword; } } else { VerifyPasswordResult condition = SecurityHelper.VerifyPasswordByPasswordKind(doc, EnumPasswordKind.StatusPermissionsPassword, dialogs); if (condition.IsDiscryptied) { if (condition.Password != null) { mergeObject.Password = condition.Password; if (doc.UnlockWithPassword(condition.Password) && doc.CheckOwnerPassword(condition.Password)) { } } } else { doc.Release(); continue; } } mergeObject.DocName = doc.FileName; mergeObject.DocPageCount = doc.PageCount.ToString() + " " + App.MainPageLoader.GetString("Merge_ItemPages"); if (doc.PageCount > 1) { mergeObject.IsEvenPageIsEnabled = true; } else { mergeObject.IsEvenPageIsEnabled = false; } mergeObject.SDKPageCount = doc.PageCount; mergeObject.DocSize = CommonHelper.GetFileSize(mergeObject.FilePath); //获取第一页缩略图 CPDFPage page = doc.PageAtIndex(0); Size size = doc.GetPageSize(0); byte[] bmpData = new byte[(int)(size.Width * size.Height * 4)]; WriteableBitmap WirteBitmap = new WriteableBitmap((int)size.Width, (int)size.Height, 96, 96, PixelFormats.Bgra32, null); page.RenderPageBitmap(0, 0, (int)size.Width, (int)size.Height, 0xFFFFFFFF, bmpData, 1); WirteBitmap.WritePixels(new Int32Rect(0, 0, (int)size.Width, (int)size.Height), bmpData, WirteBitmap.BackBufferStride, 0); WirteBitmap.Freeze(); mergeObject.DocThumbnail = WirteBitmap; doc.Release(); } MergeObjectlist.Add(mergeObject); UpDataMergeObjectIndex(); } if (showDialog) { AlertsMessage alertsMessage = new AlertsMessage(); alertsMessage.ShowDialog("", App.MainPageLoader.GetString("ErrorFile_Warning"), App.ServiceLoader.GetString("Text_ok")); if (alertsMessage.result == ContentResult.Ok) { } } } #endregion } }