using ComPDFKit.Import; using ComPDFKit.NativeMethod; using ComPDFKit.PDFDocument; using ComPDFKit.PDFPage; using System; using System.Collections.Generic; using System.Diagnostics; using System.Text.RegularExpressions; using System.Threading; using System.Windows.Media; using System.Windows; namespace ComPDFKit.Tool { /// /// This class is about search result object. /// public class TextSearchItem { /// /// Page index /// public int PageIndex; /// /// The bounds of the selection on the page(PDF 72DPI) /// public Rect TextRect; /// /// The text contains in the selection /// public string TextContent; /// /// Page rotation angle /// public int PageRotate; public void CreatePaintBrush(Color color) { Application.Current.Dispatcher.Invoke(() => { this.PaintBrush = new SolidColorBrush(color); }); } public SolidColorBrush PaintBrush { get; private set; } = Brushes.Transparent; public void CreateBorderBrush(Color color) { Application.Current.Dispatcher.Invoke(() => { this.BorderBrush = new SolidColorBrush(color); }); } public SolidColorBrush BorderBrush { get; private set; } = Brushes.Transparent; public int BorderThickness; public Thickness Padding; } /// /// Result of text search /// public class TextSearchResult { /// /// Start page index /// public int StartPage; /// /// End page index /// public int EndPage; /// /// Percentage of search process /// public double Percent; /// /// Current page index /// public int CurrentPage; /// /// The number of search result /// public int TotalCount; /// /// The maximum value of search result /// public int PageMaxCount; /// /// Details of current search result /// public Dictionary> Items = new Dictionary>(); } /// /// This class is about text search. /// public class PDFTextSearch { /// /// A notification that a find operation finished working on a page of a document. /// public event EventHandler SearchPercentHandler; /// /// A notification that a find operation cancels. /// public event EventHandler SearchCancelHandler; /// /// A notification that a find operation finished of a document. /// public event EventHandler SearchCompletedHandler; /// /// Associates a CPDFDocument. /// public CPDFDocument TextSearchDocument; private CPDFDocument mSearchDocument; private bool isCancel; private string searchKeywords; private string password; private C_Search_Options searchOption; private int startPage; private int endPage; /// /// Whether to allow to search. /// public bool CanDoSearch { get; private set; } = true; /// /// Constructor function. /// public PDFTextSearch() { } private void DoWork() { endPage = endPage == -1 ? TextSearchDocument.PageCount - 1 : Math.Min(TextSearchDocument.PageCount - 1, endPage); TextSearchResult searchResult = new TextSearchResult(); searchResult.StartPage = startPage; searchResult.EndPage = endPage; double searchPercent = 100; mSearchDocument = CPDFDocument.InitWithFilePath(TextSearchDocument.FilePath); if (mSearchDocument.IsLocked && !string.IsNullOrEmpty(password)) { mSearchDocument.UnlockWithPassword(password); } if (mSearchDocument != null && !mSearchDocument.IsLocked) { int pageMaxCount = 0; int recordCount = 0; searchPercent = 0; for (int i = startPage; i <= endPage; i++) { CPDFTextSearcher mPDFTextSearcher = new CPDFTextSearcher(); CPDFPage pageCore = mSearchDocument.PageAtIndex(i); if(pageCore == null) { continue; } CPDFTextPage textPage = pageCore.GetTextPage(); int startIndex = 0; List textSearchItems = new List(); if (mPDFTextSearcher.FindStart(textPage, searchKeywords, searchOption, startIndex)) { CRect textRect = new CRect(); string textContent = ""; while (mPDFTextSearcher.FindNext(pageCore, textPage, ref textRect, ref textContent, ref startIndex)) { if (textContent == "") { textContent = searchKeywords; } textSearchItems.Add(new TextSearchItem() { PageIndex = i, TextRect = new Rect(textRect.left, textRect.top, textRect.width(), textRect.height()), TextContent = textContent, PageRotate = pageCore.Rotation }); var matchResult = Regex.Matches(textContent, searchKeywords, RegexOptions.IgnoreCase); if (matchResult != null) { recordCount += matchResult.Count; } } } mPDFTextSearcher.FindClose(); if (textSearchItems.Count > 0) { searchResult.Items.Add(i, textSearchItems); } pageMaxCount = Math.Max(pageMaxCount, textSearchItems.Count); searchResult.TotalCount = recordCount; searchResult.PageMaxCount = pageMaxCount; if (SearchPercentHandler != null) { searchPercent = (int)((i + 1 - startPage) * 100 / (endPage + 1 - startPage)); searchResult.Percent = searchPercent; searchResult.CurrentPage = i; SearchPercentHandler.Invoke(this, searchResult); } mSearchDocument.ReleasePages(i); if (isCancel) { break; } } searchPercent = 100; mSearchDocument.Release(); } if (SearchCompletedHandler != null && !isCancel) { searchResult.Percent = searchPercent; SearchCompletedHandler.Invoke(this, searchResult); } if (SearchCancelHandler != null && isCancel) { SearchCancelHandler.Invoke(this, searchResult); } CanDoSearch = true; isCancel = false; } /// /// Cancles a search. /// public void CancleSearch() { isCancel = true; } /// /// Searches the specified string in the document. /// /// Search the specified string /// Search options /// Document password /// Start page index /// End page index /// Returns true on success, false on failure public bool SearchText(string search, C_Search_Options option, string pwd = "", int startPage = 0, int endPage = -1) { if (CPDFSDKVerifier.TextSearch == false) { Trace.WriteLine("Your license does not support this feature, please upgrade your license privilege."); return false; } if (CanDoSearch) { searchKeywords = search; password = pwd; searchOption = option; this.startPage = startPage; this.endPage = endPage; isCancel = false; CanDoSearch = false; Thread taskThread = new Thread(DoWork); taskThread.Start(); return true; } return false; } } }