Skip to content
This repository has been archived by the owner on Aug 2, 2019. It is now read-only.

Support text selection #172

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 40 additions & 8 deletions PdfiumViewer.Demo/MainForm.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

17 changes: 17 additions & 0 deletions PdfiumViewer.Demo/MainForm.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ public MainForm()

renderToBitmapsToolStripMenuItem.Enabled = false;

pdfViewer1.Renderer.ContextMenuStrip = pdfViewerContextMenu;

pdfViewer1.Renderer.DisplayRectangleChanged += Renderer_DisplayRectangleChanged;
pdfViewer1.Renderer.ZoomChanged += Renderer_ZoomChanged;

Expand Down Expand Up @@ -378,5 +380,20 @@ private void printMultiplePagesToolStripMenuItem_Click(object sender, EventArgs
form.ShowDialog(this);
}
}

private void copyToolStripMenuItem_Click(object sender, EventArgs e)
{
pdfViewer1.Renderer.CopySelection();
}

private void selectAllToolStripMenuItem_Click(object sender, EventArgs e)
{
pdfViewer1.Renderer.SelectAll();
}

private void pdfViewerContextMenu_Opening(object sender, CancelEventArgs e)
{
copyToolStripMenuItem.Enabled = pdfViewer1.Renderer.IsTextSelected;
}
}
}
3 changes: 3 additions & 0 deletions PdfiumViewer.Demo/MainForm.resx
Original file line number Diff line number Diff line change
Expand Up @@ -307,4 +307,7 @@
<metadata name="statusStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>237, 17</value>
</metadata>
<metadata name="pdfViewerContextMenu.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>353, 17</value>
</metadata>
</root>
20 changes: 20 additions & 0 deletions PdfiumViewer.Demo/PdfRangeDocument.cs
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,26 @@ public Rectangle RectangleFromPdf(int page, RectangleF rect)
return _document.RectangleFromPdf(TranslatePage(page), rect);
}

public int GetCharacterIndexAtPosition(PdfPoint location, double xTolerance, double yTolerance)
{
return _document.GetCharacterIndexAtPosition(location, xTolerance, yTolerance);
}

public bool GetWordAtPosition(PdfPoint location, double xTolerance, double yTolerance, out PdfTextSpan span)
{
return _document.GetWordAtPosition(location, xTolerance, yTolerance, out span);
}

public int CountCharacters(int page)
{
return _document.CountCharacters(page);
}

public List<PdfRectangle> GetTextRectangles(int page, int startIndex, int count)
{
return _document.GetTextRectangles(page, startIndex, count);
}

private int TranslatePage(int page)
{
if (page < 0 || page >= PageCount)
Expand Down
3 changes: 2 additions & 1 deletion PdfiumViewer/CustomScrollControl.cs
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,8 @@ public override Rectangle DisplayRectangle

public CustomScrollControl()
{
SetStyle(ControlStyles.ContainerControl, true);
SetStyle(ControlStyles.Selectable, true);
SetStyle(ControlStyles.UserMouse, true);
SetStyle(ControlStyles.AllPaintingInWmPaint, false);

_horizontalScroll = new ScrollProperties(this, NativeMethods.SB_HORZ);
Expand Down
33 changes: 33 additions & 0 deletions PdfiumViewer/IPdfDocument.cs
Original file line number Diff line number Diff line change
Expand Up @@ -252,5 +252,38 @@ public interface IPdfDocument : IDisposable
/// <param name="rect">The rectangle to convert.</param>
/// <returns>The converted rectangle.</returns>
Rectangle RectangleFromPdf(int page, RectangleF rect);

/// <summary>
/// Get the character index at or nearby a specific position.
/// </summary>
/// <param name="location">The location to inspect</param>
/// <param name="xTolerance">An x-axis tolerance value for character hit detection, in point unit.</param>
/// <param name="yTolerance">A y-axis tolerance value for character hit detection, in point unit.</param>
/// <returns>The zero-based index of the character at, or nearby the point specified by parameter x and y. If there is no character at or nearby the point, it will return -1.</returns>
int GetCharacterIndexAtPosition(PdfPoint location, double xTolerance, double yTolerance);

/// <summary>
/// Get the full word at or nearby a specific position
/// </summary>
/// <param name="location">The location to inspect</param>
/// <param name="xTolerance">An x-axis tolerance value for character hit detection, in point unit.</param>
/// <param name="yTolerance">A y-axis tolerance value for character hit detection, in point unit.</param>
/// <param name="span">The location of the found word, if any</param>
/// <returns>A value indicating whether a word was found at the specified location</returns>
bool GetWordAtPosition(PdfPoint location, double xTolerance, double yTolerance, out PdfTextSpan span);

/// <summary>
/// Get number of characters in a page.
/// </summary>
/// <param name="page">The page to get the character count from</param>
/// <returns>Number of characters in the page. Generated characters, like additional space characters, new line characters, are also counted.</returns>
int CountCharacters(int page);

/// <summary>
/// Gets the rectangular areas occupied by a segment of text
/// </summary>
/// <param name="page">The page to get the rectangles from</param>
/// <returns>The rectangular areas occupied by a segment of text</returns>
List<PdfRectangle> GetTextRectangles(int page, int startIndex, int count);
}
}
58 changes: 58 additions & 0 deletions PdfiumViewer/NativeMethods.Pdfium.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Drawing;

#pragma warning disable 1591

Expand Down Expand Up @@ -290,6 +291,17 @@ public static void FPDFText_GetCharBox(IntPtr page, int index, out double left,
}
}

public static int FPDFText_GetCharIndexAtPos(IntPtr page, double x, double y, double xTolerance, double yTolerance)
{
lock (LockString)
{
var idx = Imports.FPDFText_GetCharIndexAtPos(page, x, y, xTolerance, yTolerance);
if (idx == -3)
throw new PdfException((PdfError)Imports.FPDF_GetLastError());
return idx;
}
}

public static int FPDFText_CountChars(IntPtr page)
{
lock (LockString)
Expand All @@ -298,6 +310,40 @@ public static int FPDFText_CountChars(IntPtr page)
}
}

public static List<PdfRectangle> FPDFText_GetRectangles(IntPtr page, int pageIndex, int startIndex, int characterCount)
{
lock (LockString)
{
// GetRect uses internal state set by CountRects, so we should call them within the same lock

var count = Imports.FPDFText_CountRects(page, startIndex, characterCount);
var rectangles = new List<PdfRectangle>(count);

for (int i = 0; i < count; i++)
{
if (!Imports.FPDFText_GetRect(page, i, out var left, out var top, out var right, out var bottom))
throw new PdfException((PdfError)Imports.FPDF_GetLastError());

rectangles.Add(new PdfRectangle(pageIndex, new RectangleF(
(float)left,
(float)top,
(float)(right - left),
(float)(bottom - top)
)));
}

return rectangles;
}
}

public static char FPDFText_GetUnicode(IntPtr page, int index)
{
lock (LockString)
{
return Imports.FPDFText_GetUnicode(page, index);
}
}

public static bool FPDFText_FindNext(IntPtr handle)
{
lock (LockString)
Expand Down Expand Up @@ -696,9 +742,21 @@ private static class Imports
[DllImport("pdfium.dll")]
public static extern void FPDFText_GetCharBox(IntPtr page, int index, out double left, out double right, out double bottom, out double top);

[DllImport("pdfium.dll")]
public static extern int FPDFText_GetCharIndexAtPos(IntPtr page, double x, double y, double xTolerance, double yTolerance);

[DllImport("pdfium.dll")]
public static extern int FPDFText_CountChars(IntPtr page);

[DllImport("pdfium.dll")]
public static extern int FPDFText_CountRects(IntPtr page, int startIndex, int count);

[DllImport("pdfium.dll")]
public static extern bool FPDFText_GetRect(IntPtr page, int index, out double left, out double top, out double right, out double bottom);

[DllImport("pdfium.dll", CharSet = CharSet.Unicode)]
public static extern char FPDFText_GetUnicode(IntPtr page, int index);

[DllImport("pdfium.dll")]
public static extern bool FPDFText_FindNext(IntPtr handle);

Expand Down
11 changes: 7 additions & 4 deletions PdfiumViewer/PanningZoomingScrollControl.cs
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,8 @@ public void ZoomOut()
[DefaultValue(MouseWheelMode.PanAndZoom)]
public MouseWheelMode MouseWheelMode { get; set; }

protected bool MousePanningEnabled { get; set; } = true;

/// <summary>
/// Raises the <see cref="E:System.Windows.Forms.Control.MouseWheel"/> event.
/// </summary>
Expand Down Expand Up @@ -226,7 +228,7 @@ protected override bool IsInputKey(Keys keyData)

protected override void OnSetCursor(SetCursorEventArgs e)
{
if (_canPan && e.HitTest == HitTest.Client)
if (MousePanningEnabled && _canPan && e.HitTest == HitTest.Client)
e.Cursor = PanCursor;

base.OnSetCursor(e);
Expand All @@ -243,7 +245,7 @@ protected override void OnMouseDown(MouseEventArgs e)
{
base.OnMouseDown(e);

if (e.Button != MouseButtons.Left || !_canPan)
if (!MousePanningEnabled || e.Button != MouseButtons.Left || !_canPan)
return;

Capture = true;
Expand All @@ -255,7 +257,7 @@ protected override void OnMouseMove(MouseEventArgs e)
{
base.OnMouseMove(e);

if (!Capture)
if (!MousePanningEnabled || !Capture)
return;

var offset = new Point(e.Location.X - _dragStart.X, e.Location.Y - _dragStart.Y);
Expand All @@ -267,7 +269,8 @@ protected override void OnMouseUp(MouseEventArgs e)
{
base.OnMouseUp(e);

Capture = false;
if (MousePanningEnabled)
Capture = false;
}

private class WheelFilter : IMessageFilter
Expand Down
Loading