From 983dbfb16bf226334a3bbfcd1aa6f407b427bfcd Mon Sep 17 00:00:00 2001 From: wiera987 Date: Mon, 6 May 2019 10:58:26 +0900 Subject: [PATCH 01/39] Improve GetTextBounds() not to bump. --- PdfiumViewer/NativeMethods.Pdfium.cs | 22 ++++++++++++++++++++++ PdfiumViewer/PdfFile.cs | 16 +++++++++++++++- 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/PdfiumViewer/NativeMethods.Pdfium.cs b/PdfiumViewer/NativeMethods.Pdfium.cs index 33c245ae..b2927b87 100644 --- a/PdfiumViewer/NativeMethods.Pdfium.cs +++ b/PdfiumViewer/NativeMethods.Pdfium.cs @@ -290,6 +290,22 @@ public static void FPDFText_GetCharBox(IntPtr page, int index, out double left, } } + public static int FPDFText_CountRects(IntPtr page, int start_index, int count) + { + lock (LockString) + { + return Imports.FPDFText_CountRects(page, start_index, count); + } + } + + public static void FPDFText_GetRect(IntPtr page, int rect_index, out double left, out double top, out double right, out double bottom) + { + lock (LockString) + { + Imports.FPDFText_GetRect(page, rect_index, out left, out top, out right, out bottom); + } + } + public static int FPDFText_CountChars(IntPtr page) { lock (LockString) @@ -699,6 +715,12 @@ private static class Imports [DllImport("pdfium.dll")] public static extern int FPDFText_CountChars(IntPtr page); + [DllImport("pdfium.dll")] + public static extern int FPDFText_CountRects(IntPtr page, int start_index, int count); + + [DllImport("pdfium.dll")] + public static extern bool FPDFText_GetRect(IntPtr page, int rect_index, out double left, out double right, out double bottom, out double top); + [DllImport("pdfium.dll")] public static extern bool FPDFText_FindNext(IntPtr handle); diff --git a/PdfiumViewer/PdfFile.cs b/PdfiumViewer/PdfFile.cs index 298e8198..8ec9146c 100644 --- a/PdfiumViewer/PdfFile.cs +++ b/PdfiumViewer/PdfFile.cs @@ -282,9 +282,23 @@ public PdfMatches Search(string text, bool matchCase, bool wholeWord, int startP public IList GetTextBounds(PdfTextSpan textSpan) { + var result = new List(); + using (var pageData = new PageData(_document, _form, textSpan.Page)) + { - return GetTextBounds(pageData.TextPage, textSpan.Page, textSpan.Offset, textSpan.Length); + int rect_count = NativeMethods.FPDFText_CountRects(pageData.TextPage, textSpan.Offset, textSpan.Length); + + for (int i = 0; i < rect_count; i++) + { + NativeMethods.FPDFText_GetRect(pageData.TextPage, i, out var left, out var top, out var right, out var bottom); + + RectangleF bounds = new RectangleF((float)left, (float)top, (float)(right - left), (float)(bottom - top)); + + result.Add(new PdfRectangle(textSpan.Page, bounds)); + } + + return result; } } From 41d388dcf7e438e10c69907de9833d9e60f241ac Mon Sep 17 00:00:00 2001 From: wiera987 Date: Mon, 6 May 2019 19:07:41 +0900 Subject: [PATCH 02/39] Performance improvement. - Cached PageData, but PDFForm not tested. --- PdfiumViewer/PdfFile.cs | 65 +++++++++++++++++++++++++++++------------ 1 file changed, 46 insertions(+), 19 deletions(-) diff --git a/PdfiumViewer/PdfFile.cs b/PdfiumViewer/PdfFile.cs index 8ec9146c..27bc72e7 100644 --- a/PdfiumViewer/PdfFile.cs +++ b/PdfiumViewer/PdfFile.cs @@ -20,6 +20,7 @@ internal class PdfFile : IDisposable private GCHandle _formCallbacksHandle; private readonly int _id; private Stream _stream; + private List _pageData = null; public PdfFile(Stream stream, string password) { @@ -45,7 +46,7 @@ public bool RenderPDFPageToDC(int pageNumber, IntPtr dc, int dpiX, int dpiY, int if (_disposed) throw new ObjectDisposedException(GetType().Name); - using (var pageData = new PageData(_document, _form, pageNumber)) + var pageData = GetPageData(_document, _form, pageNumber); { NativeMethods.FPDF_RenderPage(dc, pageData.Page, boundsOriginX, boundsOriginY, boundsWidth, boundsHeight, 0, flags); } @@ -58,7 +59,7 @@ public bool RenderPDFPageToBitmap(int pageNumber, IntPtr bitmapHandle, int dpiX, if (_disposed) throw new ObjectDisposedException(GetType().Name); - using (var pageData = new PageData(_document, _form, pageNumber)) + var pageData = GetPageData(_document, _form, pageNumber); { if (renderFormFill) flags &= ~NativeMethods.FPDF.ANNOT; @@ -79,7 +80,7 @@ public PdfPageLinks GetPageLinks(int pageNumber, Size pageSize) var links = new List(); - using (var pageData = new PageData(_document, _form, pageNumber)) + var pageData = GetPageData(_document, _form, pageNumber); { int link = 0; IntPtr annotation; @@ -126,10 +127,12 @@ public List GetPDFDocInfo() int pageCount = NativeMethods.FPDF_GetPageCount(_document); var result = new List(pageCount); + _pageData = new List(pageCount); for (int i = 0; i < pageCount; i++) { result.Add(GetPDFDocInfo(i)); + _pageData.Add(null); } return result; @@ -241,7 +244,7 @@ public PdfMatches Search(string text, bool matchCase, bool wholeWord, int startP for (int page = startPage; page <= endPage; page++) { - using (var pageData = new PageData(_document, _form, page)) + var pageData = GetPageData(_document, _form, page); { NativeMethods.FPDF_SEARCH_FLAGS flags = 0; if (matchCase) @@ -284,7 +287,7 @@ public IList GetTextBounds(PdfTextSpan textSpan) { var result = new List(); - using (var pageData = new PageData(_document, _form, textSpan.Page)) + var pageData = GetPageData(_document, _form, textSpan.Page); { int rect_count = NativeMethods.FPDFText_CountRects(pageData.TextPage, textSpan.Offset, textSpan.Length); @@ -304,7 +307,7 @@ public IList GetTextBounds(PdfTextSpan textSpan) public Point PointFromPdf(int page, PointF point) { - using (var pageData = new PageData(_document, _form, page)) + var pageData = GetPageData(_document, _form, page); { NativeMethods.FPDF_PageToDevice( pageData.Page, @@ -325,7 +328,7 @@ out var deviceY public Rectangle RectangleFromPdf(int page, RectangleF rect) { - using (var pageData = new PageData(_document, _form, page)) + var pageData = GetPageData(_document, _form, page); { NativeMethods.FPDF_PageToDevice( pageData.Page, @@ -364,7 +367,7 @@ out var deviceY2 public PointF PointToPdf(int page, Point point) { - using (var pageData = new PageData(_document, _form, page)) + var pageData = GetPageData(_document, _form, page); { NativeMethods.FPDF_DeviceToPage( pageData.Page, @@ -385,7 +388,7 @@ out var deviceY public RectangleF RectangleToPdf(int page, Rectangle rect) { - using (var pageData = new PageData(_document, _form, page)) + var pageData = GetPageData(_document, _form, page); { NativeMethods.FPDF_DeviceToPage( pageData.Page, @@ -489,7 +492,7 @@ out var top public string GetPdfText(int page) { - using (var pageData = new PageData(_document, _form, page)) + var pageData = GetPageData(_document, _form, page); { int length = NativeMethods.FPDFText_CountChars(pageData.TextPage); return GetPdfText(pageData, new PdfTextSpan(page, 0, length)); @@ -498,7 +501,7 @@ public string GetPdfText(int page) public string GetPdfText(PdfTextSpan textSpan) { - using (var pageData = new PageData(_document, _form, textSpan.Page)) + var pageData = GetPageData(_document, _form, textSpan.Page); { return GetPdfText(pageData, textSpan); } @@ -511,14 +514,14 @@ private string GetPdfText(PageData pageData, PdfTextSpan textSpan) return FPDFEncoding.GetString(result, 0, textSpan.Length * 2); } - public void DeletePage (int pageNumber) + public void DeletePage(int pageNumber) { NativeMethods.FPDFPage_Delete(_document, pageNumber); } - public void RotatePage (int pageNumber, PdfRotation rotation) + public void RotatePage(int pageNumber, PdfRotation rotation) { - using (var pageData = new PageData(_document, _form, pageNumber)) + var pageData = GetPageData(_document, _form, pageNumber); { NativeMethods.FPDFPage_SetRotation(pageData.Page, rotation); } @@ -609,6 +612,17 @@ private string GetMetaText(string tag) return null; } + private PageData GetPageData(IntPtr document, IntPtr form, int pageNumber) + { + if (_pageData[pageNumber] == null) + { + _pageData[pageNumber] = new PageData(document, form, pageNumber); + } + + return _pageData[pageNumber]; + + } + public void Dispose() { Dispose(true); @@ -622,6 +636,14 @@ protected virtual void Dispose(bool disposing) { StreamManager.Unregister(_id); + foreach( var pageData in _pageData) + { + if (pageData != null) + { + pageData.Dispose(); + } + } + if (_form != IntPtr.Zero) { NativeMethods.FORM_DoDocumentAAction(_form, NativeMethods.FPDFDOC_AACTION.WC); @@ -667,9 +689,11 @@ public PageData(IntPtr document, IntPtr form, int pageNumber) Page = NativeMethods.FPDF_LoadPage(document, pageNumber); TextPage = NativeMethods.FPDFText_LoadPage(Page); - NativeMethods.FORM_OnAfterLoadPage(Page, form); - NativeMethods.FORM_DoPageAAction(Page, form, NativeMethods.FPDFPAGE_AACTION.OPEN); - + if (_form != null) + { + NativeMethods.FORM_OnAfterLoadPage(Page, form); + NativeMethods.FORM_DoPageAAction(Page, form, NativeMethods.FPDFPAGE_AACTION.OPEN); + } Width = NativeMethods.FPDF_GetPageWidth(Page); Height = NativeMethods.FPDF_GetPageHeight(Page); } @@ -678,8 +702,11 @@ public void Dispose() { if (!_disposed) { - NativeMethods.FORM_DoPageAAction(Page, _form, NativeMethods.FPDFPAGE_AACTION.CLOSE); - NativeMethods.FORM_OnBeforeClosePage(Page, _form); + if (_form != null) + { + NativeMethods.FORM_DoPageAAction(Page, _form, NativeMethods.FPDFPAGE_AACTION.CLOSE); + NativeMethods.FORM_OnBeforeClosePage(Page, _form); + } NativeMethods.FPDFText_ClosePage(TextPage); NativeMethods.FPDF_ClosePage(Page); From 7070dcce7842a84d82004cebfd290e0060429b42 Mon Sep 17 00:00:00 2001 From: wiera987 Date: Sun, 26 May 2019 17:02:07 +0900 Subject: [PATCH 03/39] Fixed the blank space at the end of PDF file which has 1500 pages. --- PdfiumViewer/PdfRenderer.cs | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/PdfiumViewer/PdfRenderer.cs b/PdfiumViewer/PdfRenderer.cs index 47b4ff98..daccb1cc 100644 --- a/PdfiumViewer/PdfRenderer.cs +++ b/PdfiumViewer/PdfRenderer.cs @@ -14,7 +14,6 @@ public class PdfRenderer : PanningZoomingScrollControl { private static readonly Padding PageMargin = new Padding(4); - private int _height; private int _maxWidth; private int _maxHeight; private double _documentScaleFactor; @@ -404,14 +403,12 @@ public void Load(IPdfDocument document) private void ReloadDocument() { - _height = 0; _maxWidth = 0; _maxHeight = 0; foreach (var size in Document.PageSizes) { var translated = TranslateSize(size); - _height += (int)translated.Height; _maxWidth = Math.Max((int)translated.Width, _maxWidth); _maxHeight = Math.Max((int)translated.Height, _maxHeight); } @@ -678,7 +675,14 @@ private void DrawPageImage(Graphics graphics, int page, Rectangle pageBounds) /// The document bounds. protected override Rectangle GetDocumentBounds() { - int height = (int)(_height * _scaleFactor + (ShadeBorder.Size.Vertical + PageMargin.Vertical) * Document.PageCount); + int scaledHeight = 0; + for (int page = 0; page < Document.PageSizes.Count; page++) + { + var size = TranslateSize(Document.PageSizes[page]); + scaledHeight += (int)(size.Height * _scaleFactor); + } + + int height = (int)(scaledHeight + (ShadeBorder.Size.Vertical + PageMargin.Vertical) * Document.PageCount); int width = (int)(_maxWidth * _scaleFactor + ShadeBorder.Size.Horizontal + PageMargin.Horizontal); var center = new Point( From 8e1c98c3aaaa84e95f454ac5c6d8bb781aca5b1e Mon Sep 17 00:00:00 2001 From: wiera987 Date: Sun, 26 May 2019 23:54:07 +0900 Subject: [PATCH 04/39] Fixed an issue that could not move to the next page. This issue occurs when you zoom too far and only half a page or less appears on the screen. --- PdfiumViewer/PdfRenderer.cs | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/PdfiumViewer/PdfRenderer.cs b/PdfiumViewer/PdfRenderer.cs index daccb1cc..985f930d 100644 --- a/PdfiumViewer/PdfRenderer.cs +++ b/PdfiumViewer/PdfRenderer.cs @@ -68,15 +68,22 @@ public int Page for (int page = 0; page < Document.PageSizes.Count; page++) { var pageCache = _pageCache[page].OuterBounds; - if (top - 10 < pageCache.Top) + if (top >= pageCache.Top || top < pageCache.Bottom) { - // If more than 50% of the page is hidden, return the previous page. + float dispPageHeight = Math.Min(bottom, pageCache.Bottom) - top; + float dispOccupancy = dispPageHeight / (bottom - top); + float pageDispRatio = dispPageHeight / pageCache.Height; - int hidden = pageCache.Bottom - bottom; - if (hidden > 0 && (double)hidden / pageCache.Height > 0.5 && page > 0) - return page - 1; - - return page; + // If this page occupies more than 50% of the screen. + if (dispOccupancy >= 0.5) + { + return page; + } + // If more than 50% of this page is displayed. + if (pageDispRatio >= 0.5) + { + return page; + } } } From 91bf871576050b758d2a73c1d28a749c2ce21a10 Mon Sep 17 00:00:00 2001 From: wiera987 Date: Mon, 27 May 2019 00:10:49 +0900 Subject: [PATCH 05/39] Fixed maybe. --- PdfiumViewer/CustomScrollControl.cs | 2 +- PdfiumViewer/PanningZoomingScrollControl.cs | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/PdfiumViewer/CustomScrollControl.cs b/PdfiumViewer/CustomScrollControl.cs index b8f167e9..727df769 100644 --- a/PdfiumViewer/CustomScrollControl.cs +++ b/PdfiumViewer/CustomScrollControl.cs @@ -348,7 +348,7 @@ private bool SetDisplayRectangleSize(int width, int height) { bool needLayout = false; - double hScale = (double)width / _displayRect.Height; + double hScale = (double)width / _displayRect.Width; double vScale = (double)height / _displayRect.Height; if (_displayRect.Width != width || _displayRect.Height != height) diff --git a/PdfiumViewer/PanningZoomingScrollControl.cs b/PdfiumViewer/PanningZoomingScrollControl.cs index ce205d5d..62cc49df 100644 --- a/PdfiumViewer/PanningZoomingScrollControl.cs +++ b/PdfiumViewer/PanningZoomingScrollControl.cs @@ -126,8 +126,6 @@ public void ZoomOut() /// A that contains the event data. protected override void OnMouseWheel(MouseEventArgs e) { - base.OnMouseWheel(e); - bool doZoom; switch (MouseWheelMode) From 2781c08f54fd65214195a2bcbde70ca0b6ddc288 Mon Sep 17 00:00:00 2001 From: wiera987 Date: Mon, 27 May 2019 00:53:47 +0900 Subject: [PATCH 06/39] Fixed a wheel zoom issue that moved to a page not pointed by the mouse cursor. --- PdfiumViewer/PdfRenderer.cs | 64 ++++++++++++++++++++++++++----------- 1 file changed, 45 insertions(+), 19 deletions(-) diff --git a/PdfiumViewer/PdfRenderer.cs b/PdfiumViewer/PdfRenderer.cs index 985f930d..7b438fd3 100644 --- a/PdfiumViewer/PdfRenderer.cs +++ b/PdfiumViewer/PdfRenderer.cs @@ -172,6 +172,44 @@ private void Markers_CollectionChanged(object sender, EventArgs e) RedrawMarkers(); } + + /// + /// Converts client coordinates to PDF coordinates. + /// + /// Client coordinates to get the PDF location for. + /// The location in a PDF page or the rounded location if not matching PDF page. + public PdfPoint PointToPdfRounded(Point location) + { + if (Document == null) + return PdfPoint.Empty; + + var offset = GetScrollOffset(); + location.Offset(-offset.Width, -offset.Height); + + for (int page = 0; page < Document.PageSizes.Count; page++) + { + var pageCache = _pageCache[page]; + if ((location.Y >= pageCache.OuterBounds.Top) && + (location.Y < pageCache.OuterBounds.Bottom)) + { + location.X = Math.Min(Math.Max(location.X, pageCache.Bounds.Left), pageCache.Bounds.Right); + location.Y = Math.Min(Math.Max(location.Y, pageCache.Bounds.Top), pageCache.Bounds.Bottom); + + location = new Point( + location.X - pageCache.Bounds.X, + location.Y - pageCache.Bounds.Y + ); + + var translated = TranslatePointToPdf(pageCache.Bounds.Size, Document.PageSizes[page], location); + translated = Document.PointToPdf(page, new Point((int)translated.X, (int)translated.Y)); + + return new PdfPoint(page, translated); + } + } + + return PdfPoint.Empty; + } + /// /// Converts client coordinates to PDF coordinates. /// @@ -882,36 +920,24 @@ private SizeF TranslateSize(SizeF size) protected override void SetZoom(double zoom, Point? focus) { Point location; + PdfPoint pdfLocation; + + var bounds = GetDocumentBounds(); if (focus.HasValue) { - var bounds = GetDocumentBounds(); - - location = new Point( - focus.Value.X - bounds.X, - focus.Value.Y - bounds.Y - ); + location = focus.Value; } else { - var bounds = _pageCacheValid - ? _pageCache[Page].Bounds - : GetDocumentBounds(); - - location = new Point( - bounds.X, - bounds.Y - ); + location = new Point(0, 0); } - double oldScale = Zoom; + pdfLocation = PointToPdfRounded(location); base.SetZoom(zoom, null); - var newLocation = new Point( - (int)(location.X * (zoom / oldScale)), - (int)(location.Y * (zoom / oldScale)) - ); + var newLocation = PointFromPdf(pdfLocation); SetDisplayRectLocation( new Point( From e4c04c97114ad87495ba7bddc986965431b8f1ca Mon Sep 17 00:00:00 2001 From: wiera987 Date: Mon, 24 Jun 2019 00:11:11 +0900 Subject: [PATCH 07/39] Demo: Add the Text Mode button to copy text. Viewer: When dragging the mouse outside the window, it scrolls while selecting text. Loosen the judgment of the Y coordinate while the mouse is moving. --- PdfiumViewer.Demo/MainForm.Designer.cs | 114 +++++++++++++++---------- PdfiumViewer.Demo/MainForm.cs | 5 ++ PdfiumViewer.Demo/MainForm.resx | 15 ++++ PdfiumViewer.Demo/PdfRangeDocument.cs | 5 -- PdfiumViewer/IPdfDocument.cs | 7 -- PdfiumViewer/PdfDocument.cs | 10 --- PdfiumViewer/PdfFile.cs | 8 -- PdfiumViewer/PdfRenderer.cs | 59 ++++++++++--- PdfiumViewer/PdfViewerCursorMode.cs | 2 +- 9 files changed, 136 insertions(+), 89 deletions(-) diff --git a/PdfiumViewer.Demo/MainForm.Designer.cs b/PdfiumViewer.Demo/MainForm.Designer.cs index 7537f774..a219eb46 100644 --- a/PdfiumViewer.Demo/MainForm.Designer.cs +++ b/PdfiumViewer.Demo/MainForm.Designer.cs @@ -92,6 +92,8 @@ private void InitializeComponent() this.copyToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.selectAllToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.pdfViewer1 = new PdfiumViewer.PdfViewer(); + this.toolStripSeparator4 = new System.Windows.Forms.ToolStripSeparator(); + this._textMode = new System.Windows.Forms.ToolStripButton(); this.menuStrip1.SuspendLayout(); this.toolStrip1.SuspendLayout(); this.statusStrip1.SuspendLayout(); @@ -119,46 +121,46 @@ private void InitializeComponent() this.toolStripMenuItem3, this.exitToolStripMenuItem}); this.fileToolStripMenuItem.Name = "fileToolStripMenuItem"; - this.fileToolStripMenuItem.Size = new System.Drawing.Size(37, 20); + this.fileToolStripMenuItem.Size = new System.Drawing.Size(36, 20); this.fileToolStripMenuItem.Text = "&File"; // // openToolStripMenuItem // this.openToolStripMenuItem.Name = "openToolStripMenuItem"; this.openToolStripMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.O))); - this.openToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.openToolStripMenuItem.Size = new System.Drawing.Size(173, 22); this.openToolStripMenuItem.Text = "&Open"; this.openToolStripMenuItem.Click += new System.EventHandler(this.openToolStripMenuItem_Click); // // toolStripMenuItem1 // this.toolStripMenuItem1.Name = "toolStripMenuItem1"; - this.toolStripMenuItem1.Size = new System.Drawing.Size(177, 6); + this.toolStripMenuItem1.Size = new System.Drawing.Size(170, 6); // // printPreviewToolStripMenuItem // this.printPreviewToolStripMenuItem.Name = "printPreviewToolStripMenuItem"; - this.printPreviewToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.printPreviewToolStripMenuItem.Size = new System.Drawing.Size(173, 22); this.printPreviewToolStripMenuItem.Text = "Print Preview"; this.printPreviewToolStripMenuItem.Click += new System.EventHandler(this.printPreviewToolStripMenuItem_Click); // // printMultiplePagesToolStripMenuItem // this.printMultiplePagesToolStripMenuItem.Name = "printMultiplePagesToolStripMenuItem"; - this.printMultiplePagesToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.printMultiplePagesToolStripMenuItem.Size = new System.Drawing.Size(173, 22); this.printMultiplePagesToolStripMenuItem.Text = "Print Multiple Pages"; this.printMultiplePagesToolStripMenuItem.Click += new System.EventHandler(this.printMultiplePagesToolStripMenuItem_Click); // // toolStripMenuItem3 // this.toolStripMenuItem3.Name = "toolStripMenuItem3"; - this.toolStripMenuItem3.Size = new System.Drawing.Size(177, 6); + this.toolStripMenuItem3.Size = new System.Drawing.Size(170, 6); // // exitToolStripMenuItem // this.exitToolStripMenuItem.Name = "exitToolStripMenuItem"; this.exitToolStripMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Alt | System.Windows.Forms.Keys.F4))); - this.exitToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.exitToolStripMenuItem.Size = new System.Drawing.Size(173, 22); this.exitToolStripMenuItem.Text = "E&xit"; this.exitToolStripMenuItem.Click += new System.EventHandler(this.exitToolStripMenuItem_Click); // @@ -179,57 +181,57 @@ private void InitializeComponent() this.toolStripMenuItem6, this.informationToolStripMenuItem}); this.toolsToolStripMenuItem.Name = "toolsToolStripMenuItem"; - this.toolsToolStripMenuItem.Size = new System.Drawing.Size(47, 20); + this.toolsToolStripMenuItem.Size = new System.Drawing.Size(45, 20); this.toolsToolStripMenuItem.Text = "&Tools"; // // findToolStripMenuItem // this.findToolStripMenuItem.Name = "findToolStripMenuItem"; this.findToolStripMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.F))); - this.findToolStripMenuItem.Size = new System.Drawing.Size(244, 22); + this.findToolStripMenuItem.Size = new System.Drawing.Size(232, 22); this.findToolStripMenuItem.Text = "&Find"; this.findToolStripMenuItem.Click += new System.EventHandler(this.findToolStripMenuItem_Click); // // toolStripMenuItem7 // this.toolStripMenuItem7.Name = "toolStripMenuItem7"; - this.toolStripMenuItem7.Size = new System.Drawing.Size(241, 6); + this.toolStripMenuItem7.Size = new System.Drawing.Size(229, 6); // // renderToBitmapsToolStripMenuItem // this.renderToBitmapsToolStripMenuItem.Name = "renderToBitmapsToolStripMenuItem"; - this.renderToBitmapsToolStripMenuItem.Size = new System.Drawing.Size(244, 22); + this.renderToBitmapsToolStripMenuItem.Size = new System.Drawing.Size(232, 22); this.renderToBitmapsToolStripMenuItem.Text = "&Render to Bitmaps"; this.renderToBitmapsToolStripMenuItem.Click += new System.EventHandler(this.renderToBitmapsToolStripMenuItem_Click); // // toolStripMenuItem2 // this.toolStripMenuItem2.Name = "toolStripMenuItem2"; - this.toolStripMenuItem2.Size = new System.Drawing.Size(241, 6); + this.toolStripMenuItem2.Size = new System.Drawing.Size(229, 6); // // cutMarginsWhenPrintingToolStripMenuItem // this.cutMarginsWhenPrintingToolStripMenuItem.Name = "cutMarginsWhenPrintingToolStripMenuItem"; - this.cutMarginsWhenPrintingToolStripMenuItem.Size = new System.Drawing.Size(244, 22); + this.cutMarginsWhenPrintingToolStripMenuItem.Size = new System.Drawing.Size(232, 22); this.cutMarginsWhenPrintingToolStripMenuItem.Text = "Cut margins when printing"; this.cutMarginsWhenPrintingToolStripMenuItem.Click += new System.EventHandler(this.cutMarginsWhenPrintingToolStripMenuItem_Click); // // shrinkToMarginsWhenPrintingToolStripMenuItem // this.shrinkToMarginsWhenPrintingToolStripMenuItem.Name = "shrinkToMarginsWhenPrintingToolStripMenuItem"; - this.shrinkToMarginsWhenPrintingToolStripMenuItem.Size = new System.Drawing.Size(244, 22); + this.shrinkToMarginsWhenPrintingToolStripMenuItem.Size = new System.Drawing.Size(232, 22); this.shrinkToMarginsWhenPrintingToolStripMenuItem.Text = "Shrink to margins when printing"; this.shrinkToMarginsWhenPrintingToolStripMenuItem.Click += new System.EventHandler(this.shrinkToMarginsWhenPrintingToolStripMenuItem_Click); // // toolStripMenuItem4 // this.toolStripMenuItem4.Name = "toolStripMenuItem4"; - this.toolStripMenuItem4.Size = new System.Drawing.Size(241, 6); + this.toolStripMenuItem4.Size = new System.Drawing.Size(229, 6); // // deleteCurrentPageToolStripMenuItem // this.deleteCurrentPageToolStripMenuItem.Name = "deleteCurrentPageToolStripMenuItem"; - this.deleteCurrentPageToolStripMenuItem.Size = new System.Drawing.Size(244, 22); + this.deleteCurrentPageToolStripMenuItem.Size = new System.Drawing.Size(232, 22); this.deleteCurrentPageToolStripMenuItem.Text = "Delete Current Page"; this.deleteCurrentPageToolStripMenuItem.Click += new System.EventHandler(this.deleteCurrentPageToolStripMenuItem_Click); // @@ -241,58 +243,58 @@ private void InitializeComponent() this.rotate180ToolStripMenuItem, this.rotate270ToolStripMenuItem}); this.rotateCurrentPageToolStripMenuItem.Name = "rotateCurrentPageToolStripMenuItem"; - this.rotateCurrentPageToolStripMenuItem.Size = new System.Drawing.Size(244, 22); + this.rotateCurrentPageToolStripMenuItem.Size = new System.Drawing.Size(232, 22); this.rotateCurrentPageToolStripMenuItem.Text = "Rotate Current Page"; // // rotate0ToolStripMenuItem // this.rotate0ToolStripMenuItem.Name = "rotate0ToolStripMenuItem"; - this.rotate0ToolStripMenuItem.Size = new System.Drawing.Size(134, 22); + this.rotate0ToolStripMenuItem.Size = new System.Drawing.Size(138, 22); this.rotate0ToolStripMenuItem.Text = "Rotate 0°"; this.rotate0ToolStripMenuItem.Click += new System.EventHandler(this.rotate0ToolStripMenuItem_Click); // // rotate90ToolStripMenuItem // this.rotate90ToolStripMenuItem.Name = "rotate90ToolStripMenuItem"; - this.rotate90ToolStripMenuItem.Size = new System.Drawing.Size(134, 22); + this.rotate90ToolStripMenuItem.Size = new System.Drawing.Size(138, 22); this.rotate90ToolStripMenuItem.Text = "Rotate 90°"; this.rotate90ToolStripMenuItem.Click += new System.EventHandler(this.rotate90ToolStripMenuItem_Click); // // rotate180ToolStripMenuItem // this.rotate180ToolStripMenuItem.Name = "rotate180ToolStripMenuItem"; - this.rotate180ToolStripMenuItem.Size = new System.Drawing.Size(134, 22); + this.rotate180ToolStripMenuItem.Size = new System.Drawing.Size(138, 22); this.rotate180ToolStripMenuItem.Text = "Rotate 180°"; this.rotate180ToolStripMenuItem.Click += new System.EventHandler(this.rotate180ToolStripMenuItem_Click); // // rotate270ToolStripMenuItem // this.rotate270ToolStripMenuItem.Name = "rotate270ToolStripMenuItem"; - this.rotate270ToolStripMenuItem.Size = new System.Drawing.Size(134, 22); + this.rotate270ToolStripMenuItem.Size = new System.Drawing.Size(138, 22); this.rotate270ToolStripMenuItem.Text = "Rotate 270°"; this.rotate270ToolStripMenuItem.Click += new System.EventHandler(this.rotate270ToolStripMenuItem_Click); // // toolStripMenuItem5 // this.toolStripMenuItem5.Name = "toolStripMenuItem5"; - this.toolStripMenuItem5.Size = new System.Drawing.Size(241, 6); + this.toolStripMenuItem5.Size = new System.Drawing.Size(229, 6); // // showRangeOfPagesToolStripMenuItem // this.showRangeOfPagesToolStripMenuItem.Name = "showRangeOfPagesToolStripMenuItem"; - this.showRangeOfPagesToolStripMenuItem.Size = new System.Drawing.Size(244, 22); + this.showRangeOfPagesToolStripMenuItem.Size = new System.Drawing.Size(232, 22); this.showRangeOfPagesToolStripMenuItem.Text = "Show range of pages"; this.showRangeOfPagesToolStripMenuItem.Click += new System.EventHandler(this.showRangeOfPagesToolStripMenuItem_Click); // // toolStripMenuItem6 // this.toolStripMenuItem6.Name = "toolStripMenuItem6"; - this.toolStripMenuItem6.Size = new System.Drawing.Size(241, 6); + this.toolStripMenuItem6.Size = new System.Drawing.Size(229, 6); // // informationToolStripMenuItem // this.informationToolStripMenuItem.Name = "informationToolStripMenuItem"; - this.informationToolStripMenuItem.Size = new System.Drawing.Size(244, 22); + this.informationToolStripMenuItem.Size = new System.Drawing.Size(232, 22); this.informationToolStripMenuItem.Text = "Information"; this.informationToolStripMenuItem.Click += new System.EventHandler(this.informationToolStripMenuItem_Click); // @@ -318,6 +320,8 @@ private void InitializeComponent() this._rotateLeft, this._rotateRight, this.toolStripSeparator6, + this._textMode, + this.toolStripSeparator4, this._showToolbar, this._showBookmarks, this._getTextFromPage}); @@ -330,7 +334,7 @@ private void InitializeComponent() // toolStripLabel1 // this.toolStripLabel1.Name = "toolStripLabel1"; - this.toolStripLabel1.Size = new System.Drawing.Size(36, 22); + this.toolStripLabel1.Size = new System.Drawing.Size(32, 22); this.toolStripLabel1.Text = "Page:"; // // _page @@ -372,7 +376,7 @@ private void InitializeComponent() // toolStripLabel2 // this.toolStripLabel2.Name = "toolStripLabel2"; - this.toolStripLabel2.Size = new System.Drawing.Size(42, 22); + this.toolStripLabel2.Size = new System.Drawing.Size(35, 22); this.toolStripLabel2.Text = "Zoom:"; // // _zoom @@ -417,7 +421,7 @@ private void InitializeComponent() this._fitWidth.Image = ((System.Drawing.Image)(resources.GetObject("_fitWidth.Image"))); this._fitWidth.ImageTransparentColor = System.Drawing.Color.Magenta; this._fitWidth.Name = "_fitWidth"; - this._fitWidth.Size = new System.Drawing.Size(59, 22); + this._fitWidth.Size = new System.Drawing.Size(55, 22); this._fitWidth.Text = "Fit Width"; this._fitWidth.Click += new System.EventHandler(this._fitWidth_Click); // @@ -427,7 +431,7 @@ private void InitializeComponent() this._fitHeight.Image = ((System.Drawing.Image)(resources.GetObject("_fitHeight.Image"))); this._fitHeight.ImageTransparentColor = System.Drawing.Color.Magenta; this._fitHeight.Name = "_fitHeight"; - this._fitHeight.Size = new System.Drawing.Size(63, 22); + this._fitHeight.Size = new System.Drawing.Size(60, 22); this._fitHeight.Text = "Fit Height"; this._fitHeight.Click += new System.EventHandler(this._fitHeight_Click); // @@ -437,7 +441,7 @@ private void InitializeComponent() this._fitBest.Image = ((System.Drawing.Image)(resources.GetObject("_fitBest.Image"))); this._fitBest.ImageTransparentColor = System.Drawing.Color.Magenta; this._fitBest.Name = "_fitBest"; - this._fitBest.Size = new System.Drawing.Size(49, 22); + this._fitBest.Size = new System.Drawing.Size(51, 22); this._fitBest.Text = "Fit Best"; this._fitBest.Click += new System.EventHandler(this._fitBest_Click); // @@ -452,7 +456,7 @@ private void InitializeComponent() this._rotateLeft.Image = ((System.Drawing.Image)(resources.GetObject("_rotateLeft.Image"))); this._rotateLeft.ImageTransparentColor = System.Drawing.Color.Magenta; this._rotateLeft.Name = "_rotateLeft"; - this._rotateLeft.Size = new System.Drawing.Size(68, 22); + this._rotateLeft.Size = new System.Drawing.Size(67, 22); this._rotateLeft.Text = "Rotate Left"; this._rotateLeft.Click += new System.EventHandler(this._rotateLeft_Click); // @@ -462,7 +466,7 @@ private void InitializeComponent() this._rotateRight.Image = ((System.Drawing.Image)(resources.GetObject("_rotateRight.Image"))); this._rotateRight.ImageTransparentColor = System.Drawing.Color.Magenta; this._rotateRight.Name = "_rotateRight"; - this._rotateRight.Size = new System.Drawing.Size(76, 22); + this._rotateRight.Size = new System.Drawing.Size(74, 22); this._rotateRight.Text = "Rotate Right"; this._rotateRight.Click += new System.EventHandler(this._rotateRight_Click); // @@ -478,7 +482,7 @@ private void InitializeComponent() this._showToolbar.Image = ((System.Drawing.Image)(resources.GetObject("_showToolbar.Image"))); this._showToolbar.ImageTransparentColor = System.Drawing.Color.Magenta; this._showToolbar.Name = "_showToolbar"; - this._showToolbar.Size = new System.Drawing.Size(83, 22); + this._showToolbar.Size = new System.Drawing.Size(78, 22); this._showToolbar.Text = "Show Toolbar"; this._showToolbar.Click += new System.EventHandler(this._hideToolbar_Click); // @@ -489,7 +493,7 @@ private void InitializeComponent() this._showBookmarks.Image = ((System.Drawing.Image)(resources.GetObject("_showBookmarks.Image"))); this._showBookmarks.ImageTransparentColor = System.Drawing.Color.Magenta; this._showBookmarks.Name = "_showBookmarks"; - this._showBookmarks.Size = new System.Drawing.Size(102, 22); + this._showBookmarks.Size = new System.Drawing.Size(97, 22); this._showBookmarks.Text = "Show Bookmarks"; this._showBookmarks.Click += new System.EventHandler(this._hideBookmarks_Click); // @@ -499,7 +503,7 @@ private void InitializeComponent() this._getTextFromPage.Image = ((System.Drawing.Image)(resources.GetObject("_getTextFromPage.Image"))); this._getTextFromPage.ImageTransparentColor = System.Drawing.Color.Magenta; this._getTextFromPage.Name = "_getTextFromPage"; - this._getTextFromPage.Size = new System.Drawing.Size(53, 22); + this._getTextFromPage.Size = new System.Drawing.Size(54, 22); this._getTextFromPage.Text = "Get Text"; this._getTextFromPage.ToolTipText = "Get Text From Current Page"; this._getTextFromPage.Click += new System.EventHandler(this._getTextFromPage_Click); @@ -511,7 +515,7 @@ private void InitializeComponent() this._pageToolStripLabel, this.toolStripStatusLabel2, this._coordinatesToolStripLabel}); - this.statusStrip1.Location = new System.Drawing.Point(0, 573); + this.statusStrip1.Location = new System.Drawing.Point(0, 527); this.statusStrip1.Name = "statusStrip1"; this.statusStrip1.Size = new System.Drawing.Size(1128, 22); this.statusStrip1.TabIndex = 3; @@ -520,25 +524,25 @@ private void InitializeComponent() // toolStripStatusLabel1 // this.toolStripStatusLabel1.Name = "toolStripStatusLabel1"; - this.toolStripStatusLabel1.Size = new System.Drawing.Size(36, 17); + this.toolStripStatusLabel1.Size = new System.Drawing.Size(32, 17); this.toolStripStatusLabel1.Text = "Page:"; // // _pageToolStripLabel // this._pageToolStripLabel.Name = "_pageToolStripLabel"; - this._pageToolStripLabel.Size = new System.Drawing.Size(41, 17); + this._pageToolStripLabel.Size = new System.Drawing.Size(37, 17); this._pageToolStripLabel.Text = "(page)"; // // toolStripStatusLabel2 // this.toolStripStatusLabel2.Name = "toolStripStatusLabel2"; - this.toolStripStatusLabel2.Size = new System.Drawing.Size(74, 17); + this.toolStripStatusLabel2.Size = new System.Drawing.Size(68, 17); this.toolStripStatusLabel2.Text = "Coordinates:"; // // _coordinatesToolStripLabel // this._coordinatesToolStripLabel.Name = "_coordinatesToolStripLabel"; - this._coordinatesToolStripLabel.Size = new System.Drawing.Size(77, 17); + this._coordinatesToolStripLabel.Size = new System.Drawing.Size(72, 17); this._coordinatesToolStripLabel.Text = "(coordinates)"; // // pdfViewerContextMenu @@ -547,20 +551,20 @@ private void InitializeComponent() this.copyToolStripMenuItem, this.selectAllToolStripMenuItem}); this.pdfViewerContextMenu.Name = "pdfViewerContextMenu"; - this.pdfViewerContextMenu.Size = new System.Drawing.Size(123, 48); + this.pdfViewerContextMenu.Size = new System.Drawing.Size(121, 48); this.pdfViewerContextMenu.Opening += new System.ComponentModel.CancelEventHandler(this.pdfViewerContextMenu_Opening); // // copyToolStripMenuItem // this.copyToolStripMenuItem.Name = "copyToolStripMenuItem"; - this.copyToolStripMenuItem.Size = new System.Drawing.Size(122, 22); + this.copyToolStripMenuItem.Size = new System.Drawing.Size(120, 22); this.copyToolStripMenuItem.Text = "&Copy"; this.copyToolStripMenuItem.Click += new System.EventHandler(this.copyToolStripMenuItem_Click); // // selectAllToolStripMenuItem // this.selectAllToolStripMenuItem.Name = "selectAllToolStripMenuItem"; - this.selectAllToolStripMenuItem.Size = new System.Drawing.Size(122, 22); + this.selectAllToolStripMenuItem.Size = new System.Drawing.Size(120, 22); this.selectAllToolStripMenuItem.Text = "Select &All"; this.selectAllToolStripMenuItem.Click += new System.EventHandler(this.selectAllToolStripMenuItem_Click); // @@ -569,14 +573,30 @@ private void InitializeComponent() this.pdfViewer1.Dock = System.Windows.Forms.DockStyle.Fill; this.pdfViewer1.Location = new System.Drawing.Point(0, 49); this.pdfViewer1.Name = "pdfViewer1"; - this.pdfViewer1.Size = new System.Drawing.Size(1128, 524); + this.pdfViewer1.Size = new System.Drawing.Size(1128, 478); this.pdfViewer1.TabIndex = 0; // + // toolStripSeparator4 + // + this.toolStripSeparator4.Name = "toolStripSeparator4"; + this.toolStripSeparator4.Size = new System.Drawing.Size(6, 25); + // + // _textMode + // + this._textMode.CheckOnClick = true; + this._textMode.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text; + this._textMode.Image = ((System.Drawing.Image)(resources.GetObject("_textMode.Image"))); + this._textMode.ImageTransparentColor = System.Drawing.Color.Magenta; + this._textMode.Name = "_textMode"; + this._textMode.Size = new System.Drawing.Size(67, 22); + this._textMode.Text = "Text Mode"; + this._textMode.Click += new System.EventHandler(this._textMode_Click); + // // MainForm // - this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.ClientSize = new System.Drawing.Size(1128, 595); + this.ClientSize = new System.Drawing.Size(1128, 549); this.Controls.Add(this.pdfViewer1); this.Controls.Add(this.statusStrip1); this.Controls.Add(this.toolStrip1); @@ -657,6 +677,8 @@ private void InitializeComponent() private System.Windows.Forms.ContextMenuStrip pdfViewerContextMenu; private System.Windows.Forms.ToolStripMenuItem copyToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem selectAllToolStripMenuItem; + private System.Windows.Forms.ToolStripButton _textMode; + private System.Windows.Forms.ToolStripSeparator toolStripSeparator4; } } diff --git a/PdfiumViewer.Demo/MainForm.cs b/PdfiumViewer.Demo/MainForm.cs index 87dd7b70..93eaecc9 100644 --- a/PdfiumViewer.Demo/MainForm.cs +++ b/PdfiumViewer.Demo/MainForm.cs @@ -395,5 +395,10 @@ private void pdfViewerContextMenu_Opening(object sender, CancelEventArgs e) { copyToolStripMenuItem.Enabled = pdfViewer1.Renderer.IsTextSelected; } + + private void _textMode_Click(object sender, EventArgs e) + { + pdfViewer1.Renderer.CursorMode = (pdfViewer1.Renderer.CursorMode == PdfCursorMode.Pan) ? PdfCursorMode.TextSelection : PdfCursorMode.Pan; + } } } diff --git a/PdfiumViewer.Demo/MainForm.resx b/PdfiumViewer.Demo/MainForm.resx index c32d9b38..35df8487 100644 --- a/PdfiumViewer.Demo/MainForm.resx +++ b/PdfiumViewer.Demo/MainForm.resx @@ -257,6 +257,21 @@ mDEo5mNjuweFGvjWg2EBhCbpkW78htSHHwRyNdmgAFzPEee2iFkzayy2OLXzT4gr6UdUnlXrullsxxQ+ kx0g8BTA3aZlButjSTyjODq/WcQcW/B/Je4OQhLvKQDnzN1mp0nnkvAhR8VuMzNrpm1mpjgkoVwB/v8D TgDQASA1MVpwzwAAAABJRU5ErkJggg== + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAIDSURBVDhPpZLrS5NhGMb3j4SWh0oRQVExD4gonkDpg4hG + YKxG6WBogkMZKgPNCEVJFBGdGETEvgwyO9DJE5syZw3PIlPEE9pgBCLZ5XvdMB8Ew8gXbl54nuf63dd9 + 0OGSnwCahxbPRNPAPMw9Xpg6ZmF46kZZ0xSKzJPIrhpDWsVnpBhGkKx3nAX8Pv7z1zg8OoY/cITdn4fw + bf/C0kYAN3Ma/w3gWfZL5kzTKBxjWyK2DftwI9tyMYCZKXbNHaD91bLYJrDXsYbrWfUKwJrPE9M2M1Oc + VzOOpHI7Jr376Hi9ogHqFIANO0/MmmmbmSmm9a8ze+I4MrNWAdjtoJgWcx+PSzg166yZZ8xM8XvXDix9 + c4jIqFYAjoriBV9AhEPv1mH/sonogha0afbZMMZz+yreTGyhpusHwtNNCsA5U1zS4BLxzJIfg299qO32 + Ir7UJtZfftyATqeT+8o2D8JSjQrAJblrncYL7ZJ2+bfaFnC/1S1NjL3diRat7qrO7wLRP3HjWsojBeCo + mDEo5mNjuweFGvjWg2EBhCbpkW78htSHHwRyNdmgAFzPEee2iFkzayy2OLXzT4gr6UdUnlXrullsxxQ+ + kx0g8BTA3aZlButjSTyjODq/WcQcW/B/Je4OQhLvKQDnzN1mp0nnkvAhR8VuMzNrpm1mpjgkoVwB/v8D + TgDQASA1MVpwzwAAAABJRU5ErkJggg== diff --git a/PdfiumViewer.Demo/PdfRangeDocument.cs b/PdfiumViewer.Demo/PdfRangeDocument.cs index 3dee0e6f..1d0c43a0 100644 --- a/PdfiumViewer.Demo/PdfRangeDocument.cs +++ b/PdfiumViewer.Demo/PdfRangeDocument.cs @@ -303,11 +303,6 @@ public int CountCharacters(int page) return _document.CountCharacters(page); } - public List GetTextRectangles(int page, int startIndex, int count) - { - return _document.GetTextRectangles(page, startIndex, count); - } - private int TranslatePage(int page) { if (page < 0 || page >= PageCount) diff --git a/PdfiumViewer/IPdfDocument.cs b/PdfiumViewer/IPdfDocument.cs index 92a137c9..286b0cdd 100644 --- a/PdfiumViewer/IPdfDocument.cs +++ b/PdfiumViewer/IPdfDocument.cs @@ -278,12 +278,5 @@ public interface IPdfDocument : IDisposable /// The page to get the character count from /// Number of characters in the page. Generated characters, like additional space characters, new line characters, are also counted. int CountCharacters(int page); - - /// - /// Gets the rectangular areas occupied by a segment of text - /// - /// The page to get the rectangles from - /// The rectangular areas occupied by a segment of text - List GetTextRectangles(int page, int startIndex, int count); } } diff --git a/PdfiumViewer/PdfDocument.cs b/PdfiumViewer/PdfDocument.cs index 2a6412d0..cd9c9f95 100644 --- a/PdfiumViewer/PdfDocument.cs +++ b/PdfiumViewer/PdfDocument.cs @@ -541,16 +541,6 @@ public int CountCharacters(int page) return _file.CountChars(page); } - /// - /// Gets the rectangular areas occupied by a segment of text - /// - /// The page to get the rectangles from - /// The rectangular areas occupied by a segment of text - public List GetTextRectangles(int page, int startIndex, int count) - { - return _file.GetTextRectangles(page, startIndex, count); - } - /// /// Creates a for the PDF document. /// diff --git a/PdfiumViewer/PdfFile.cs b/PdfiumViewer/PdfFile.cs index 79304892..c62da676 100644 --- a/PdfiumViewer/PdfFile.cs +++ b/PdfiumViewer/PdfFile.cs @@ -593,14 +593,6 @@ public int CountChars(int page) } } - public List GetTextRectangles(int page, int startIndex, int count) - { - var pageData = GetPageData(_document, _form, page); - { - return NativeMethods.FPDFText_GetRectangles(pageData.TextPage, page, startIndex, count); - } - } - public void DeletePage(int pageNumber) { NativeMethods.FPDFPage_Delete(_document, pageNumber); diff --git a/PdfiumViewer/PdfRenderer.cs b/PdfiumViewer/PdfRenderer.cs index 8f2ddcc5..312960da 100644 --- a/PdfiumViewer/PdfRenderer.cs +++ b/PdfiumViewer/PdfRenderer.cs @@ -13,6 +13,7 @@ namespace PdfiumViewer /// public class PdfRenderer : PanningZoomingScrollControl { + private static readonly double _textTolerance = 8.0; private static readonly Padding PageMargin = new Padding(4); private static readonly SolidBrush _textSelectionBrush = new SolidBrush(Color.FromArgb(90, Color.DodgerBlue)); @@ -33,7 +34,7 @@ public class PdfRenderer : PanningZoomingScrollControl private DragState _dragState; private PdfRotation _rotation; private List[] _markers; - private PdfViewerCursorMode _cursorMode = PdfViewerCursorMode.Pan; + private PdfCursorMode _cursorMode = PdfCursorMode.Pan; private bool _isSelectingText = false; private MouseState _cachedMouseState = null; private TextSelectionState _textSelectionState = null; @@ -140,14 +141,14 @@ public PdfViewerZoomMode ZoomMode /// /// Gets or sets the way the viewer should respond to cursor input /// - [DefaultValue(PdfViewerCursorMode.Pan)] - public PdfViewerCursorMode CursorMode + [DefaultValue(PdfCursorMode.Pan)] + public PdfCursorMode CursorMode { get { return _cursorMode; } set { _cursorMode = value; - MousePanningEnabled = _cursorMode == PdfViewerCursorMode.Pan; + MousePanningEnabled = _cursorMode == PdfCursorMode.Pan; } } @@ -837,7 +838,9 @@ private void DrawTextSelection(Graphics graphics, int page, TextSelectionState s end = Document.CountCharacters(page); Region region = null; - foreach (var rectangle in Document.GetTextRectangles(page, start, end - start)) + PdfTextSpan textSpan = new PdfTextSpan(page, start, end - start); + + foreach (var rectangle in Document.GetTextBounds(textSpan)) { if (region == null) region = new Region(BoundsFromPdf(rectangle)); @@ -927,7 +930,7 @@ protected override void OnSetCursor(SetCursorEventArgs e) } } - if (_cursorMode == PdfViewerCursorMode.TextSelection) + if (_cursorMode == PdfCursorMode.TextSelection) { var state = GetMouseState(e.Location); if (state.CharacterIndex >= 0) @@ -949,7 +952,7 @@ protected override void OnMouseDown(MouseEventArgs e) HandleMouseDownForLinks(e); - if (_cursorMode == PdfViewerCursorMode.TextSelection) + if (_cursorMode == PdfCursorMode.TextSelection) { HandleMouseDownForTextSelection(e); } @@ -963,7 +966,7 @@ protected override void OnMouseUp(MouseEventArgs e) HandleMouseUpForLinks(e); - if (_cursorMode == PdfViewerCursorMode.TextSelection) + if (_cursorMode == PdfCursorMode.TextSelection) { HandleMouseUpForTextSelection(e); } @@ -973,7 +976,7 @@ protected override void OnMouseMove(MouseEventArgs e) { base.OnMouseMove(e); - if (_cursorMode == PdfViewerCursorMode.TextSelection) + if (_cursorMode == PdfCursorMode.TextSelection) { HandleMouseMoveForTextSelection(e); } @@ -983,7 +986,7 @@ protected override void OnMouseDoubleClick(MouseEventArgs e) { base.OnMouseDoubleClick(e); - if (_cursorMode == PdfViewerCursorMode.TextSelection) + if (_cursorMode == PdfCursorMode.TextSelection) { HandleMouseDoubleClickForTextSelection(e); } @@ -1057,7 +1060,7 @@ private void HandleMouseDownForTextSelection(MouseEventArgs e) if (!pdfLocation.IsValid) return; - var characterIndex = Document.GetCharacterIndexAtPosition(pdfLocation, 4f, 4f); + var characterIndex = Document.GetCharacterIndexAtPosition(pdfLocation, _textTolerance, _textTolerance); if (characterIndex >= 0) { @@ -1103,6 +1106,37 @@ private void HandleMouseMoveForTextSelection(MouseEventArgs e) Invalidate(); } + + ScrollWithMouseDrag(e); + } + + private void ScrollWithMouseDrag(MouseEventArgs e) + { + var clientArea = GetScrollClientArea(); + Point scroll = new Point(0, 0); + + if (e.X < 0) + { + scroll.X = 0 - e.X; + } + else if (e.X > clientArea.Width) + { + scroll.X = clientArea.Width - e.X; + } + + if (e.Y < 0) + { + scroll.Y = 0 - e.Y; + } + else if (e.Y > clientArea.Height) + { + scroll.Y = clientArea.Height - e.Y; + } + + SetDisplayRectLocation(new Point( + DisplayRectangle.X + scroll.X, + DisplayRectangle.Y + scroll.Y + )); } private void HandleMouseDoubleClickForTextSelection(MouseEventArgs e) @@ -1143,7 +1177,8 @@ private MouseState GetMouseState(Point mouseLocation) if (!_cachedMouseState.PdfLocation.IsValid) return _cachedMouseState; - _cachedMouseState.CharacterIndex = Document.GetCharacterIndexAtPosition(_cachedMouseState.PdfLocation, 4f, 4f); + // Loosen the judgment of the Y coordinate while the mouse is moving. + _cachedMouseState.CharacterIndex = Document.GetCharacterIndexAtPosition(_cachedMouseState.PdfLocation, _textTolerance, _textTolerance*2); return _cachedMouseState; } diff --git a/PdfiumViewer/PdfViewerCursorMode.cs b/PdfiumViewer/PdfViewerCursorMode.cs index d33a5d45..b873920c 100644 --- a/PdfiumViewer/PdfViewerCursorMode.cs +++ b/PdfiumViewer/PdfViewerCursorMode.cs @@ -4,7 +4,7 @@ namespace PdfiumViewer { - public enum PdfViewerCursorMode + public enum PdfCursorMode { Pan, TextSelection From d9b2b1bf86fd3fdf95fb5b5b3998c8dcd59b2495 Mon Sep 17 00:00:00 2001 From: wiera987 Date: Mon, 24 Jun 2019 00:31:39 +0900 Subject: [PATCH 08/39] Fixed an issue where panning and text selection were confused and the page moved suddenly when right-clicking. --- PdfiumViewer/PanningZoomingScrollControl.cs | 8 ++++---- PdfiumViewer/PdfRenderer.cs | 7 ++++--- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/PdfiumViewer/PanningZoomingScrollControl.cs b/PdfiumViewer/PanningZoomingScrollControl.cs index a2e043cd..a62b2e28 100644 --- a/PdfiumViewer/PanningZoomingScrollControl.cs +++ b/PdfiumViewer/PanningZoomingScrollControl.cs @@ -28,6 +28,7 @@ static PanningZoomingScrollControl() } private double _zoom = 1; + private bool _capture = false; private bool _canPan; private Point _dragStart; private Point _startOffset; @@ -246,7 +247,7 @@ protected override void OnMouseDown(MouseEventArgs e) if (!MousePanningEnabled || e.Button != MouseButtons.Left || !_canPan) return; - Capture = true; + _capture = true; _dragStart = e.Location; _startOffset = DisplayRectangle.Location; } @@ -255,7 +256,7 @@ protected override void OnMouseMove(MouseEventArgs e) { base.OnMouseMove(e); - if (!MousePanningEnabled || !Capture) + if (!_capture) return; var offset = new Point(e.Location.X - _dragStart.X, e.Location.Y - _dragStart.Y); @@ -267,8 +268,7 @@ protected override void OnMouseUp(MouseEventArgs e) { base.OnMouseUp(e); - if (MousePanningEnabled) - Capture = false; + _capture = false; } private class WheelFilter : IMessageFilter diff --git a/PdfiumViewer/PdfRenderer.cs b/PdfiumViewer/PdfRenderer.cs index 312960da..66ca067c 100644 --- a/PdfiumViewer/PdfRenderer.cs +++ b/PdfiumViewer/PdfRenderer.cs @@ -35,6 +35,7 @@ public class PdfRenderer : PanningZoomingScrollControl private PdfRotation _rotation; private List[] _markers; private PdfCursorMode _cursorMode = PdfCursorMode.Pan; + private bool _captureText = false; private bool _isSelectingText = false; private MouseState _cachedMouseState = null; private TextSelectionState _textSelectionState = null; @@ -1072,12 +1073,12 @@ private void HandleMouseDownForTextSelection(MouseEventArgs e) EndIndex = -1 }; _isSelectingText = true; - Capture = true; + _captureText = true; } else { _isSelectingText = false; - Capture = false; + _captureText = false; _textSelectionState = null; } } @@ -1088,7 +1089,7 @@ private void HandleMouseUpForTextSelection(MouseEventArgs e) return; _isSelectingText = false; - Capture = false; + _captureText = false; Invalidate(); } From a66323bd8e2e2d22f004c9063f2bef79dcb3783d Mon Sep 17 00:00:00 2001 From: wiera987 Date: Mon, 24 Jun 2019 22:33:20 +0900 Subject: [PATCH 09/39] Fixed an issue with text selection.It is copied more than the selected number of characters. --- PdfiumViewer/PdfFile.cs | 9 ++------- PdfiumViewer/PdfRenderer.cs | 11 ++++------- 2 files changed, 6 insertions(+), 14 deletions(-) diff --git a/PdfiumViewer/PdfFile.cs b/PdfiumViewer/PdfFile.cs index c62da676..ed800ae4 100644 --- a/PdfiumViewer/PdfFile.cs +++ b/PdfiumViewer/PdfFile.cs @@ -509,14 +509,9 @@ public string GetPdfText(PdfTextSpan textSpan) private string GetPdfText(PageData pageData, PdfTextSpan textSpan) { - // NOTE: The count parameter in FPDFText_GetText seems to include the null terminator, even though the documentation does not specify this. - // So to read 40 characters, we need to allocate 82 bytes (2 for the terminator), and request 41 characters from GetText. - // The return value also includes the terminator (which is documented) var result = new byte[(textSpan.Length + 1) * 2]; - int count = NativeMethods.FPDFText_GetText(pageData.TextPage, textSpan.Offset, textSpan.Length + 1, result); - if (count <= 0) - return string.Empty; - return FPDFEncoding.GetString(result, 0, (count - 1) * 2); + NativeMethods.FPDFText_GetText(pageData.TextPage, textSpan.Offset, textSpan.Length, result); + return FPDFEncoding.GetString(result, 0, textSpan.Length * 2); } public int GetCharIndexAtPos(PdfPoint location, double xTolerance, double yTolerance) diff --git a/PdfiumViewer/PdfRenderer.cs b/PdfiumViewer/PdfRenderer.cs index 66ca067c..3f5c99db 100644 --- a/PdfiumViewer/PdfRenderer.cs +++ b/PdfiumViewer/PdfRenderer.cs @@ -13,7 +13,8 @@ namespace PdfiumViewer /// public class PdfRenderer : PanningZoomingScrollControl { - private static readonly double _textTolerance = 8.0; + private static readonly double _textToleranceX = 0.0; + private static readonly double _textToleranceY = 8.0; private static readonly Padding PageMargin = new Padding(4); private static readonly SolidBrush _textSelectionBrush = new SolidBrush(Color.FromArgb(90, Color.DodgerBlue)); @@ -35,7 +36,6 @@ public class PdfRenderer : PanningZoomingScrollControl private PdfRotation _rotation; private List[] _markers; private PdfCursorMode _cursorMode = PdfCursorMode.Pan; - private bool _captureText = false; private bool _isSelectingText = false; private MouseState _cachedMouseState = null; private TextSelectionState _textSelectionState = null; @@ -1061,7 +1061,7 @@ private void HandleMouseDownForTextSelection(MouseEventArgs e) if (!pdfLocation.IsValid) return; - var characterIndex = Document.GetCharacterIndexAtPosition(pdfLocation, _textTolerance, _textTolerance); + var characterIndex = Document.GetCharacterIndexAtPosition(pdfLocation, _textToleranceX, _textToleranceY); if (characterIndex >= 0) { @@ -1073,12 +1073,10 @@ private void HandleMouseDownForTextSelection(MouseEventArgs e) EndIndex = -1 }; _isSelectingText = true; - _captureText = true; } else { _isSelectingText = false; - _captureText = false; _textSelectionState = null; } } @@ -1089,7 +1087,6 @@ private void HandleMouseUpForTextSelection(MouseEventArgs e) return; _isSelectingText = false; - _captureText = false; Invalidate(); } @@ -1179,7 +1176,7 @@ private MouseState GetMouseState(Point mouseLocation) return _cachedMouseState; // Loosen the judgment of the Y coordinate while the mouse is moving. - _cachedMouseState.CharacterIndex = Document.GetCharacterIndexAtPosition(_cachedMouseState.PdfLocation, _textTolerance, _textTolerance*2); + _cachedMouseState.CharacterIndex = Document.GetCharacterIndexAtPosition(_cachedMouseState.PdfLocation, _textToleranceX, _textToleranceY); return _cachedMouseState; } From 96889c8e6cdaaec822ad59ea278ea0ed16b21651 Mon Sep 17 00:00:00 2001 From: wiera987 Date: Mon, 21 Oct 2019 23:33:37 +0900 Subject: [PATCH 10/39] Added PdfMarker tag for multiple purposes. --- PdfiumViewer/IPdfMarker.cs | 5 +++++ PdfiumViewer/PdfMarker.cs | 7 +++++-- PdfiumViewer/PdfMarkerCollection.cs | 15 +++++++++++++++ PdfiumViewer/PdfSearchManager.cs | 7 ++++--- 4 files changed, 29 insertions(+), 5 deletions(-) diff --git a/PdfiumViewer/IPdfMarker.cs b/PdfiumViewer/IPdfMarker.cs index c8c2dd5b..f22b2209 100644 --- a/PdfiumViewer/IPdfMarker.cs +++ b/PdfiumViewer/IPdfMarker.cs @@ -15,6 +15,11 @@ public interface IPdfMarker /// int Page { get; } + /// + /// The marker Tag by purpose. + /// + int Tag { get; } + /// /// Draw the marker. /// diff --git a/PdfiumViewer/PdfMarker.cs b/PdfiumViewer/PdfMarker.cs index e483e56d..27d89853 100644 --- a/PdfiumViewer/PdfMarker.cs +++ b/PdfiumViewer/PdfMarker.cs @@ -15,18 +15,21 @@ public class PdfMarker : IPdfMarker public Color BorderColor { get; } public float BorderWidth { get; } + public int Tag { get; } + public PdfMarker(int page, RectangleF bounds, Color color) - : this(page, bounds, color, Color.Transparent, 0) + : this(page, bounds, color, Color.Transparent, 0, 0) { } - public PdfMarker(int page, RectangleF bounds, Color color, Color borderColor, float borderWidth) + public PdfMarker(int page, RectangleF bounds, Color color, Color borderColor, float borderWidth, int tag) { Page = page; Bounds = bounds; Color = color; BorderColor = borderColor; BorderWidth = borderWidth; + Tag = tag; } public void Draw(PdfRenderer renderer, Graphics graphics) diff --git a/PdfiumViewer/PdfMarkerCollection.cs b/PdfiumViewer/PdfMarkerCollection.cs index 59460dc4..3108adc3 100644 --- a/PdfiumViewer/PdfMarkerCollection.cs +++ b/PdfiumViewer/PdfMarkerCollection.cs @@ -11,6 +11,21 @@ public class PdfMarkerCollection : Collection { public event EventHandler CollectionChanged; + /// + /// Clear specified tag. + /// + /// + public void Clear(int tag) + { + for (int i=Count-1; i>=0; i--) + { + if (Items[i].Tag == tag) + { + RemoveAt(i); + } + } + } + protected override void ClearItems() { base.ClearItems(); diff --git a/PdfiumViewer/PdfSearchManager.cs b/PdfiumViewer/PdfSearchManager.cs index ba0333c8..6fa3ef29 100644 --- a/PdfiumViewer/PdfSearchManager.cs +++ b/PdfiumViewer/PdfSearchManager.cs @@ -100,7 +100,7 @@ public PdfSearchManager(PdfRenderer renderer) /// Whether any matches were found. public bool Search(string text) { - Renderer.Markers.Clear(); + Renderer.Markers.Clear(0); if (String.IsNullOrEmpty(text)) { @@ -206,7 +206,7 @@ public void Reset() private void UpdateHighlights() { - Renderer.Markers.Clear(); + Renderer.Markers.Clear(0); if (_matches == null) return; @@ -240,7 +240,8 @@ private void AddMatch(int index, bool current) bounds, current ? CurrentMatchColor : MatchColor, current ? CurrentMatchBorderColor : MatchBorderColor, - current ? CurrentMatchBorderWidth : MatchBorderWidth + current ? CurrentMatchBorderWidth : MatchBorderWidth, + 0 ); Renderer.Markers.Add(marker); From 5909adb65ac01808d0b477906f8247f976089b02 Mon Sep 17 00:00:00 2001 From: wiera987 <50268838+wiera987@users.noreply.github.com> Date: Sun, 19 Feb 2023 02:20:00 +0900 Subject: [PATCH 11/39] =?UTF-8?q?Rectangle=E3=80=80drawing=E3=80=80support?= =?UTF-8?q?=20for=20PDFComp=20boundary=20comparison.=20Build=20tool=20chan?= =?UTF-8?q?ged.=20Visual=20studio=202022=20/=20.NET=20Framework=204.8.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- PdfiumViewer.Test/PdfiumViewer.Test.csproj | 5 +- PdfiumViewer.Test/packages.config | 6 +- PdfiumViewer.WPFDemo/App.config | 12 +- .../PdfiumViewer.WPFDemo.csproj | 3 +- .../Properties/Resources.Designer.cs | 134 ++++++++---------- .../Properties/Settings.Designer.cs | 56 ++++---- PdfiumViewer/PdfRenderer.cs | 47 ++++++ PdfiumViewer/PdfViewerCursorMode.cs | 3 +- 8 files changed, 153 insertions(+), 113 deletions(-) diff --git a/PdfiumViewer.Test/PdfiumViewer.Test.csproj b/PdfiumViewer.Test/PdfiumViewer.Test.csproj index c10d65d8..1737ce6e 100644 --- a/PdfiumViewer.Test/PdfiumViewer.Test.csproj +++ b/PdfiumViewer.Test/PdfiumViewer.Test.csproj @@ -9,8 +9,9 @@ Properties PdfiumViewer.Test PdfiumViewer.Test - v4.0 + v4.8 512 + true @@ -20,6 +21,7 @@ DEBUG;TRACE prompt 4 + false pdbonly @@ -28,6 +30,7 @@ TRACE prompt 4 + false diff --git a/PdfiumViewer.Test/packages.config b/PdfiumViewer.Test/packages.config index 512ce05d..24af581c 100644 --- a/PdfiumViewer.Test/packages.config +++ b/PdfiumViewer.Test/packages.config @@ -1,4 +1,4 @@ - - - + + + \ No newline at end of file diff --git a/PdfiumViewer.WPFDemo/App.config b/PdfiumViewer.WPFDemo/App.config index 8e156463..5ffd8f8e 100644 --- a/PdfiumViewer.WPFDemo/App.config +++ b/PdfiumViewer.WPFDemo/App.config @@ -1,6 +1,6 @@ - - - - - - \ No newline at end of file + + + + + + diff --git a/PdfiumViewer.WPFDemo/PdfiumViewer.WPFDemo.csproj b/PdfiumViewer.WPFDemo/PdfiumViewer.WPFDemo.csproj index 614d2b7d..91b93d48 100644 --- a/PdfiumViewer.WPFDemo/PdfiumViewer.WPFDemo.csproj +++ b/PdfiumViewer.WPFDemo/PdfiumViewer.WPFDemo.csproj @@ -9,10 +9,11 @@ Properties PdfiumViewer.WPFDemo PdfiumViewer.WPFDemo - v4.5 + v4.8 512 {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} 4 + AnyCPU diff --git a/PdfiumViewer.WPFDemo/Properties/Resources.Designer.cs b/PdfiumViewer.WPFDemo/Properties/Resources.Designer.cs index 0c40e3a1..d7904b37 100644 --- a/PdfiumViewer.WPFDemo/Properties/Resources.Designer.cs +++ b/PdfiumViewer.WPFDemo/Properties/Resources.Designer.cs @@ -1,71 +1,63 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// Runtime Version:4.0.30319.36323 -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -namespace PdfiumViewer.WPFDemo.Properties -{ - - - /// - /// A strongly-typed resource class, for looking up localized strings, etc. - /// - // This class was auto-generated by the StronglyTypedResourceBuilder - // class via a tool like ResGen or Visual Studio. - // To add or remove a member, edit your .ResX file then rerun ResGen - // with the /str option, or rebuild your VS project. - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - internal class Resources - { - - private static global::System.Resources.ResourceManager resourceMan; - - private static global::System.Globalization.CultureInfo resourceCulture; - - [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - internal Resources() - { - } - - /// - /// Returns the cached ResourceManager instance used by this class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Resources.ResourceManager ResourceManager - { - get - { - if ((resourceMan == null)) - { - global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("PdfiumViewer.WPFDemo.Properties.Resources", typeof(Resources).Assembly); - resourceMan = temp; - } - return resourceMan; - } - } - - /// - /// Overrides the current thread's CurrentUICulture property for all - /// resource lookups using this strongly typed resource class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Globalization.CultureInfo Culture - { - get - { - return resourceCulture; - } - set - { - resourceCulture = value; - } - } - } -} +//------------------------------------------------------------------------------ +// +// このコードはツールによって生成されました。 +// ランタイム バージョン:4.0.30319.42000 +// +// このファイルへの変更は、以下の状況下で不正な動作の原因になったり、 +// コードが再生成されるときに損失したりします。 +// +//------------------------------------------------------------------------------ + +namespace PdfiumViewer.WPFDemo.Properties { + using System; + + + /// + /// ローカライズされた文字列などを検索するための、厳密に型指定されたリソース クラスです。 + /// + // このクラスは StronglyTypedResourceBuilder クラスが ResGen + // または Visual Studio のようなツールを使用して自動生成されました。 + // メンバーを追加または削除するには、.ResX ファイルを編集して、/str オプションと共に + // ResGen を実行し直すか、または VS プロジェクトをビルドし直します。 + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// このクラスで使用されているキャッシュされた ResourceManager インスタンスを返します。 + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("PdfiumViewer.WPFDemo.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// すべてについて、現在のスレッドの CurrentUICulture プロパティをオーバーライドします + /// 現在のスレッドの CurrentUICulture プロパティをオーバーライドします。 + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + } +} diff --git a/PdfiumViewer.WPFDemo/Properties/Settings.Designer.cs b/PdfiumViewer.WPFDemo/Properties/Settings.Designer.cs index 638c15f4..badfdf10 100644 --- a/PdfiumViewer.WPFDemo/Properties/Settings.Designer.cs +++ b/PdfiumViewer.WPFDemo/Properties/Settings.Designer.cs @@ -1,30 +1,26 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// Runtime Version:4.0.30319.36323 -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -namespace PdfiumViewer.WPFDemo.Properties -{ - - - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")] - internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase - { - - private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); - - public static Settings Default - { - get - { - return defaultInstance; - } - } - } -} +//------------------------------------------------------------------------------ +// +// このコードはツールによって生成されました。 +// ランタイム バージョン:4.0.30319.42000 +// +// このファイルへの変更は、以下の状況下で不正な動作の原因になったり、 +// コードが再生成されるときに損失したりします。 +// +//------------------------------------------------------------------------------ + +namespace PdfiumViewer.WPFDemo.Properties { + + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.4.0.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { + + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); + + public static Settings Default { + get { + return defaultInstance; + } + } + } +} diff --git a/PdfiumViewer/PdfRenderer.cs b/PdfiumViewer/PdfRenderer.cs index 3f5c99db..6c3a610d 100644 --- a/PdfiumViewer/PdfRenderer.cs +++ b/PdfiumViewer/PdfRenderer.cs @@ -39,6 +39,7 @@ public class PdfRenderer : PanningZoomingScrollControl private bool _isSelectingText = false; private MouseState _cachedMouseState = null; private TextSelectionState _textSelectionState = null; + private RectangleF _compareBounds = Rectangle.Empty; /// /// The associated PDF document. @@ -153,6 +154,31 @@ public PdfCursorMode CursorMode } } + /// + /// Gets or sets the Boundary for comparison + /// + public RectangleF CompareBounds + { + get { return _compareBounds; } + set + { + if (value.Width < 0) + { + value.X += value.Width; + value.Width = -value.Width; + } + if (value.Height < 0) + { + value.Y += value.Height; + value.Height = -value.Height; + } + + Debug.Assert(value.Width >= 0 && value.Height >= 0); + _compareBounds = value; + Invalidate(); + } + } + /// /// Gets or sets the current rotation of the PDF document. /// @@ -809,6 +835,8 @@ protected override void OnPaint(PaintEventArgs e) DrawMarkers(e.Graphics, page); + DrawCompareBounds(e.Graphics, page); + var selectionInfo = _textSelectionState; if (selectionInfo != null) DrawTextSelection(e.Graphics, page, selectionInfo.GetNormalized()); @@ -821,6 +849,19 @@ protected override void OnPaint(PaintEventArgs e) _visiblePageEnd = Document.PageCount - 1; } + private void DrawCompareBounds(Graphics graphics, int page) + { + var bounds = BoundsFromPdf(new PdfRectangle(page, _compareBounds)); + + if (!bounds.IsEmpty) + { + using (var pen = new Pen(Color.Crimson, 2)) + { + graphics.DrawRectangle(pen, bounds); + } + } + } + private void DrawTextSelection(Graphics graphics, int page, TextSelectionState state) { if (state.EndPage < 0 || state.EndIndex < 0) @@ -940,6 +981,12 @@ protected override void OnSetCursor(SetCursorEventArgs e) return; } } + + if (_cursorMode == PdfCursorMode.Bounds) + { + e.Cursor = Cursors.Cross; + return; + } } base.OnSetCursor(e); diff --git a/PdfiumViewer/PdfViewerCursorMode.cs b/PdfiumViewer/PdfViewerCursorMode.cs index b873920c..2d3f7354 100644 --- a/PdfiumViewer/PdfViewerCursorMode.cs +++ b/PdfiumViewer/PdfViewerCursorMode.cs @@ -7,6 +7,7 @@ namespace PdfiumViewer public enum PdfCursorMode { Pan, - TextSelection + TextSelection, + Bounds } } From c9a885ae35e7fc54d61088fe5d1eed08e8699d2d Mon Sep 17 00:00:00 2001 From: wiera987 <50268838+wiera987@users.noreply.github.com> Date: Wed, 22 Feb 2023 23:53:23 +0900 Subject: [PATCH 12/39] Fixed the display position shifting up when loading. --- PdfiumViewer/PdfRenderer.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/PdfiumViewer/PdfRenderer.cs b/PdfiumViewer/PdfRenderer.cs index 6c3a610d..452d9a94 100644 --- a/PdfiumViewer/PdfRenderer.cs +++ b/PdfiumViewer/PdfRenderer.cs @@ -1306,7 +1306,11 @@ protected override void SetZoom(double zoom, Point? focus) } else { - location = new Point(0, 0); + // Zoom the center of the page. + var pageCache = _pageCache[Page]; + int x = pageCache.OuterBounds.X + pageCache.OuterBounds.Width / 2; + int y = pageCache.OuterBounds.Y + pageCache.OuterBounds.Height / 2; + location = new Point(x,y); } pdfLocation = PointToPdfRounded(location); From 95c7bfecdac5b91696a8ce7eb718eb77e539c04d Mon Sep 17 00:00:00 2001 From: wiera987 <50268838+wiera987@users.noreply.github.com> Date: Sat, 10 Aug 2024 23:21:19 +0900 Subject: [PATCH 13/39] In bounds mode, the page with the bounds displayed has priority as the comparison page. --- PdfiumViewer/PdfRenderer.cs | 62 +++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/PdfiumViewer/PdfRenderer.cs b/PdfiumViewer/PdfRenderer.cs index 452d9a94..bfafc711 100644 --- a/PdfiumViewer/PdfRenderer.cs +++ b/PdfiumViewer/PdfRenderer.cs @@ -3,6 +3,8 @@ using System.ComponentModel; using System.Diagnostics; using System.Drawing; +using System.Runtime.InteropServices; +using System.Security.Policy; using System.Text; using System.Windows.Forms; @@ -113,6 +115,66 @@ public int Page } } + /// + /// Gets or sets the currently comparison page. + /// + public int ComparisonPage + { + get + { + if (Document == null || !_pageCacheValid) + return 0; + + var clientArea = GetScrollClientArea(); + int top = -DisplayRectangle.Top; + int bottom = top + clientArea.Height; + + for (int page = 0; page < Document.PageSizes.Count; page++) + { + var pageCache = _pageCache[page].OuterBounds; + if (top >= pageCache.Top || top < pageCache.Bottom) + { + float dispPageHeight = Math.Min(bottom, pageCache.Bottom) - top; + float dispOccupancy = dispPageHeight / (bottom - top); + float pageDispRatio = dispPageHeight / pageCache.Height; + + //Debug.Print("Page:{0}, pageCache:{1}, _compareBounds:{2}", page, pageCache, _compareBounds); + + // If this page occupies more than 50% of the screen. + if (dispOccupancy >= 0.5) + { + return page; + } + // If more than 50% of this page is displayed. + if (pageDispRatio >= 0.5) + { + return page; + } + + // When multiple pages are displayed, + // if an earlier page is small but has a visible bounds rectangle + // and a later page is large but has no visible bounds rectangle, + // the earlier page is set as the comparison page. + if (!_compareBounds.IsEmpty) + { + if ((dispOccupancy > 0) && (page + 1 < Document.PageSizes.Count)) + { + // The calculation of whether the bounds rectangle is displayed follows OnPaint(). + var bounds = BoundsFromPdf(new PdfRectangle(page + 1, _compareBounds)); + if (clientArea.Bottom < bounds.Top) + { + return page; + } + } + + } + } + } + + return Document.PageCount - 1; + } + } + /// /// Get the outer bounds of the page. /// From e7cb0b6f974d3ea4ce9378d51c50ac7427cf4959 Mon Sep 17 00:00:00 2001 From: wiera987 <50268838+wiera987@users.noreply.github.com> Date: Sun, 10 Nov 2024 21:03:35 +0900 Subject: [PATCH 14/39] Fixed: An exception occurred when pressing the zoom button. --- PdfiumViewer/PdfRenderer.cs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/PdfiumViewer/PdfRenderer.cs b/PdfiumViewer/PdfRenderer.cs index bfafc711..a5b1a1da 100644 --- a/PdfiumViewer/PdfRenderer.cs +++ b/PdfiumViewer/PdfRenderer.cs @@ -1364,15 +1364,16 @@ protected override void SetZoom(double zoom, Point? focus) if (focus.HasValue) { + // Zoom into the focus. location = focus.Value; } else { - // Zoom the center of the page. - var pageCache = _pageCache[Page]; - int x = pageCache.OuterBounds.X + pageCache.OuterBounds.Width / 2; - int y = pageCache.OuterBounds.Y + pageCache.OuterBounds.Height / 2; - location = new Point(x,y); + // Zoom the center of the pane. + var x = ClientRectangle.Width/2; + var y = ClientRectangle.Height / 2; + + location = new Point(x, y); } pdfLocation = PointToPdfRounded(location); From 31f4af87ef776d9058d1ddb7fb4a615d6accffbd Mon Sep 17 00:00:00 2001 From: wiera987 <50268838+wiera987@users.noreply.github.com> Date: Sun, 10 Nov 2024 21:03:35 +0900 Subject: [PATCH 15/39] Fixed: An exception occurred when pressing the zoom button. --- PdfiumViewer/PdfRenderer.cs | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/PdfiumViewer/PdfRenderer.cs b/PdfiumViewer/PdfRenderer.cs index bfafc711..8293f049 100644 --- a/PdfiumViewer/PdfRenderer.cs +++ b/PdfiumViewer/PdfRenderer.cs @@ -351,8 +351,9 @@ public PdfPoint PointToPdfRounded(Point location) for (int page = 0; page < Document.PageSizes.Count; page++) { var pageCache = _pageCache[page]; - if ((location.Y >= pageCache.OuterBounds.Top) && - (location.Y < pageCache.OuterBounds.Bottom)) + if (((location.Y >= pageCache.OuterBounds.Top) && + (location.Y < pageCache.OuterBounds.Bottom)) || + (page == Document.PageSizes.Count-1)) { location.X = Math.Min(Math.Max(location.X, pageCache.Bounds.Left), pageCache.Bounds.Right); location.Y = Math.Min(Math.Max(location.Y, pageCache.Bounds.Top), pageCache.Bounds.Bottom); @@ -1364,15 +1365,16 @@ protected override void SetZoom(double zoom, Point? focus) if (focus.HasValue) { + // Zoom into the focus. location = focus.Value; } else { - // Zoom the center of the page. - var pageCache = _pageCache[Page]; - int x = pageCache.OuterBounds.X + pageCache.OuterBounds.Width / 2; - int y = pageCache.OuterBounds.Y + pageCache.OuterBounds.Height / 2; - location = new Point(x,y); + // Zoom the center of the pane. + var x = ClientRectangle.Width/2; + var y = ClientRectangle.Height / 2; + + location = new Point(x, y); } pdfLocation = PointToPdfRounded(location); From fb5d1f3fc079608ebe0ad0087138d4c2ecf83511 Mon Sep 17 00:00:00 2001 From: wiera987 <50268838+wiera987@users.noreply.github.com> Date: Sun, 24 Nov 2024 13:36:39 +0900 Subject: [PATCH 16/39] The bookmark that corresponds to the current page is now displayed as selected. --- PdfiumViewer/PdfViewer.Designer.cs | 5 ++ PdfiumViewer/PdfViewer.cs | 119 +++++++++++++++++++++++++++-- PdfiumViewer/PdfViewer.resx | 62 ++++++++------- 3 files changed, 153 insertions(+), 33 deletions(-) diff --git a/PdfiumViewer/PdfViewer.Designer.cs b/PdfiumViewer/PdfViewer.Designer.cs index c8defc0f..2a576950 100644 --- a/PdfiumViewer/PdfViewer.Designer.cs +++ b/PdfiumViewer/PdfViewer.Designer.cs @@ -118,10 +118,15 @@ private void InitializeComponent() this._bookmarks.FullRowSelect = true; this._bookmarks.Name = "_bookmarks"; this._bookmarks.ShowLines = false; + this._bookmarks.BeforeCollapse += new System.Windows.Forms.TreeViewCancelEventHandler(this._bookmarks_BeforeCollapse); + this._bookmarks.AfterCollapse += new System.Windows.Forms.TreeViewEventHandler(this._bookmarks_AfterCollapse); + this._bookmarks.BeforeExpand += new System.Windows.Forms.TreeViewCancelEventHandler(this._bookmarks_BeforeExpand); + this._bookmarks.AfterExpand += new System.Windows.Forms.TreeViewEventHandler(this._bookmarks_AfterExpand); this._bookmarks.AfterSelect += new System.Windows.Forms.TreeViewEventHandler(this._bookmarks_AfterSelect); // // _renderer // + this._renderer.CompareBounds = ((System.Drawing.RectangleF)(resources.GetObject("_renderer.CompareBounds"))); this._renderer.Cursor = System.Windows.Forms.Cursors.Default; resources.ApplyResources(this._renderer, "_renderer"); this._renderer.Name = "_renderer"; diff --git a/PdfiumViewer/PdfViewer.cs b/PdfiumViewer/PdfViewer.cs index 4e7ec82b..1c0437c1 100644 --- a/PdfiumViewer/PdfViewer.cs +++ b/PdfiumViewer/PdfViewer.cs @@ -13,6 +13,8 @@ public partial class PdfViewer : UserControl { private IPdfDocument _document; private bool _showBookmarks; + private bool preventPageRefresh; + private int bookmarkPage; /// /// Gets or sets the PDF document. @@ -30,7 +32,7 @@ public IPdfDocument Document if (_document != null) { _renderer.Load(_document); - UpdateBookmarks(); + UpdateBookmarks(true); } UpdateEnabled(); @@ -117,7 +119,7 @@ protected virtual void OnLinkClick(LinkClickEventArgs e) handler(this, e); } - private void UpdateBookmarks() + private void UpdateBookmarks(bool construct = false) { bool visible = _showBookmarks && _document != null && _document.Bookmarks.Count > 0; @@ -127,12 +129,80 @@ private void UpdateBookmarks() { _container.Panel1Collapsed = false; - _bookmarks.Nodes.Clear(); - foreach (var bookmark in _document.Bookmarks) - _bookmarks.Nodes.Add(GetBookmarkNode(bookmark)); + if ((_bookmarks.Nodes.Count == 0) || (construct)) + { + _bookmarks.Nodes.Clear(); + foreach (var bookmark in _document.Bookmarks) + { + _bookmarks.Nodes.Add(GetBookmarkNode(bookmark)); + } + } + + // Select a bookmark for the renderer page. + bookmarkPage = -1; + SelectBookmarkForPage(_renderer.Page); + } + } + + /// + /// Select a bookmark for a specified page. + /// + public void SelectBookmarkForPage(int page) + { + TreeNode validNode = null; + int bmpage = bookmarkPage; + + if (page != bookmarkPage) + { + GetNodeForPage(page, _bookmarks.Nodes, ref validNode); + + // Select the last valid Node. + if (validNode != null) + { + preventPageRefresh = true; + _bookmarks.SelectedNode = validNode; + preventPageRefresh = false; + bookmarkPage = page; + } } + //Console.WriteLine("SelectBookmarkForPage: Page={0}!={1}, Text={2}", page, bmpage, validNode?.Text); } + /// + /// Recursively search for the node that corresponds to the page from Nodes. + /// + /// The page being selected. + /// Bookmark Nodes being searched recursively + /// Currently active Node + private void GetNodeForPage(int page, TreeNodeCollection nodes, ref TreeNode validNode) + { + int validPage = -1; + + foreach (TreeNode node in nodes) + { + PdfBookmark bookmark = (PdfBookmark)node.Tag; + + if (bookmark.PageIndex <= page) + { + // The last updated node is valid. + // However, if they are on the same page, select the node found first. + // Prefer child node over parent node. + if (bookmark.PageIndex != validPage) + { + validNode = node; + validPage = bookmark.PageIndex; + } + } + + // If the tree is expanded, explore further + if (node.IsExpanded) + { + GetNodeForPage(page, node.Nodes, ref validNode); + } + } + } + + /// /// Initializes a new instance of the PdfViewer class. /// @@ -145,6 +215,10 @@ public PdfViewer() ShowToolbar = true; ShowBookmarks = true; + _bookmarks.HideSelection = false; + preventPageRefresh = false; + bookmarkPage = -1; + UpdateEnabled(); } @@ -228,14 +302,47 @@ private TreeNode GetBookmarkNode(PdfBookmark bookmark) if (bookmark.Children != null) { foreach (var child in bookmark.Children) + { node.Nodes.Add(GetBookmarkNode(child)); + } } return node; } private void _bookmarks_AfterSelect(object sender, TreeViewEventArgs e) { - _renderer.Page = ((PdfBookmark)e.Node.Tag).PageIndex; + if (preventPageRefresh == false) + { + _renderer.Page = ((PdfBookmark)e.Node.Tag).PageIndex; + } + } + + private void _bookmarks_BeforeExpand(object sender, TreeViewCancelEventArgs e) + { + // AfterSelect event is fired when child node has focus. + preventPageRefresh = true; + } + + private void _bookmarks_AfterExpand(object sender, TreeViewEventArgs e) + { + // AfterSelect event is fired when child node has focus. + preventPageRefresh = false; + + // Select a bookmark for the renderer page. + bookmarkPage = -1; + SelectBookmarkForPage(_renderer.Page); + } + + private void _bookmarks_BeforeCollapse(object sender, TreeViewCancelEventArgs e) + { + // AfterSelect event is fired when child node has focus. + preventPageRefresh = true; + } + + private void _bookmarks_AfterCollapse(object sender, TreeViewEventArgs e) + { + // AfterSelect event is fired when child node has focus. + preventPageRefresh = false; } private void _renderer_LinkClick(object sender, LinkClickEventArgs e) diff --git a/PdfiumViewer/PdfViewer.resx b/PdfiumViewer/PdfViewer.resx index 07595c73..3f203a9b 100644 --- a/PdfiumViewer/PdfViewer.resx +++ b/PdfiumViewer/PdfViewer.resx @@ -121,6 +121,28 @@ 17, 17 + + 0, 0 + + + 588, 25 + + + + 0 + + + _toolStrip + + + System.Windows.Forms.ToolStrip, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 1 + Magenta @@ -160,28 +182,6 @@ Zoom Out - - 0, 0 - - - 588, 25 - - - - 0 - - - _toolStrip - - - System.Windows.Forms.ToolStrip, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - $this - - - 1 - Fill @@ -196,7 +196,7 @@ 0, 0 - 200, 413 + 200, 379 0 @@ -225,6 +225,14 @@ 0 + + + AAEAAAD/////AQAAAAAAAAAMAgAAAFFTeXN0ZW0uRHJhd2luZywgVmVyc2lvbj0yLjAuMC4wLCBDdWx0 + dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWIwM2Y1ZjdmMTFkNTBhM2EFAQAAABlTeXN0ZW0uRHJh + d2luZy5SZWN0YW5nbGVGBAAAAAF4AXkFd2lkdGgGaGVpZ2h0AAAAAAsLCwsCAAAAAAAAAAAAAAAAAAAA + AAAAAAs= + + Fill @@ -232,7 +240,7 @@ 0, 0 - 384, 413 + 384, 379 2 @@ -265,7 +273,7 @@ 1 - 588, 413 + 588, 379 200 @@ -289,10 +297,10 @@ True - 6, 13 + 6, 12 - 588, 438 + 588, 404 _saveButton From 0ff531ad8169dd13a25845377df7049227b8bd1d Mon Sep 17 00:00:00 2001 From: wiera987 <50268838+wiera987@users.noreply.github.com> Date: Mon, 25 Nov 2024 20:30:35 +0900 Subject: [PATCH 17/39] Fixed an issue that caused an exception when calling ZoomMin/ZoomMax during initialization of controls including PdfViewer. --- PdfiumViewer/PdfRenderer.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/PdfiumViewer/PdfRenderer.cs b/PdfiumViewer/PdfRenderer.cs index 8293f049..9c6adfd6 100644 --- a/PdfiumViewer/PdfRenderer.cs +++ b/PdfiumViewer/PdfRenderer.cs @@ -1361,6 +1361,9 @@ protected override void SetZoom(double zoom, Point? focus) Point location; PdfPoint pdfLocation; + if (Document == null || !_pageCacheValid) + return; + var bounds = GetDocumentBounds(); if (focus.HasValue) From 6fd28a366854a840481af1042c97ac36df85b5fc Mon Sep 17 00:00:00 2001 From: wiera987 <50268838+wiera987@users.noreply.github.com> Date: Thu, 28 Nov 2024 00:05:48 +0900 Subject: [PATCH 18/39] Fixed: Zooming with the mouse wheel changes the zoom position. --- PdfiumViewer/PdfRenderer.cs | 82 +++++++++++++++++++++++++++++++++++-- 1 file changed, 79 insertions(+), 3 deletions(-) diff --git a/PdfiumViewer/PdfRenderer.cs b/PdfiumViewer/PdfRenderer.cs index 9c6adfd6..89cbe49f 100644 --- a/PdfiumViewer/PdfRenderer.cs +++ b/PdfiumViewer/PdfRenderer.cs @@ -42,6 +42,9 @@ public class PdfRenderer : PanningZoomingScrollControl private MouseState _cachedMouseState = null; private TextSelectionState _textSelectionState = null; private RectangleF _compareBounds = Rectangle.Empty; + private Point zoomLocation; + private PdfPoint zoomPdfLocation; + private Rectangle zoomRectangle; /// /// The associated PDF document. @@ -580,6 +583,17 @@ protected override void OnLayout(LayoutEventArgs levent) UpdateScrollbars(); } + /// + /// Called when scroll. + /// + /// The event data. + protected override void OnScroll(ScrollEventArgs se) + { + base.OnScroll(se); + + zoomLocation = new Point(-999, -999); // Cancel zoom position when scrolling. + } + /// /// Called when the zoom level changes. /// @@ -591,6 +605,32 @@ protected override void OnZoomChanged(EventArgs e) UpdateScrollbars(); } + /// + /// Determines whether the specified key is a regular input key or a special key that requires preprocessing. + /// + /// + /// true if the specified key is a regular input key; otherwise, false. + /// + /// One of the values. + protected override bool IsInputKey(Keys keyData) + { + switch ((keyData) & Keys.KeyCode) + { + case Keys.Up: + case Keys.Down: + case Keys.Left: + case Keys.Right: + case Keys.PageUp: + case Keys.PageDown: + case Keys.Home: + case Keys.End: + zoomLocation = new Point(-999, -999); // Cancel zoom position when scrolling. + break; + } + + return base.IsInputKey(keyData); + } + protected override void OnKeyDown(KeyEventArgs e) { switch ((e.KeyData) & Keys.KeyCode) @@ -1103,6 +1143,18 @@ protected override void OnMouseDoubleClick(MouseEventArgs e) } } + protected override void OnMouseWheel(MouseEventArgs e) + { + var oldRect = DisplayRectangle; + base.OnMouseWheel(e); + var newRect = DisplayRectangle; + + if (IsScrolled(oldRect, newRect)) + { + zoomLocation = new Point(-999, -999); // Cancel zoom position when scrolling. + } + } + private void HandleMouseDownForLinks(MouseEventArgs e) { _dragState = null; @@ -1364,23 +1416,40 @@ protected override void SetZoom(double zoom, Point? focus) if (Document == null || !_pageCacheValid) return; - var bounds = GetDocumentBounds(); + if ((zoom == ZoomMax) && (Zoom== ZoomMax)) + return; // Repeated processing with ZoomMax accumulates errors in zoom position. + var fvalue = focus.HasValue ? focus.Value : new Point(-999,-999); if (focus.HasValue) { // Zoom into the focus. location = focus.Value; + + if (zoomLocation == location) + { + // Zoom to the same point while zooming without scrolling. + pdfLocation = zoomPdfLocation; + } + else + { + // When zoom position changes, zoom to new position. + pdfLocation = PointToPdfRounded(location); + zoomLocation = location; + zoomPdfLocation = pdfLocation; + } } else { // Zoom the center of the pane. var x = ClientRectangle.Width/2; var y = ClientRectangle.Height / 2; - location = new Point(x, y); + pdfLocation = PointToPdfRounded(location); + zoomLocation = location; + zoomPdfLocation = pdfLocation; } - pdfLocation = PointToPdfRounded(location); + //Console.WriteLine("{0},{1:F5},({2}),({3})", focus.HasValue, zoom, location, pdfLocation.Location); base.SetZoom(zoom, null); @@ -1395,6 +1464,13 @@ protected override void SetZoom(double zoom, Point? focus) ); } + private bool IsScrolled(Rectangle oldRect, Rectangle newRect) + { + bool isScrolled = (oldRect.Size == newRect.Size) && (oldRect.Location != newRect.Location); + + return isScrolled; + } + private void RedrawMarkers() { _markers = null; From 543d031fcf464e8686c703d24618f916fe8f2d7a Mon Sep 17 00:00:00 2001 From: wiera987 <50268838+wiera987@users.noreply.github.com> Date: Sat, 7 Dec 2024 13:57:10 +0900 Subject: [PATCH 19/39] Fixed: When zooming, the screen would flicker and update out of position for a moment. --- PdfiumViewer/CustomScrollControl.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PdfiumViewer/CustomScrollControl.cs b/PdfiumViewer/CustomScrollControl.cs index 5569a7ad..3134bbc7 100644 --- a/PdfiumViewer/CustomScrollControl.cs +++ b/PdfiumViewer/CustomScrollControl.cs @@ -381,7 +381,7 @@ private bool SetDisplayRectangleSize(int width, int height) if (y < minY) y = minY; - SetDisplayRectLocation(x, y); + SetDisplayRectLocation(x, y, false); return needLayout; } From 3dec9f6ad0e82b830504eec76e0f015b561eb575 Mon Sep 17 00:00:00 2001 From: wiera987 <50268838+wiera987@users.noreply.github.com> Date: Sat, 7 Dec 2024 16:01:29 +0900 Subject: [PATCH 20/39] Change: Mouse wheel zooms to the focus point, zoom button zooms to the focused page. --- PdfiumViewer/PdfRenderer.cs | 41 ++++++++++++++++--------------------- 1 file changed, 18 insertions(+), 23 deletions(-) diff --git a/PdfiumViewer/PdfRenderer.cs b/PdfiumViewer/PdfRenderer.cs index 89cbe49f..b7c409a9 100644 --- a/PdfiumViewer/PdfRenderer.cs +++ b/PdfiumViewer/PdfRenderer.cs @@ -1410,8 +1410,8 @@ private SizeF TranslateSize(SizeF size) /// The location to focus on. protected override void SetZoom(double zoom, Point? focus) { - Point location; - PdfPoint pdfLocation; + Point location = new Point(-999,-999); + PdfPoint pdfLocation = new PdfPoint(0, location); if (Document == null || !_pageCacheValid) return; @@ -1419,10 +1419,9 @@ protected override void SetZoom(double zoom, Point? focus) if ((zoom == ZoomMax) && (Zoom== ZoomMax)) return; // Repeated processing with ZoomMax accumulates errors in zoom position. - var fvalue = focus.HasValue ? focus.Value : new Point(-999,-999); if (focus.HasValue) { - // Zoom into the focus. + // Zoom into the focus point. location = focus.Value; if (zoomLocation == location) @@ -1437,31 +1436,27 @@ protected override void SetZoom(double zoom, Point? focus) zoomLocation = location; zoomPdfLocation = pdfLocation; } + + base.SetZoom(zoom, null); + + var newLocation = PointFromPdf(pdfLocation); + SetDisplayRectLocation( + new Point( + DisplayRectangle.Left - (newLocation.X - location.X), + DisplayRectangle.Top - (newLocation.Y - location.Y) + ), + false + ); } else { - // Zoom the center of the pane. - var x = ClientRectangle.Width/2; - var y = ClientRectangle.Height / 2; - location = new Point(x, y); - pdfLocation = PointToPdfRounded(location); - zoomLocation = location; - zoomPdfLocation = pdfLocation; + // Zoom to the focused page. + base.SetZoom(zoom, null); + Page = Page; + zoomLocation = new Point(-999, -999); // Cancel zoom position when scrolling. } - //Console.WriteLine("{0},{1:F5},({2}),({3})", focus.HasValue, zoom, location, pdfLocation.Location); - base.SetZoom(zoom, null); - - var newLocation = PointFromPdf(pdfLocation); - - SetDisplayRectLocation( - new Point( - DisplayRectangle.Left - (newLocation.X - location.X), - DisplayRectangle.Top - (newLocation.Y - location.Y) - ), - false - ); } private bool IsScrolled(Rectangle oldRect, Rectangle newRect) From 32ebeddbb9d5d7bea8d3077fcda0b6a24fbfffaf Mon Sep 17 00:00:00 2001 From: wiera987 <50268838+wiera987@users.noreply.github.com> Date: Sun, 8 Dec 2024 00:58:22 +0900 Subject: [PATCH 21/39] Added buttons for bookmark operations. --- PdfiumViewer/PdfViewer.Designer.cs | 73 +++++++ PdfiumViewer/PdfViewer.cs | 135 ++++++++++++- PdfiumViewer/PdfViewer.resx | 228 +++++++++++++++++++--- PdfiumViewer/Resources/bm_collapse20.png | Bin 0 -> 509 bytes PdfiumViewer/Resources/bm_expand_fill.png | Bin 0 -> 596 bytes PdfiumViewer/Resources/bookmark_aim20.png | Bin 0 -> 670 bytes PdfiumViewer/Resources/close_fill20.png | Bin 0 -> 484 bytes 7 files changed, 404 insertions(+), 32 deletions(-) create mode 100644 PdfiumViewer/Resources/bm_collapse20.png create mode 100644 PdfiumViewer/Resources/bm_expand_fill.png create mode 100644 PdfiumViewer/Resources/bookmark_aim20.png create mode 100644 PdfiumViewer/Resources/close_fill20.png diff --git a/PdfiumViewer/PdfViewer.Designer.cs b/PdfiumViewer/PdfViewer.Designer.cs index 2a576950..e0ae0897 100644 --- a/PdfiumViewer/PdfViewer.Designer.cs +++ b/PdfiumViewer/PdfViewer.Designer.cs @@ -40,12 +40,20 @@ private void InitializeComponent() this._zoomInButton = new System.Windows.Forms.ToolStripButton(); this._zoomOutButton = new System.Windows.Forms.ToolStripButton(); this._container = new System.Windows.Forms.SplitContainer(); + this.toolStripBookmark = new System.Windows.Forms.ToolStrip(); + this.toolStripButtonExpand = new System.Windows.Forms.ToolStripButton(); + this.toolStripSplitButtonCollapse = new System.Windows.Forms.ToolStripSplitButton(); + this.expandAllToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.collapseAllToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripButtonExpandCurrent = new System.Windows.Forms.ToolStripButton(); + this.toolStripButtonClose = new System.Windows.Forms.ToolStripButton(); this._bookmarks = new PdfiumViewer.NativeTreeView(); this._renderer = new PdfiumViewer.PdfRenderer(); this._toolStrip.SuspendLayout(); this._container.Panel1.SuspendLayout(); this._container.Panel2.SuspendLayout(); this._container.SuspendLayout(); + this.toolStripBookmark.SuspendLayout(); this.SuspendLayout(); // // _toolStrip @@ -105,6 +113,7 @@ private void InitializeComponent() // // _container.Panel1 // + this._container.Panel1.Controls.Add(this.toolStripBookmark); this._container.Panel1.Controls.Add(this._bookmarks); // // _container.Panel2 @@ -112,6 +121,60 @@ private void InitializeComponent() this._container.Panel2.Controls.Add(this._renderer); this._container.TabStop = false; // + // toolStripBookmark + // + this.toolStripBookmark.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.toolStripButtonExpand, + this.toolStripSplitButtonCollapse, + this.toolStripButtonExpandCurrent, + this.toolStripButtonClose}); + resources.ApplyResources(this.toolStripBookmark, "toolStripBookmark"); + this.toolStripBookmark.Name = "toolStripBookmark"; + // + // toolStripButtonExpand + // + this.toolStripButtonExpand.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + resources.ApplyResources(this.toolStripButtonExpand, "toolStripButtonExpand"); + this.toolStripButtonExpand.Name = "toolStripButtonExpand"; + this.toolStripButtonExpand.Click += new System.EventHandler(this.toolStripButtonExpand_Click); + // + // toolStripSplitButtonCollapse + // + this.toolStripSplitButtonCollapse.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + this.toolStripSplitButtonCollapse.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.expandAllToolStripMenuItem, + this.collapseAllToolStripMenuItem}); + resources.ApplyResources(this.toolStripSplitButtonCollapse, "toolStripSplitButtonCollapse"); + this.toolStripSplitButtonCollapse.Name = "toolStripSplitButtonCollapse"; + this.toolStripSplitButtonCollapse.ButtonClick += new System.EventHandler(this.toolStripSplitButtonCollapse_ButtonClick); + // + // expandAllToolStripMenuItem + // + this.expandAllToolStripMenuItem.Name = "expandAllToolStripMenuItem"; + resources.ApplyResources(this.expandAllToolStripMenuItem, "expandAllToolStripMenuItem"); + this.expandAllToolStripMenuItem.Click += new System.EventHandler(this.expandAllToolStripMenuItem_Click); + // + // collapseAllToolStripMenuItem + // + this.collapseAllToolStripMenuItem.Name = "collapseAllToolStripMenuItem"; + resources.ApplyResources(this.collapseAllToolStripMenuItem, "collapseAllToolStripMenuItem"); + this.collapseAllToolStripMenuItem.Click += new System.EventHandler(this.collapseAllToolStripMenuItem_Click); + // + // toolStripButtonExpandCurrent + // + this.toolStripButtonExpandCurrent.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + resources.ApplyResources(this.toolStripButtonExpandCurrent, "toolStripButtonExpandCurrent"); + this.toolStripButtonExpandCurrent.Name = "toolStripButtonExpandCurrent"; + this.toolStripButtonExpandCurrent.Click += new System.EventHandler(this.toolStripButtonExpandCurrent_Click); + // + // toolStripButtonClose + // + this.toolStripButtonClose.Alignment = System.Windows.Forms.ToolStripItemAlignment.Right; + this.toolStripButtonClose.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + resources.ApplyResources(this.toolStripButtonClose, "toolStripButtonClose"); + this.toolStripButtonClose.Name = "toolStripButtonClose"; + this.toolStripButtonClose.Click += new System.EventHandler(this.toolStripButtonClose_Click); + // // _bookmarks // resources.ApplyResources(this._bookmarks, "_bookmarks"); @@ -145,8 +208,11 @@ private void InitializeComponent() this._toolStrip.ResumeLayout(false); this._toolStrip.PerformLayout(); this._container.Panel1.ResumeLayout(false); + this._container.Panel1.PerformLayout(); this._container.Panel2.ResumeLayout(false); this._container.ResumeLayout(false); + this.toolStripBookmark.ResumeLayout(false); + this.toolStripBookmark.PerformLayout(); this.ResumeLayout(false); this.PerformLayout(); @@ -163,5 +229,12 @@ private void InitializeComponent() private System.Windows.Forms.SplitContainer _container; private NativeTreeView _bookmarks; private PdfRenderer _renderer; + private System.Windows.Forms.ToolStrip toolStripBookmark; + private System.Windows.Forms.ToolStripButton toolStripButtonExpand; + private System.Windows.Forms.ToolStripSplitButton toolStripSplitButtonCollapse; + private System.Windows.Forms.ToolStripMenuItem collapseAllToolStripMenuItem; + private System.Windows.Forms.ToolStripButton toolStripButtonExpandCurrent; + private System.Windows.Forms.ToolStripMenuItem expandAllToolStripMenuItem; + private System.Windows.Forms.ToolStripButton toolStripButtonClose; } } diff --git a/PdfiumViewer/PdfViewer.cs b/PdfiumViewer/PdfViewer.cs index 1c0437c1..79722c1d 100644 --- a/PdfiumViewer/PdfViewer.cs +++ b/PdfiumViewer/PdfViewer.cs @@ -1,8 +1,13 @@ using System; using System.Collections.Generic; using System.ComponentModel; +using System.Reflection.Emit; +using System.Runtime.InteropServices; +using System.Runtime.InteropServices.Expando; +using System.Security.Cryptography; using System.Text; using System.Windows.Forms; +using static System.Windows.Forms.VisualStyles.VisualStyleElement; namespace PdfiumViewer { @@ -11,6 +16,15 @@ namespace PdfiumViewer /// public partial class PdfViewer : UserControl { + public event EventHandler PanelBookmarkClosed; + + // Constants for the SendMessage() method. + private const int WM_HSCROLL = 276; + private const int SB_LEFT = 6; + [DllImport("user32.dll")] + private static extern int SendMessage(IntPtr hWnd, int wMsg, + int wParam, int lParam); + private IPdfDocument _document; private bool _showBookmarks; private bool preventPageRefresh; @@ -146,6 +160,7 @@ private void UpdateBookmarks(bool construct = false) /// /// Select a bookmark for a specified page. + /// Do not expand new nodes. /// public void SelectBookmarkForPage(int page) { @@ -154,7 +169,7 @@ public void SelectBookmarkForPage(int page) if (page != bookmarkPage) { - GetNodeForPage(page, _bookmarks.Nodes, ref validNode); + GetPageNode(page, _bookmarks.Nodes, false, ref validNode); // Select the last valid Node. if (validNode != null) @@ -173,8 +188,9 @@ public void SelectBookmarkForPage(int page) /// /// The page being selected. /// Bookmark Nodes being searched recursively + /// If true, search while expanding collapsed nodes /// Currently active Node - private void GetNodeForPage(int page, TreeNodeCollection nodes, ref TreeNode validNode) + private void GetPageNode(int page, TreeNodeCollection nodes, bool expand, ref TreeNode validNode) { int validPage = -1; @@ -194,10 +210,11 @@ private void GetNodeForPage(int page, TreeNodeCollection nodes, ref TreeNode val } } - // If the tree is expanded, explore further - if (node.IsExpanded) + // If the tree is expanded, explore further. + // If 'expand' is true, explore nodes even if they are collapsed. + if (node.IsExpanded || (expand && (node.Nodes != null))) { - GetNodeForPage(page, node.Nodes, ref validNode); + GetPageNode(page, node.Nodes, expand, ref validNode); } } } @@ -349,5 +366,113 @@ private void _renderer_LinkClick(object sender, LinkClickEventArgs e) { OnLinkClick(e); } + + private void toolStripButtonExpand_Click(object sender, EventArgs e) + { + // Expand Top-Level + bool visible = _showBookmarks && _document != null && _document.Bookmarks.Count > 0; + + if (visible) + { + foreach (TreeNode node in _bookmarks.Nodes) + { + node.Expand(); + } + + // Show selected nodes. + EnsureVisibleWithoutRightScrolling(_bookmarks.SelectedNode); + } + } + + private void toolStripSplitButtonCollapse_ButtonClick(object sender, EventArgs e) + { + // Collapse Top-Level + bool visible = _showBookmarks && _document != null && _document.Bookmarks.Count > 0; + + if (visible) + { + foreach (TreeNode node in _bookmarks.Nodes) + { + node.Collapse(); + } + // Show selected nodes. + EnsureVisibleWithoutRightScrolling(_bookmarks.SelectedNode); + } + } + + private void expandAllToolStripMenuItem_Click(object sender, EventArgs e) + { + // Expand All + _bookmarks.ExpandAll(); + // Show selected nodes. + EnsureVisibleWithoutRightScrolling(_bookmarks.SelectedNode); + } + + private void collapseAllToolStripMenuItem_Click(object sender, EventArgs e) + { + // Collapse All + CollapseChildrenNodes(_bookmarks.Nodes); + // Show selected nodes. + EnsureVisibleWithoutRightScrolling(_bookmarks.SelectedNode); + } + + private void toolStripButtonExpandCurrent_Click(object sender, EventArgs e) + { + // Expand current bookmark + TreeNode validNode = null; + + // Collapse all nodes initially + CollapseChildrenNodes(_bookmarks.Nodes); + GetPageNode(_renderer.Page, _bookmarks.Nodes, true, ref validNode); + ExpandParentNodes(validNode); + + // Show selected nodes. + EnsureVisibleWithoutRightScrolling(_bookmarks.SelectedNode); + } + + private void ExpandParentNodes(TreeNode node) + { + if (node != null) + { + node.Expand(); + if (node.Parent != null) + { + ExpandParentNodes(node.Parent); + } + } + } + + private void CollapseChildrenNodes(TreeNodeCollection nodes) + { + foreach (TreeNode node in nodes) + { + if (node != null) + { + if (node.Nodes != null) + { + CollapseChildrenNodes(node.Nodes); + } + node.Collapse(); + } + } + } + + private void EnsureVisibleWithoutRightScrolling(TreeNode node) + { + // we do the standard call.. + node.EnsureVisible(); + + // ..and afterwards we scroll to the left again! + SendMessage(_bookmarks.Handle, WM_HSCROLL, SB_LEFT, 0); + } + + private void toolStripButtonClose_Click(object sender, EventArgs e) + { + ShowBookmarks = false; + + // Fire a custom event when a bookmark is closed + PanelBookmarkClosed?.Invoke(this, e); + } + } } diff --git a/PdfiumViewer/PdfViewer.resx b/PdfiumViewer/PdfViewer.resx index 3f203a9b..9bea7a5a 100644 --- a/PdfiumViewer/PdfViewer.resx +++ b/PdfiumViewer/PdfViewer.resx @@ -121,28 +121,6 @@ 17, 17 - - 0, 0 - - - 588, 25 - - - - 0 - - - _toolStrip - - - System.Windows.Forms.ToolStrip, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - $this - - - 1 - Magenta @@ -182,6 +160,28 @@ Zoom Out + + 0, 0 + + + 588, 25 + + + + 0 + + + _toolStrip + + + System.Windows.Forms.ToolStrip, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 1 + Fill @@ -189,14 +189,152 @@ 0, 25 - - Fill + + 121, 17 + + + + iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAFJSURBVEhLYxg+gEPRI5pNyTOfgSGUGSISygzig8QhfAoB + p4r3fxBmU/Y6AuJzKHvOh4kxyLlLAoUYOZS9wtiVPRvwYiWvdJB+DMCu5HEeZiCHiud+GJtd2esUA4M9 + C9DCOJgYIcyh6BkFNRYJyLpIASV+oyhU8rjGIOMmBJJmU/YMQJbDh7FbAATM8l6O7Moef0GKgAY+ZJDx + loZKgQGbkocX1mBBwpwqXoVApUwQHdiAnKsiu7K3A8zlQwewK3kmYkumIHEIn0IAiyBg2B8C8ZGTKYey + myxQiNJk6nUObiB6MlXxYCctmWLLnJI+csMkmSp6qg3NZDoYSlMGdhWvLGzhjoIVvTNBajEA4dLUKwwm + RgiDUhzUWCRAoDQlyQIlryCwmeiAWd7dASWZAi2FSoEB0De5WIMFGePKyXAgby8wNJMpbQADAwAeqgoS + oZ5UtAAAAABJRU5ErkJggg== + - + + Magenta + + + 23, 24 + + + Expand + + + Expand Top-Level Bookmarks + + + 180, 22 + + + Expand All + + + 180, 22 + + + Collapse All + + + + iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAFFSURBVDhP3ZOxSgRBDIa3cHdyT6AIsjubrazUQiwUixM3 + k/XEwicQwQdQQRDB1vcRG0F9DsHKysLyDrwD1yQeKOsdynXeDyGZSfgZ+DLR9CkpaFGzS8sM8nARp+1l + azQVp7wEGG6TnB/GBoY9KGgTMk4Tz8+toqqlHsQp/TSFnNbB80CHxgUgn9ispydA6jrkK7mrY+QXM5lU + YtYDX21o7Xx1AFj2rDGdSnzYsZwTQxHuBdSxNZr6E2VP+zGWKy6jbQHYH4KqXVYeDW2+NOOrVaF3N9JI + wl7jqaOzBkUoQ8FnaghZ+WYmk8oMZR+t1r2cbsoup7bmBKtd+SmvCfK5NZrSdfj16+V8GvnOrMNwKDDe + 7U4pY7gc2nzTwtY8YHU9irCGboCulo5+GtFjq6A1AdLVs3lMKnnVTZTynB0k2/mfKIo+AOhngqW543Bu + AAAAAElFTkSuQmCC + + + + Magenta + + + 32, 24 + + + Collapse + + + Collapse Top-Level Bookmarks + + + + iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAGOSURBVDhPvVS9SgNBED4Fd1dsBEHBwuR20/kENipIzN0u + +gZaWPgCIjaWPoGFhZ0oaBBrSwXBV1GihYVFEGKc725WDzcJOVE/GHZ+vvlmb+/2on/BmGnMS+OWBxk4 + TB+AytKkiNP78ZrrDmPC2Ltopj7B3SGkTg9AVNru9tpV0Yizx9x9bg8hY3sBErkjeSaHNLYL49BjFFxp + 0nOOQ0htL1kwg4jtCeKiqVp6yOUIMXo4DFEUpLPc8b40jY40qx34PgeUEiw2fgcNe8Y6tCDOC6sy9h15 + +H4AcV6LnF/ZIb3ZF6ylBGV1bdv7quLaas614RcHlRL0UNX0DTmYitNM1ONHgkCf73AYwaTZS1CZdBPG + 4SdywaTJYYhgh7o+reLkGjkYfOS4Wm6Hwrh1uttPmZCxRzAWaNENcuDk8aAd8l2mz+I4I5vkgc4u4XIk + dGLp7j76IRmHergcgprPQMqIeBT6nXHpC7MrUyR65XlCu1OuhFBVuyi0vaXpG5zqCxm7LfpR3CjTWODU + XyCKPgDrXcUFGj58dAAAAABJRU5ErkJggg== + + + + None + + + Magenta + + + 24, 24 + + + toolStripButton1 + + + Expand Current Bookmark + + + + iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAEUSURBVDhP5VRBa8IwGO2lTT1u3mQoTbzpYXj2ZKdrElCH + 4E/xIHiYv9nadlP0i3uGQbbSijcfFMJ773t8afLFe3S04mYo9JpF+g3Mv2CRHIdcbry2fgLlggn92ejq + UyjUMYjkArQDoxnPxcvlCrQLX7wPyLhD6CEQegrJIhBqZjR4dj7XfUh/I+TJkIwpCr6ZUAkk2oFKDAct + NV5I5UBohsKCcTlCWAEuqxx2BeNJTIW5DRDqC+vcaLDVg+mMAi5d/e4Wcn3cNRBh1/+Ymw/rrHaocyh0 + IDcfCsLuc238jnol4x4FdLHlHJJFwPUHaT9TQl4ahh4kF9TBFsbS0SN9aUPLRs8+DhXumX0cXibPoB4T + nncGvBCB7WZU/eEAAAAASUVORK5CYII= + + + + Magenta + + + 23, 24 + + + toolStripButton1 + + + Close Bookmarks + + 0, 0 + + 200, 27 + + + 1 + + + toolStrip1 + + + toolStripBookmark + + + System.Windows.Forms.ToolStrip, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + _container.Panel1 + + + 0 + + + Top, Bottom, Left, Right + + + 0, 30 + - 200, 379 + 200, 349 0 @@ -211,7 +349,7 @@ _container.Panel1 - 0 + 1 _container.Panel1 @@ -332,6 +470,42 @@ System.Windows.Forms.ToolStripButton, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + toolStripButtonExpand + + + System.Windows.Forms.ToolStripButton, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + toolStripSplitButtonCollapse + + + System.Windows.Forms.ToolStripSplitButton, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + expandAllToolStripMenuItem + + + System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + collapseAllToolStripMenuItem + + + System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + toolStripButtonExpandCurrent + + + System.Windows.Forms.ToolStripButton, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + toolStripButtonClose + + + System.Windows.Forms.ToolStripButton, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + PdfViewer diff --git a/PdfiumViewer/Resources/bm_collapse20.png b/PdfiumViewer/Resources/bm_collapse20.png new file mode 100644 index 0000000000000000000000000000000000000000..04ef74ccff774c4e9b57676819cc78b366987e32 GIT binary patch literal 509 zcmVPx#1ZP1_K>z@;j|==^1poj532;bRa{vGi!2kdb!2!6DYwZ940g_2XK~y+T-IKpB z1W^#jXJ+qqms}JmM98_@jY6f;$w^4;?%_{Rs5BZ9iD+nPL^PEC0SZ4(fk@Qo-ElgJ zAR^%|cl*ZMmzNW{NKoOEY`*W!%=R>w;E=1K5Pg-K+<7!YYEWVrA_0s824Uv2 zj{x0LK6e7dM~K`kn3tqO3}ckjHb295{1-cw?T^k@Dm!62-ivDdPt24*qBQLVw(B38 zjz6Osn(w8|VvUKfD8yDI+CjoNGXsa=WVv{-9*xveW+qtp{b=Dtpg!$$>d_XR0j*5 zEwQm_QFRmnH)I&7QU+cu7xovTnVKPV4z=5+wITn{gsyymScp*2bmeC6qQT8dA8{$| z#--mOqS5%8-+lM`F18cwK{9Al7pdz0M*w&Ob^nox%Q5^O00000NkvXXu0mjfCX3!0 literal 0 HcmV?d00001 diff --git a/PdfiumViewer/Resources/bm_expand_fill.png b/PdfiumViewer/Resources/bm_expand_fill.png new file mode 100644 index 0000000000000000000000000000000000000000..74605f8699585ad08d9eab2c4c812dfd7184f4ad GIT binary patch literal 596 zcmV-a0;~OrP)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!TDjc?aX{L(D0yc!HUGE1>$2b)3N~Y zp$IV96pCKHVMO2E?E11ERyTfu=I$|4tsvUtPU@KzODrL>S*2Zjg-$sB_|=NplLYic zX%!(n z_wr*TL_x*D%DRtzP^UD4N3duwl@qTnUp~b<8;qKrVTryCD>f+lcs7 zr?nGR92uw*GR;C5DIgi{|vc}A6mV?1cw|=%t;%ymfKVgxZs)ek{(t! zeu2QIVwXGV7r)z-DBtBe8@W5$)IN|0)TiRVY>MK!Mfj?An-*toE@xoVpX_Btn;xz6 z`fQ4&-BA4DqW@#lNTSDNth4cKdLLfXGqc-%El<8fX%!Ld8_y;ebruw;{+d3TkO#b~ zv}zPdjC)RcO~p08rYf%)LVw;en~n|{2HWy&>UsU}W%E>btIPOSe%-Fq+o^PueZqrn irqR;dFgE?i0Q>@s9wvk%70N3B0000Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!Tc=cZ2VEBNMU86kS>)XB8a+o!Pd^! zblHodjTi{Q=*{N#W_)ja8=PY|RX*^TH*em2=gsWQilYX&^=S96EK1Qj#obzrD1T1! z^$qSG;0w-QnhVtNOiH-OkwY=oek}GTOXA0e-yHGQr@@5-m?IoI9v-@djTY@ zVD3Xb%9c6o6GX|2V+*N8*I%fgSTgQbNXo_dbM8ANw+;ZI*maXTy=09hNgN;}KU|2P zxC}Z*1Xpgk9^(oAPp22(RSK?+H{XM?Q)6st$VcfroKj1ppi=TN36NjpLsjJKu6l|E zy?C4aI%);0^9uWk+ZJt=&z8=4Pbzt`=1d*6f<>OW%5UnIpfBM#19C+f}M6?8W=g5&^VD5Js`CDs7@sutIMQI`|^! zRR}#AgdA?f6SUU4k1z`ed!3BC9+Y8jxL|ZZ4NNJMn*oxc+@dFr?J9LKfM}4 zdjq6g!uT^X@-g-qUr@?vhgXQ}{rjp>vZ_G5!SoW(F2?I~n`~;PBxLXfy~8{Dlya*% z6}}*d(lrup;L5Lb`R6>|x1k$D_D91^kBdbt>NRflmJ0$*T+38H14p}icH4r8(0zmz zJrKKJ-QDx}wKXnxHeaglxo<++E{N$$xs!kA(W6F)zX_1-c^)gIF#rGn07*qoM6N<$ Ef=%r$F#rGn literal 0 HcmV?d00001 diff --git a/PdfiumViewer/Resources/close_fill20.png b/PdfiumViewer/Resources/close_fill20.png new file mode 100644 index 0000000000000000000000000000000000000000..d4e854467fdde92ffff0f4c8017a03e87e0a4d3d GIT binary patch literal 484 zcmVF&JZ_vu>2Z zIP0X83io&lLcp|O1nktFp7Xo^dtL}besIV<7%^}vI;jTL4Uq6)m5s|@>H{-+3?Jh}oMV=$ChAXJJRFwOxr1}|65T*3Jl(DVe` z&-uVHwtpbi5_pD+jPS!Feph=LFX zs|h#&_Eh-Y$EvHG;gnS_T)E}9XWOV+auHDE9aT2P$qHqq=4d7pjGSs&5P3yCYf_L0&L8q}L$aUMypL8|0wzR_IaqLV9`&1;> z=Iv7P$$j*+)Gj-2^&7olSkDmQVc*e%_HwA-d-YjMNqad| Date: Fri, 13 Dec 2024 22:42:29 +0900 Subject: [PATCH 22/39] Fixed: An exception occurred when loading a short PDF after displaying the last page of a long PDF. --- PdfiumViewer/PdfRenderer.cs | 28 +++++++++++++++++++++++----- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/PdfiumViewer/PdfRenderer.cs b/PdfiumViewer/PdfRenderer.cs index b7c409a9..ad5e52ae 100644 --- a/PdfiumViewer/PdfRenderer.cs +++ b/PdfiumViewer/PdfRenderer.cs @@ -44,7 +44,6 @@ public class PdfRenderer : PanningZoomingScrollControl private RectangleF _compareBounds = Rectangle.Empty; private Point zoomLocation; private PdfPoint zoomPdfLocation; - private Rectangle zoomRectangle; /// /// The associated PDF document. @@ -332,6 +331,27 @@ public PdfRenderer() Markers.CollectionChanged += Markers_CollectionChanged; } + private void ResetRenderer() + { + _maxWidth = 0; + _maxHeight = 0; + + _visiblePageStart = 0; // to avoid an exception from OnSetCursor. + _visiblePageEnd = -1; + + _pageCacheValid = false; + _cachedLink = null; + _dragState = null; + _cachedMouseState = null; + + _textSelectionState = null; + _isSelectingText = false; + + _compareBounds = Rectangle.Empty; + zoomLocation = new Point(-999, -999); // Cancel zoom position when scrolling. + zoomPdfLocation = new PdfPoint(0, zoomLocation); + } + private void Markers_CollectionChanged(object sender, EventArgs e) { RedrawMarkers(); @@ -689,9 +709,7 @@ public void Load(IPdfDocument document) private void ReloadDocument() { - _maxWidth = 0; - _maxHeight = 0; - _textSelectionState = null; + ResetRenderer(); foreach (var size in Document.PageSizes) { @@ -1564,7 +1582,7 @@ protected override void Dispose(bool disposing) pageCache.Image = null; } } - + _disposed = true; } From e5009552ea5fa0d2bda6010611e106a0dfb21883 Mon Sep 17 00:00:00 2001 From: wiera987 <50268838+wiera987@users.noreply.github.com> Date: Wed, 18 Dec 2024 21:41:39 +0900 Subject: [PATCH 23/39] Fixed: When I minimized the window and restored it, the page was out of place. --- PdfiumViewer/CustomScrollControl.cs | 7 ++++++- PdfiumViewer/PdfRenderer.cs | 8 +++++++- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/PdfiumViewer/CustomScrollControl.cs b/PdfiumViewer/CustomScrollControl.cs index 3134bbc7..3f77320f 100644 --- a/PdfiumViewer/CustomScrollControl.cs +++ b/PdfiumViewer/CustomScrollControl.cs @@ -123,6 +123,11 @@ private bool ApplyScrollbarChanges() var fullClient = ClientRectangle; var minClient = fullClient; + if (fullClient.Height == 0) + { + return false; + } + if (HScroll) fullClient.Height += SystemInformation.HorizontalScrollBarHeight; else @@ -270,7 +275,7 @@ private void SetDisplayRectLocation(int x, int y, bool preserveContents) _displayRect.X = x; _displayRect.Y = y; - + if ((xDelta != 0 || yDelta != 0) && IsHandleCreated && preserveContents) { var cr = ClientRectangle; diff --git a/PdfiumViewer/PdfRenderer.cs b/PdfiumViewer/PdfRenderer.cs index ad5e52ae..7bf75187 100644 --- a/PdfiumViewer/PdfRenderer.cs +++ b/PdfiumViewer/PdfRenderer.cs @@ -600,7 +600,13 @@ protected override void OnLayout(LayoutEventArgs levent) { base.OnLayout(levent); - UpdateScrollbars(); + // Calculate when the form is not minimized. + if (Height>0) + { + UpdateScrollbars(); + // UpdateScrollbars() rebuilds the cache and changes the Page, so the event is called twice. + OnDisplayRectangleChanged(EventArgs.Empty); + } } /// From 705bdd2228621ddb825917f2d1147bec5b7e5812 Mon Sep 17 00:00:00 2001 From: wiera987 <50268838+wiera987@users.noreply.github.com> Date: Thu, 19 Dec 2024 23:13:13 +0900 Subject: [PATCH 24/39] Patch: Repeated magnification causes the display position to shift due to rounding error. --- PdfiumViewer/CustomScrollControl.cs | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/PdfiumViewer/CustomScrollControl.cs b/PdfiumViewer/CustomScrollControl.cs index 3f77320f..73e4adae 100644 --- a/PdfiumViewer/CustomScrollControl.cs +++ b/PdfiumViewer/CustomScrollControl.cs @@ -15,6 +15,8 @@ public class CustomScrollControl : Control { private Size _displaySize; private Rectangle _displayRect; + private double _displayRect_X; // Patch: Repeated magnification causes the display position to shift due to rounding error. + private double _displayRect_Y; // Patch: Same as Above private readonly ScrollProperties _verticalScroll; private readonly ScrollProperties _horizontalScroll; @@ -244,16 +246,18 @@ public void SetDisplayRectLocation(Point offset, bool preserveContents) SyncScrollbars(); } - private void SetDisplayRectLocation(int x, int y) + private void SetDisplayRectLocation(double x, double y) { SetDisplayRectLocation(x, y, true); } - private void SetDisplayRectLocation(int x, int y, bool preserveContents) + private void SetDisplayRectLocation(double x, double y, bool preserveContents) { int xDelta = 0; int yDelta = 0; + Console.WriteLine("SetDisplayRectLocation({0},{1},{2})={3}", x, y, preserveContents, _displayRect); + var client = ClientRectangle; var displayRectangle = _displayRect; int minX = Math.Min(client.Width - displayRectangle.Width, 0); @@ -269,12 +273,14 @@ private void SetDisplayRectLocation(int x, int y, bool preserveContents) y = minY; if (displayRectangle.X != x) - xDelta = x - displayRectangle.X; + xDelta = (int)(x - _displayRect_X); if (displayRectangle.Y != y) - yDelta = y - displayRectangle.Y; + yDelta = (int)(y - _displayRect_Y); - _displayRect.X = x; - _displayRect.Y = y; + _displayRect_X = x; + _displayRect_Y = y; + _displayRect.X = (int)x; + _displayRect.Y = (int)y; if ((xDelta != 0 || yDelta != 0) && IsHandleCreated && preserveContents) { @@ -322,8 +328,8 @@ private bool SetVisibleScrollbars(bool horiz, bool vert) if (needLayout) { - int x = _displayRect.X; - int y = _displayRect.Y; + double x = _displayRect_X; + double y = _displayRect_Y; if (!horiz) x = 0; @@ -373,8 +379,8 @@ private bool SetDisplayRectangleSize(int width, int height) if (minY > 0) minY = 0; - int x = (int)(_displayRect.X * hScale); - int y = (int)(_displayRect.Y * vScale); + double x = (_displayRect_X * hScale); + double y = (_displayRect_Y * vScale); if (!HScroll || x > 0) x = 0; From 739a40c06b4dae68a107eb50ec6fd27a87246270 Mon Sep 17 00:00:00 2001 From: wiera987 <50268838+wiera987@users.noreply.github.com> Date: Thu, 19 Dec 2024 23:13:13 +0900 Subject: [PATCH 25/39] Patch: Repeated magnification causes the display position to shift due to rounding error. --- PdfiumViewer/CustomScrollControl.cs | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/PdfiumViewer/CustomScrollControl.cs b/PdfiumViewer/CustomScrollControl.cs index 3f77320f..285fd046 100644 --- a/PdfiumViewer/CustomScrollControl.cs +++ b/PdfiumViewer/CustomScrollControl.cs @@ -15,6 +15,8 @@ public class CustomScrollControl : Control { private Size _displaySize; private Rectangle _displayRect; + private double _displayRect_X; // Patch: Repeated magnification causes the display position to shift due to rounding error. + private double _displayRect_Y; // Patch: Same as Above private readonly ScrollProperties _verticalScroll; private readonly ScrollProperties _horizontalScroll; @@ -244,12 +246,12 @@ public void SetDisplayRectLocation(Point offset, bool preserveContents) SyncScrollbars(); } - private void SetDisplayRectLocation(int x, int y) + private void SetDisplayRectLocation(double x, double y) { SetDisplayRectLocation(x, y, true); } - private void SetDisplayRectLocation(int x, int y, bool preserveContents) + private void SetDisplayRectLocation(double x, double y, bool preserveContents) { int xDelta = 0; int yDelta = 0; @@ -269,12 +271,14 @@ private void SetDisplayRectLocation(int x, int y, bool preserveContents) y = minY; if (displayRectangle.X != x) - xDelta = x - displayRectangle.X; + xDelta = (int)(x - _displayRect_X); if (displayRectangle.Y != y) - yDelta = y - displayRectangle.Y; + yDelta = (int)(y - _displayRect_Y); - _displayRect.X = x; - _displayRect.Y = y; + _displayRect_X = x; + _displayRect_Y = y; + _displayRect.X = (int)x; + _displayRect.Y = (int)y; if ((xDelta != 0 || yDelta != 0) && IsHandleCreated && preserveContents) { @@ -322,8 +326,8 @@ private bool SetVisibleScrollbars(bool horiz, bool vert) if (needLayout) { - int x = _displayRect.X; - int y = _displayRect.Y; + double x = _displayRect_X; + double y = _displayRect_Y; if (!horiz) x = 0; @@ -373,8 +377,8 @@ private bool SetDisplayRectangleSize(int width, int height) if (minY > 0) minY = 0; - int x = (int)(_displayRect.X * hScale); - int y = (int)(_displayRect.Y * vScale); + double x = (_displayRect_X * hScale); + double y = (_displayRect_Y * vScale); if (!HScroll || x > 0) x = 0; From dec15cdbdfa2933296549281a77db22d4add65e6 Mon Sep 17 00:00:00 2001 From: wiera987 <50268838+wiera987@users.noreply.github.com> Date: Thu, 26 Dec 2024 22:56:44 +0900 Subject: [PATCH 26/39] Patch: Repeated magnification causes the display position to shift due to rounding error. --- PdfiumViewer/CustomScrollControl.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/PdfiumViewer/CustomScrollControl.cs b/PdfiumViewer/CustomScrollControl.cs index 73e4adae..285fd046 100644 --- a/PdfiumViewer/CustomScrollControl.cs +++ b/PdfiumViewer/CustomScrollControl.cs @@ -256,8 +256,6 @@ private void SetDisplayRectLocation(double x, double y, bool preserveContents) int xDelta = 0; int yDelta = 0; - Console.WriteLine("SetDisplayRectLocation({0},{1},{2})={3}", x, y, preserveContents, _displayRect); - var client = ClientRectangle; var displayRectangle = _displayRect; int minX = Math.Min(client.Width - displayRectangle.Width, 0); From bc73f92ef9a427bfa67d26379b481532c657dbba Mon Sep 17 00:00:00 2001 From: wiera987 <50268838+wiera987@users.noreply.github.com> Date: Sat, 4 Jan 2025 21:19:42 +0900 Subject: [PATCH 27/39] Build bookmark tree even when bookmark panel is hidden. Get the start page and end page of the selected bookmark node. Checks if the specified page has any markers. --- PdfiumViewer/PdfRenderer.cs | 30 ++++++++++++++++++ PdfiumViewer/PdfViewer.cs | 63 ++++++++++++++++++++++++++++++++++--- 2 files changed, 88 insertions(+), 5 deletions(-) diff --git a/PdfiumViewer/PdfRenderer.cs b/PdfiumViewer/PdfRenderer.cs index 7bf75187..30b7a5f6 100644 --- a/PdfiumViewer/PdfRenderer.cs +++ b/PdfiumViewer/PdfRenderer.cs @@ -1528,6 +1528,36 @@ private void DrawMarkers(Graphics graphics, int page) } } + /// + /// Checks if the specified page has any markers. + /// + /// The page number to check for markers. + /// True if the page has markers, otherwise false. + public bool HasMarkers(int page) + { + foreach (var marker in Markers) + { + if (marker.Page != page) + continue; + + if (_compareBounds.IsEmpty) + { + // If compareBounds is not specified, the marker must exist. + return true; + } + else + { + // If compareBounds is specified, the marker is within the bounds. + var pdfmarker = (PdfMarker)marker; + if (_compareBounds.Contains(pdfmarker.Bounds)) + { + return true; + } + } + } + return false; + } + /// /// Scroll the PDF bounds into view. /// diff --git a/PdfiumViewer/PdfViewer.cs b/PdfiumViewer/PdfViewer.cs index 79722c1d..e4ca3b22 100644 --- a/PdfiumViewer/PdfViewer.cs +++ b/PdfiumViewer/PdfViewer.cs @@ -139,11 +139,9 @@ private void UpdateBookmarks(bool construct = false) _container.Panel1Collapsed = !visible; - if (visible) + if (visible || construct) { - _container.Panel1Collapsed = false; - - if ((_bookmarks.Nodes.Count == 0) || (construct)) + if ((_bookmarks.Nodes.Count == 0) || construct) { _bookmarks.Nodes.Clear(); foreach (var bookmark in _document.Bookmarks) @@ -219,6 +217,61 @@ private void GetPageNode(int page, TreeNodeCollection nodes, bool expand, ref Tr } } + /// + /// Get the start page and end page of the selected bookmark node. + /// + /// Tuple containing the start page and end page of the current bookmark node. + public void GetBookmarkPageRange(out int startPage, out int endPage) + { + if (_bookmarks.SelectedNode != null) + { + TreeNode currentNode = _bookmarks.SelectedNode; + PdfBookmark currentBookmark = (PdfBookmark)currentNode.Tag; + startPage = currentBookmark.PageIndex; + + TreeNode endNode = GetEndNode(currentNode); + if (endNode != null) + { + // When the node after the current node is found. + PdfBookmark endBookmark = (PdfBookmark)endNode.Tag; + endPage = endBookmark.PageIndex - 1; + } + else + { + // If there is no node, it is the last page. + endPage = _document.PageCount - 1; + } + } + else + { + startPage = -1; + endPage = -1; + } + //Console.WriteLine("GetBookmarkPageRange(): {0} - {1}", startPage, endPage); + } + + + /// + /// Get the end node of the current bookmark node. + /// When the end node at the same level cannot be found, recursively search for the parent node. + /// + /// + /// + private TreeNode GetEndNode(TreeNode currentNode) + { + if (currentNode.NextNode != null) + { + return currentNode.NextNode; + } + else if (currentNode.Parent != null) + { + return GetEndNode(currentNode.Parent); + } + else + { + return null; + } + } /// /// Initializes a new instance of the PdfViewer class. @@ -460,7 +513,7 @@ private void CollapseChildrenNodes(TreeNodeCollection nodes) private void EnsureVisibleWithoutRightScrolling(TreeNode node) { // we do the standard call.. - node.EnsureVisible(); + node?.EnsureVisible(); // ..and afterwards we scroll to the left again! SendMessage(_bookmarks.Handle, WM_HSCROLL, SB_LEFT, 0); From fb0f3ecf15714507b5ad1a67e6e9f81a39ae42d6 Mon Sep 17 00:00:00 2001 From: wiera987 <50268838+wiera987@users.noreply.github.com> Date: Sun, 5 Jan 2025 13:01:30 +0900 Subject: [PATCH 28/39] Fixed that the bookmark page range is an invalid value for pages that do not have a bookmark assigned. --- PdfiumViewer/PdfViewer.cs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/PdfiumViewer/PdfViewer.cs b/PdfiumViewer/PdfViewer.cs index e4ca3b22..a6a93e40 100644 --- a/PdfiumViewer/PdfViewer.cs +++ b/PdfiumViewer/PdfViewer.cs @@ -221,7 +221,7 @@ private void GetPageNode(int page, TreeNodeCollection nodes, bool expand, ref Tr /// Get the start page and end page of the selected bookmark node. /// /// Tuple containing the start page and end page of the current bookmark node. - public void GetBookmarkPageRange(out int startPage, out int endPage) + public void GetBookmarkPageRange(int page, out int startPage, out int endPage) { if (_bookmarks.SelectedNode != null) { @@ -241,6 +241,13 @@ public void GetBookmarkPageRange(out int startPage, out int endPage) // If there is no node, it is the last page. endPage = _document.PageCount - 1; } + + if ((page < startPage) || (page > endPage)) + { + // In case the target page lacks an assigned bookmark. + startPage = -1; + endPage = -1; + } } else { From 97f58bcc01d1fd90a2999a371c3b913093663b17 Mon Sep 17 00:00:00 2001 From: wiera987 <50268838+wiera987@users.noreply.github.com> Date: Fri, 10 Jan 2025 22:25:53 +0900 Subject: [PATCH 29/39] Fixed an issue where text could not be selected correctly when rotated 90 degrees and 270 degrees. --- PdfiumViewer/PdfRenderer.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/PdfiumViewer/PdfRenderer.cs b/PdfiumViewer/PdfRenderer.cs index 30b7a5f6..f773d49a 100644 --- a/PdfiumViewer/PdfRenderer.cs +++ b/PdfiumViewer/PdfRenderer.cs @@ -541,14 +541,14 @@ private PointF TranslatePointToPdf(Size size, SizeF pageSize, Point point) switch (Rotation) { case PdfRotation.Rotate90: - point = new Point(size.Height - point.Y, point.X); + point = new Point(point.Y, size.Width - point.X); size = new Size(size.Height, size.Width); break; case PdfRotation.Rotate180: point = new Point(size.Width - point.X, size.Height - point.Y); break; case PdfRotation.Rotate270: - point = new Point(point.Y, size.Width - point.X); + point = new Point(size.Height - point.Y, point.X); size = new Size(size.Height, size.Width); break; } From 68564311f71b6b7eca58df19cc1d24a82af91f56 Mon Sep 17 00:00:00 2001 From: wiera987 <50268838+wiera987@users.noreply.github.com> Date: Sat, 15 Feb 2025 12:00:08 +0900 Subject: [PATCH 30/39] Change: Disable assembly signing due to requirement for administrator privileges. --- PdfiumViewer/Key.snk | Bin 596 -> 0 bytes PdfiumViewer/PdfiumViewer.csproj | 6 +++--- 2 files changed, 3 insertions(+), 3 deletions(-) delete mode 100644 PdfiumViewer/Key.snk diff --git a/PdfiumViewer/Key.snk b/PdfiumViewer/Key.snk deleted file mode 100644 index 7526af7afd535d4847c680ff6f5e077fba58a84c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 596 zcmV-a0;~N80ssI2Bme+XQ$aES1ONa50096QrnSs1i38PkTv>4oYaI@PTOBa_TEm>| z&L4;*_Irf9JIboWQawE;6>rkWHQPsFuMoQK&xnNq%8P3dA2MAW6cPkp<_TJ&V`Dm_ z7CoFLH$V1E&r_zd>yNllpWH9rbEgO-Nx-j+RLt_mK0zjCZ) z|IWw=!IQclysFIVDPBIBC$1?)Y2kU&2!dobR&aR;2DCOj9C;{eF(F6q#jrUJLRmaJ zi~PgY)>$N}PgUWiLibA~oR~q1V!bcTrA(_G1uYl}f51FFyx$di0n&K@>jQNu0zB^+b$P|Y3G8js#${qTZhf=dE|fod9-gbBlcl@eZTwg`2@vho zlrOW|`4P7Xc^tY8I--EdmiR80{SBh}Z!Z4u2bDHT8f)+A> zQbm9@Yq?ipAHHM{G+*NCI8ixJ;&%?G@>0~Ful5CsDql|`fWM`VSdKdVxQ%Th|0h4H zeK;L(jnKDF{cfS}3urytJWFDKlA$(y8r`~FISMSktWgnP&g5F!ZFuLT<* iq{f?`-U39rL2?ay?1USDwuiHmDlYINvJ4NnWWh`D6d0NS diff --git a/PdfiumViewer/PdfiumViewer.csproj b/PdfiumViewer/PdfiumViewer.csproj index 83e95046..8acb3cb1 100644 --- a/PdfiumViewer/PdfiumViewer.csproj +++ b/PdfiumViewer/PdfiumViewer.csproj @@ -14,10 +14,11 @@ 512 - true + false - Key.snk + + true @@ -119,7 +120,6 @@ - From 5f733b77d4bbbceefb12f4bcc98f98a1b011951c Mon Sep 17 00:00:00 2001 From: wiera987 <50268838+wiera987@users.noreply.github.com> Date: Sat, 22 Mar 2025 16:01:45 +0900 Subject: [PATCH 31/39] Change: Add a feature to flash the specified range of TextSpans. --- PdfiumViewer/PdfRenderer.cs | 142 ++++++++++++++++++++++++++++++++++++ 1 file changed, 142 insertions(+) diff --git a/PdfiumViewer/PdfRenderer.cs b/PdfiumViewer/PdfRenderer.cs index f773d49a..ace6482a 100644 --- a/PdfiumViewer/PdfRenderer.cs +++ b/PdfiumViewer/PdfRenderer.cs @@ -1,4 +1,5 @@ using System; +using System.Collections; using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics; @@ -19,6 +20,8 @@ public class PdfRenderer : PanningZoomingScrollControl private static readonly double _textToleranceY = 8.0; private static readonly Padding PageMargin = new Padding(4); private static readonly SolidBrush _textSelectionBrush = new SolidBrush(Color.FromArgb(90, Color.DodgerBlue)); + private static readonly int _flashColorAlpha = 100; + private static readonly Color _flashColor = Color.Orange; private int _maxWidth; private int _maxHeight; @@ -37,6 +40,7 @@ public class PdfRenderer : PanningZoomingScrollControl private DragState _dragState; private PdfRotation _rotation; private List[] _markers; + private List _flashTextSpans = null; private PdfCursorMode _cursorMode = PdfCursorMode.Pan; private bool _isSelectingText = false; private MouseState _cachedMouseState = null; @@ -44,6 +48,9 @@ public class PdfRenderer : PanningZoomingScrollControl private RectangleF _compareBounds = Rectangle.Empty; private Point zoomLocation; private PdfPoint zoomPdfLocation; + private int tempFlashTextAlpha = 0; + + public int FlashTextAlpha = 0; /// /// The associated PDF document. @@ -727,6 +734,7 @@ private void ReloadDocument() _documentScaleFactor = _maxHeight != 0 ? (double)_maxWidth / _maxHeight : 0D; _markers = null; + _flashTextSpans = null; UpdateScrollbars(); @@ -960,6 +968,12 @@ protected override void OnPaint(PaintEventArgs e) _shadeBorder.Draw(e.Graphics, pageBounds); + if ((_flashTextSpans != null) & (FlashTextAlpha > 0)) + { + //DrawTextSpans(e.Graphics, _flashTextSpans, tempFlashTextAlpha); + DrawTextRectangle(e.Graphics, _flashTextSpans, tempFlashTextAlpha); + } + DrawMarkers(e.Graphics, page); DrawCompareBounds(e.Graphics, page); @@ -1022,6 +1036,111 @@ private void DrawTextSelection(Graphics graphics, int page, TextSelectionState s } } + /// + /// Draws the specified text spans with a border. + /// + /// The graphics to draw on. + /// The text spans to draw. + public void DrawTextSpans(Graphics graphics, IList textSpans, int alpha) + { + if (textSpans == null || textSpans.Count == 0) + return; + + foreach (var textSpan in textSpans) + { + if (textSpan.Page < 0 || textSpan.Page >= _pageCache.Count) + continue; + + var pageCache = _pageCache[textSpan.Page]; + if (pageCache == null) + continue; + + Region region = null; + foreach (var rectangle in Document.GetTextBounds(textSpan)) + { + if (region == null) + region = new Region(BoundsFromPdf(rectangle)); + else + region.Union(BoundsFromPdf(rectangle)); + } + + if (region != null) + { + Color customColor = Color.FromArgb(alpha, _flashColor); + SolidBrush customBrush = new SolidBrush(customColor); + graphics.FillRegion(customBrush, region); + } + } + } + + /// + /// Draws the specified text spans with a border. + /// + /// The graphics to draw on. + /// The text spans to draw. + public void DrawTextRectangle(Graphics graphics, IList textSpans, int alpha) + { + if (textSpans == null || textSpans.Count == 0) + return; + + Rectangle frame = new Rectangle(); + + foreach (var textSpan in textSpans) + { + if (textSpan.Page < 0 || textSpan.Page >= _pageCache.Count) + continue; + + var pageCache = _pageCache[textSpan.Page]; + if (pageCache == null) + continue; + + foreach (var rectangle in Document.GetTextBounds(textSpan)) + { + Rectangle rect2 = BoundsFromPdf(rectangle); + + if (!rect2.Size.IsEmpty) + { + if (frame.IsEmpty) + { + frame = rect2; + } + else + { + frame = GetEnclosingRectangle(frame, rect2); + } + } + } + } + + if (!frame.Size.IsEmpty) + { + Color customColor = Color.FromArgb(alpha, _flashColor); + Pen customPen = new Pen(customColor,5); + + graphics.DrawRectangle(customPen, frame); + + + } + + } + + Rectangle GetEnclosingRectangle(Rectangle rect1, Rectangle rect2) + { + // Find the minimum x and y coordinates + int minX = Math.Min(rect1.Left, rect2.Left); + int minY = Math.Min(rect1.Top, rect2.Top); + + // Find the maximum x and y coordinates + int maxX = Math.Max(rect1.Right, rect2.Right); + int maxY = Math.Max(rect1.Bottom, rect2.Bottom); + + // Calculate width and height + int width = maxX - minX; + int height = maxY - minY; + + return new Rectangle(minX, minY, width, height); + } + private void DrawPageImage(Graphics graphics, int page, Rectangle pageBounds) { var pageCache = _pageCache[page]; @@ -1625,6 +1744,29 @@ protected override void Dispose(bool disposing) base.Dispose(disposing); } + public void SetFlashTextSpans(List index1) + { + _flashTextSpans = new List(index1); + FlashTextAlpha = _flashColorAlpha; + tempFlashTextAlpha = FlashTextAlpha; + } + + public void CalcFlashTextAlpha() + { + int step = 10; + + //tempFlashTextAlpha -= (FlashTextAlpha + step - 1) / step; + //tempFlashTextAlpha -= (FlashTextAlpha - tempFlashTextAlpha)*3/2 + 1; + tempFlashTextAlpha -= (FlashTextAlpha - tempFlashTextAlpha)*3/4 + 1; + if (tempFlashTextAlpha <= 0) + { + tempFlashTextAlpha = 0; + FlashTextAlpha = 0; // Stop flash animation. + } + //Console.WriteLine("FlashTextAlpha={0}, tempFlashTextAlpha={1}", FlashTextAlpha, tempFlashTextAlpha); + Invalidate(); + } + private class PageCache { public List Links { get; set; } From cff5a3e373494e9a7fa49a230647b3def72c81bb Mon Sep 17 00:00:00 2001 From: wiera987 <50268838+wiera987@users.noreply.github.com> Date: Thu, 1 Jan 2026 11:21:07 +0900 Subject: [PATCH 32/39] Add a feature to flash the TextSpan area using DrawTextOutline(). --- PdfiumViewer/PdfRenderer.cs | 132 +++++++++++++++++++++++++++++++----- 1 file changed, 114 insertions(+), 18 deletions(-) diff --git a/PdfiumViewer/PdfRenderer.cs b/PdfiumViewer/PdfRenderer.cs index ace6482a..0fcd0f5c 100644 --- a/PdfiumViewer/PdfRenderer.cs +++ b/PdfiumViewer/PdfRenderer.cs @@ -971,7 +971,7 @@ protected override void OnPaint(PaintEventArgs e) if ((_flashTextSpans != null) & (FlashTextAlpha > 0)) { //DrawTextSpans(e.Graphics, _flashTextSpans, tempFlashTextAlpha); - DrawTextRectangle(e.Graphics, _flashTextSpans, tempFlashTextAlpha); + DrawTextOutline(e.Graphics, _flashTextSpans, tempFlashTextAlpha); } DrawMarkers(e.Graphics, page); @@ -1074,16 +1074,18 @@ public void DrawTextSpans(Graphics graphics, IList textSpans, int a } /// - /// Draws the specified text spans with a border. + /// Draws the outer outline of the specified text spans. + /// First and last lines are drawn individually, middle lines are merged into one rectangle. + /// Vertical lines are aligned to the outermost X coordinates. /// /// The graphics to draw on. /// The text spans to draw. - public void DrawTextRectangle(Graphics graphics, IList textSpans, int alpha) + public void DrawTextOutline(Graphics graphics, IList textSpans, int alpha) { if (textSpans == null || textSpans.Count == 0) return; - Rectangle frame = new Rectangle(); + List allRectangles = new List(); foreach (var textSpan in textSpans) { @@ -1100,31 +1102,125 @@ public void DrawTextRectangle(Graphics graphics, IList textSpans, i if (!rect2.Size.IsEmpty) { - if (frame.IsEmpty) - { - frame = rect2; - } - else - { - frame = GetEnclosingRectangle(frame, rect2); - } + allRectangles.Add(rect2); } } } - if (!frame.Size.IsEmpty) + if (allRectangles.Count == 0) + return; + + Color customColor = Color.FromArgb(alpha, _flashColor); + Pen customPen = new Pen(customColor, 5); + // Sort by the Top value. + allRectangles.Sort((a, b) => a.Top.CompareTo(b.Top)); + + if (allRectangles.Count == 1) + { + // Only one rectangle: draw outer outline + DrawRectangleOutline(graphics, customPen, allRectangles[0]); + } + else if (allRectangles.Count == 2) + { + if (allRectangles[0].Bottom > allRectangles[1].Top) + { + // One row + Rectangle mergedMiddle = GetEnclosingRectangle(allRectangles[0], allRectangles[1]); + DrawRectangleOutline(graphics, customPen, mergedMiddle); + } + else + { + // Two row: draw outer outline of both + DrawTwoRectanglesOutline(graphics, customPen, allRectangles[0], allRectangles[1]); + } + } + else { - Color customColor = Color.FromArgb(alpha, _flashColor); - Pen customPen = new Pen(customColor,5); + // Three or more rectangles: draw first, merged middle, and last + Rectangle mergedMiddle = allRectangles[1]; + for (int i = 2; i < allRectangles.Count - 1; i++) + { + mergedMiddle = GetEnclosingRectangle(mergedMiddle, allRectangles[i]); + } + + DrawMultipleRectanglesOutline(graphics, customPen, allRectangles[0], mergedMiddle, allRectangles[allRectangles.Count - 1]); + } - graphics.DrawRectangle(customPen, frame); + customPen.Dispose(); + } + /// + /// Draw outer outline of a single rectangle. + /// + private void DrawRectangleOutline(Graphics graphics, Pen pen, Rectangle rect) + { + graphics.DrawRectangle(pen, rect); + } - } + /// + /// Draw outer outline of two rectangles with vertical lines aligned to outermost X coordinates. + /// + private void DrawTwoRectanglesOutline(Graphics graphics, Pen pen, Rectangle first, Rectangle last) + { + // Direction is /L2R(Left‑to‑Right) + // 1------2 + // 7--8 4--3 + // 6------5 + + // Line 1-2 + graphics.DrawLine(pen, first.Left, first.Top, first.Right, first.Top); + // Line 2-3 + graphics.DrawLine(pen, first.Right, first.Top, first.Right, last.Top); + // Line 3-4 + graphics.DrawLine(pen, first.Right, last.Top, last.Right, last.Top); + // Line 4-5 + graphics.DrawLine(pen, last.Right, last.Top, last.Right, last.Bottom); + // Line 5-6 + graphics.DrawLine(pen, last.Right, last.Bottom, last.Left, last.Bottom); + // Line 6-7 + graphics.DrawLine(pen, last.Left, last.Bottom, last.Left, last.Top); + // Line 7-8 + graphics.DrawLine(pen, last.Left, last.Top, first.Left, last.Top); + // Line 8-1 + graphics.DrawLine(pen, first.Left, last.Top, first.Left, first.Top); } - Rectangle GetEnclosingRectangle(Rectangle rect1, Rectangle rect2) + /// + /// Draw outer outline of three rectangles (first, merged middle, last) with vertical lines aligned to outermost X coordinates. + /// Vertical lines only extend from first.Top to middle.Bottom on the left/right edges. + /// + private void DrawMultipleRectanglesOutline(Graphics graphics, Pen pen, Rectangle first, Rectangle middle, Rectangle last) + { + // Direction is /L2R(Left‑to‑Right) + // 1------2 + // 7--8 | + // | | + // | 4--3 + // 6------5 + + int minX = Math.Min(first.Left, Math.Min(middle.Left, last.Left)); + int maxX = Math.Max(first.Right, Math.Max(middle.Right, last.Right)); + + // Line 1-2 + graphics.DrawLine(pen, first.Left, first.Top, maxX, first.Top); + // Line 2-3 + graphics.DrawLine(pen, maxX, first.Top, maxX, middle.Bottom); + // Line 3-4 + graphics.DrawLine(pen, maxX, middle.Bottom, last.Right, middle.Bottom); + // Line 4-5 + graphics.DrawLine(pen, last.Right, middle.Bottom, last.Right, last.Bottom); + // Line 5-6 + graphics.DrawLine(pen, last.Right, last.Bottom, minX, last.Bottom); + // Line 6-7 + graphics.DrawLine(pen, minX, last.Bottom, minX, middle.Top); + // Line 7-8 + graphics.DrawLine(pen, minX, middle.Top, first.Left, middle.Top); + // Line 8-1 + graphics.DrawLine(pen, first.Left, middle.Top, first.Left, first.Top); + } + + private Rectangle GetEnclosingRectangle(Rectangle rect1, Rectangle rect2) { // Find the minimum x and y coordinates int minX = Math.Min(rect1.Left, rect2.Left); From 73c4f2eee1996f2a779b47d3d3dc128d600701c7 Mon Sep 17 00:00:00 2001 From: wiera987 <50268838+wiera987@users.noreply.github.com> Date: Thu, 1 Jan 2026 16:18:52 +0900 Subject: [PATCH 33/39] Clarify custom version for PDFComp in README Add a note indicating this is a custom version for PDFComp. --- README.markdown | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.markdown b/README.markdown index 3981de63..ab6b19b2 100644 --- a/README.markdown +++ b/README.markdown @@ -1,5 +1,7 @@ # PdfiumViewer +This PdfiumViewer is a custom version for PDFComp. + Apache 2.0 License. [Download from NuGet](http://nuget.org/packages/PdfiumViewer). From 95c2553a6f3137dd3d6b4af4385f145c8ec4c90b Mon Sep 17 00:00:00 2001 From: wiera987 <50268838+wiera987@users.noreply.github.com> Date: Thu, 1 Jan 2026 16:38:15 +0900 Subject: [PATCH 34/39] Add note about custom PdfiumViewer version --- README.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.markdown b/README.markdown index ab6b19b2..6ea39e86 100644 --- a/README.markdown +++ b/README.markdown @@ -1,6 +1,6 @@ # PdfiumViewer -This PdfiumViewer is a custom version for PDFComp. +**⚠️ Note:** This PdfiumViewer is a custom version for PDFComp. Apache 2.0 License. From 66030a79cf94e218b7afc09b55e2c0320b5220e6 Mon Sep 17 00:00:00 2001 From: wiera987 <50268838+wiera987@users.noreply.github.com> Date: Fri, 2 Jan 2026 21:16:44 +0900 Subject: [PATCH 35/39] Fixed: Corrected broken TextSpan outline when using DrawTwoRectanglesOutline(). --- PdfiumViewer/PdfRenderer.cs | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/PdfiumViewer/PdfRenderer.cs b/PdfiumViewer/PdfRenderer.cs index 0fcd0f5c..79f84654 100644 --- a/PdfiumViewer/PdfRenderer.cs +++ b/PdfiumViewer/PdfRenderer.cs @@ -1167,20 +1167,23 @@ private void DrawTwoRectanglesOutline(Graphics graphics, Pen pen, Rectangle firs // 7--8 4--3 // 6------5 + int minX = Math.Min(first.Left, last.Left); + int maxX = Math.Max(first.Right, last.Right); + // Line 1-2 - graphics.DrawLine(pen, first.Left, first.Top, first.Right, first.Top); + graphics.DrawLine(pen, first.Left, first.Top, maxX, first.Top); // Line 2-3 - graphics.DrawLine(pen, first.Right, first.Top, first.Right, last.Top); + graphics.DrawLine(pen, maxX, first.Top, maxX, last.Top); // Line 3-4 - graphics.DrawLine(pen, first.Right, last.Top, last.Right, last.Top); + graphics.DrawLine(pen, maxX, last.Top, last.Right, last.Top); // Line 4-5 graphics.DrawLine(pen, last.Right, last.Top, last.Right, last.Bottom); // Line 5-6 - graphics.DrawLine(pen, last.Right, last.Bottom, last.Left, last.Bottom); + graphics.DrawLine(pen, last.Right, last.Bottom, minX, last.Bottom); // Line 6-7 - graphics.DrawLine(pen, last.Left, last.Bottom, last.Left, last.Top); + graphics.DrawLine(pen, minX, last.Bottom, minX, last.Top); // Line 7-8 - graphics.DrawLine(pen, last.Left, last.Top, first.Left, last.Top); + graphics.DrawLine(pen, minX, last.Top, first.Left, last.Top); // Line 8-1 graphics.DrawLine(pen, first.Left, last.Top, first.Left, first.Top); From 6a6075aabed240b1a8d3e4e424219415c8c07b2a Mon Sep 17 00:00:00 2001 From: wiera987 <50268838+wiera987@users.noreply.github.com> Date: Sat, 3 Jan 2026 17:42:42 +0900 Subject: [PATCH 36/39] If no bookmark is selected, return an undefined range determined by the current page number. --- PdfiumViewer/PdfViewer.cs | 114 +++++++++++++++++++++++++++++--------- 1 file changed, 87 insertions(+), 27 deletions(-) diff --git a/PdfiumViewer/PdfViewer.cs b/PdfiumViewer/PdfViewer.cs index a6a93e40..970a31a8 100644 --- a/PdfiumViewer/PdfViewer.cs +++ b/PdfiumViewer/PdfViewer.cs @@ -170,13 +170,14 @@ public void SelectBookmarkForPage(int page) GetPageNode(page, _bookmarks.Nodes, false, ref validNode); // Select the last valid Node. - if (validNode != null) + if (validNode == null) { - preventPageRefresh = true; - _bookmarks.SelectedNode = validNode; - preventPageRefresh = false; - bookmarkPage = page; + page = -1; } + preventPageRefresh = true; + _bookmarks.SelectedNode = validNode; + preventPageRefresh = false; + bookmarkPage = page; } //Console.WriteLine("SelectBookmarkForPage: Page={0}!={1}, Text={2}", page, bmpage, validNode?.Text); } @@ -218,45 +219,104 @@ private void GetPageNode(int page, TreeNodeCollection nodes, bool expand, ref Tr } /// - /// Get the start page and end page of the selected bookmark node. + /// Get the start page and end page of the selected/unselected bookmark node. /// /// Tuple containing the start page and end page of the current bookmark node. public void GetBookmarkPageRange(int page, out int startPage, out int endPage) { if (_bookmarks.SelectedNode != null) { - TreeNode currentNode = _bookmarks.SelectedNode; - PdfBookmark currentBookmark = (PdfBookmark)currentNode.Tag; - startPage = currentBookmark.PageIndex; + GetSelectedBookmarkPageRange(page, out startPage, out endPage); + } + else + { + GetUnselectedBookmarkPageRange(page, out startPage, out endPage); + } + // Console.WriteLine("GetBookmarkPageRange(): {0} - {1}", startPage, endPage); + } + + private void GetSelectedBookmarkPageRange(int page, out int startPage, out int endPage) + { + TreeNode currentNode = _bookmarks.SelectedNode; + PdfBookmark currentBookmark = (PdfBookmark)currentNode.Tag; + startPage = currentBookmark.PageIndex; + + TreeNode endNode = GetEndNode(currentNode); + if (endNode != null) + { + // When the node after the current node is found. + PdfBookmark endBookmark = (PdfBookmark)endNode.Tag; + endPage = endBookmark.PageIndex - 1; + } + else + { + // If there is no node, it is the last page. + endPage = _document.PageCount - 1; + } + + if ((page < startPage) || (page > endPage)) + { + // In case the target page lacks an assigned bookmark. + startPage = -1; + endPage = -1; + } + } + + + private void GetUnselectedBookmarkPageRange(int page, out int startPage, out int endPage) + { + // No node selected: return the top-level (first-level) bookmark range that contains 'page'. + if (_document == null) + { + startPage = -1; + endPage = -1; + return; + } + else + { + startPage = 0; + endPage = _document.PageCount - 1; + } - TreeNode endNode = GetEndNode(currentNode); - if (endNode != null) + TreeNode candidate = null; + int candidateStart = 0; + + // a. Before the range defined by the bookmarks + // b. Gap within the range defined by the bookmarks + // c. After the range defined by the bookmarks + + // Find the last top-level bookmark whose PageIndex <= page + foreach (TreeNode node in _bookmarks.Nodes) + { + PdfBookmark bm = (PdfBookmark)node.Tag; + if (bm.PageIndex <= page) { - // When the node after the current node is found. - PdfBookmark endBookmark = (PdfBookmark)endNode.Tag; - endPage = endBookmark.PageIndex - 1; + candidate = node; + candidateStart = bm.PageIndex; } else { - // If there is no node, it is the last page. - endPage = _document.PageCount - 1; + endPage = bm.PageIndex-1; + break; } + } - if ((page < startPage) || (page > endPage)) + if (candidate != null) + { + // If there is a next node, it will be PageIndex -1, if not it will be the last page. + startPage = candidateStart; + if (candidate.NextNode != null) { - // In case the target page lacks an assigned bookmark. - startPage = -1; - endPage = -1; + endPage = ((PdfBookmark)candidate.NextNode.Tag).PageIndex - 1; + } + else + { + endPage = _document.PageCount - 1; } } - else - { - startPage = -1; - endPage = -1; - } - //Console.WriteLine("GetBookmarkPageRange(): {0} - {1}", startPage, endPage); - } + return; + } /// /// Get the end node of the current bookmark node. From 652a636cee3f0ac96844429da90051df98a589b1 Mon Sep 17 00:00:00 2001 From: alxnull Date: Sun, 6 Sep 2020 22:58:11 +0200 Subject: [PATCH 37/39] Upgrade to newer pdfium build from https://github.com/bblanchon/pdfium-binaries. # resolved: # PdfiumViewer/PdfFile.cs --- PdfiumViewer.Demo/MainForm.cs | 20 +++--------- PdfiumViewer.Demo/PdfiumViewer.Demo.csproj | 8 ++--- PdfiumViewer.Demo/packages.config | 4 +-- PdfiumViewer/NativeMethods.Pdfium.cs | 37 ++++++++++++++++------ PdfiumViewer/PdfFile.cs | 9 ++++-- PdfiumViewer/PdfLibrary.cs | 9 ++++-- PdfiumViewer/PdfRenderer.cs | 2 +- 7 files changed, 53 insertions(+), 36 deletions(-) diff --git a/PdfiumViewer.Demo/MainForm.cs b/PdfiumViewer.Demo/MainForm.cs index 93eaecc9..c0a39649 100644 --- a/PdfiumViewer.Demo/MainForm.cs +++ b/PdfiumViewer.Demo/MainForm.cs @@ -280,15 +280,9 @@ private void _hideBookmarks_Click(object sender, EventArgs e) private void deleteCurrentPageToolStripMenuItem_Click(object sender, EventArgs e) { - // PdfRenderer does not support changes to the loaded document, - // so we fake it by reloading the document into the renderer. - int page = pdfViewer1.Renderer.Page; - var document = pdfViewer1.Document; - pdfViewer1.Document = null; - document.DeletePage(page); - pdfViewer1.Document = document; - pdfViewer1.Renderer.Page = page; + pdfViewer1.Document.DeletePage(page); + pdfViewer1.Renderer.ReloadDocument(); } private void rotate0ToolStripMenuItem_Click(object sender, EventArgs e) @@ -313,15 +307,9 @@ private void rotate270ToolStripMenuItem_Click(object sender, EventArgs e) private void Rotate(PdfRotation rotate) { - // PdfRenderer does not support changes to the loaded document, - // so we fake it by reloading the document into the renderer. - int page = pdfViewer1.Renderer.Page; - var document = pdfViewer1.Document; - pdfViewer1.Document = null; - document.RotatePage(page, rotate); - pdfViewer1.Document = document; - pdfViewer1.Renderer.Page = page; + pdfViewer1.Document.RotatePage(page, rotate); + pdfViewer1.Renderer.ReloadDocument(); } private void showRangeOfPagesToolStripMenuItem_Click(object sender, EventArgs e) diff --git a/PdfiumViewer.Demo/PdfiumViewer.Demo.csproj b/PdfiumViewer.Demo/PdfiumViewer.Demo.csproj index 54f680ee..443da779 100644 --- a/PdfiumViewer.Demo/PdfiumViewer.Demo.csproj +++ b/PdfiumViewer.Demo/PdfiumViewer.Demo.csproj @@ -1,7 +1,7 @@  - - + + Debug x86 @@ -160,8 +160,8 @@ This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - + +