New to Telerik UI for WinForms? Download free 30-day trial

How to Get the Context Menu's Coordinates and Draw a Rectangle in PdfViewer

Environment

Product Version Product Author
2023.2.718 RadPdfViewer for WinForms Desislava Yordanova

Problem

For a regular WinForms control painting a rectangle would be a straightforward task assuming you have calculated the coordinates. In the RadPdfViewer, however, this is more complex because the control works with a document, and any custom rendering must be applied to the document itself. This way these settings will be preserved and still available when you save or print the document. This article shows how you can get the top left location of the context menu and draw a rectangle in the WinForms PdfViewer.

draw-rectangle-in-pdf-with-context-menu

Solution

We can achieve this task with the help of the RadPdfProcessing library. The library exposes convenient APIs for creating and editing PDF documents: PdfProcessing - Overview - Telerik Document Processing. For your actual scenario it will be necessary to work with the loaded inside the UI control document and modify it with the FixedContentEditor class. We can use the editor to paint a rectangle at a desired location.

PdfProcessing - FixedContentEditor - Telerik Document Processing

PdfProcessing - Colors and Color Spaces - Telerik Document Processing

After we edit the document, we need to reload it inside the control so that the changes are reflected. This is a sample implementation of the context menu item Click event:


public partial class RadForm1 : Telerik.WinControls.UI.RadForm
{
    int paginaCurenta = 0; //the current pdf page
    float pozitiaX = 0; // the mouse down X position
    float pozitiaY = 0; // the mouse down Y position

    public RadForm1()
    {
        InitializeComponent();

        this.radPdfViewer1.LoadDocument(@"..\..\sample.pdf");

        this.radPdfViewer1.MouseDown += this.RadPdfViewer1_MouseDown;
        this.CreateContextMenu();
        this.radPdfViewer1.PdfViewerElement.Mode = FixedDocumentViewerMode.TextSelection;
    }

    private void RadPdfViewer1_MouseDown(object sender, MouseEventArgs e)
    {
        var element = this.radPdfViewer1.ElementTree.GetElementAtPoint(e.Location) as RadFixedPageElement;

        if (element != null)
        {

            var mouseLocation = e.Location;
            var tt = element.TotalTransform;
            tt.Invert();

            var pointInDoc = tt.TransformPoint(mouseLocation);

            var currentPageIndex = this.radPdfViewer1.Document.Pages.IndexOf(element.Page);
            var zoom = this.radPdfViewer1.PdfViewerElement.ScaleFactor;


            paginaCurenta = currentPageIndex;
            pozitiaX = (pointInDoc.X / zoom);
            pozitiaY = (pointInDoc.Y / zoom);
        }
    }

    private void CreateContextMenu()
    {
        RadMenuItem item = new RadMenuItem("Semneaza aici");
        item.ToolTipText = "plaseaza semnatura in pozitia curenta";

        item.Click += item_Click;

        RadItem[] items = new RadItem[this.radPdfViewer1.PdfViewerElement.ContextMenu.Items.Count];

        this.radPdfViewer1.PdfViewerElement.ContextMenu.Items.CopyTo(items, 0);

        this.radPdfViewer1.PdfViewerElement.ContextMenu.Items.Clear();
        this.radPdfViewer1.PdfViewerElement.ContextMenu.Items.Add(item);

        for (int w = 0; w < items.Length; w++)
        {
            this.radPdfViewer1.PdfViewerElement.ContextMenu.Items.Add(items[w]);
        }
    }

    private void item_Click(object sender, EventArgs e)
    {
        Telerik.Windows.Documents.Fixed.FormatProviders.Pdf.PdfFormatProvider provider = new Telerik.Windows.Documents.Fixed.FormatProviders.Pdf.PdfFormatProvider();
        MemoryStream ms = new MemoryStream();
        this.radPdfViewer1.PdfViewerElement.SaveDocument(ms);
        ms.Seek(0, SeekOrigin.Begin);
        RadFixedDocument doc = provider.Import(ms);

        var page = doc.Pages[paginaCurenta];
        FixedContentEditor editor = new FixedContentEditor(page);
        editor.Position = new MatrixPosition();
        var rotation = page.Rotation;

        if (rotation == Rotation.Rotate90)
        {
            editor.Position.Rotate(90);
        }
        else if (rotation == Rotation.Rotate270)
        {
            editor.Position.Rotate(270);
        }

        editor.Position.Translate(pozitiaX, pozitiaY);

        editor.GraphicProperties.FillColor = new RgbColor(67, 123, 123, 123);
        editor.DrawRectangle(new System.Windows.Rect(0, 0, 320, 80));

        MemoryStream newFile = new MemoryStream();
        provider.Export(doc, newFile);
        this.radPdfViewer1.UnloadDocument();
        newFile.Seek(0, SeekOrigin.Begin);
        this.radPdfViewer1.LoadDocument(newFile);
    }
}



Private paginaCurenta As Integer = 0
Private pozitiaX As Single = 0
Private pozitiaY As Single = 0

Public Sub New()
    InitializeComponent()
    Me.RadPdfViewer1.LoadDocument("..\..\sample.pdf")
    AddHandler Me.RadPdfViewer1.MouseDown, AddressOf Me.RadPdfViewer1_MouseDown
    Me.CreateContextMenu()
    Me.RadPdfViewer1.PdfViewerElement.Mode = FixedDocumentViewerMode.TextSelection
End Sub

Private Sub RadPdfViewer1_MouseDown(ByVal sender As Object, ByVal e As MouseEventArgs)
    Dim element = TryCast(Me.RadPdfViewer1.ElementTree.GetElementAtPoint(e.Location), RadFixedPageElement)

    If element IsNot Nothing Then
        Dim mouseLocation = e.Location
        Dim tt = element.TotalTransform
        tt.Invert()
        Dim pointInDoc = tt.TransformPoint(mouseLocation)
        Dim currentPageIndex = Me.RadPdfViewer1.Document.Pages.IndexOf(element.Page)
        Dim zoom = Me.RadPdfViewer1.PdfViewerElement.ScaleFactor
        paginaCurenta = currentPageIndex
        pozitiaX = (pointInDoc.X / zoom)
        pozitiaY = (pointInDoc.Y / zoom)
    End If
End Sub

Private Sub CreateContextMenu()
    Dim item As RadMenuItem = New RadMenuItem("Semneaza aici")
    item.ToolTipText = "plaseaza semnatura in pozitia curenta"
    AddHandler item.Click, AddressOf item_Click
    Dim items As RadItem() = New RadItem(Me.RadPdfViewer1.PdfViewerElement.ContextMenu.Items.Count - 1) {}
    Me.RadPdfViewer1.PdfViewerElement.ContextMenu.Items.CopyTo(items, 0)
    Me.RadPdfViewer1.PdfViewerElement.ContextMenu.Items.Clear()
    Me.RadPdfViewer1.PdfViewerElement.ContextMenu.Items.Add(item)

    For w As Integer = 0 To items.Length - 1
        Me.RadPdfViewer1.PdfViewerElement.ContextMenu.Items.Add(items(w))
    Next
End Sub

Private Sub item_Click(ByVal sender As Object, ByVal e As EventArgs)
    Dim provider As Telerik.Windows.Documents.Fixed.FormatProviders.Pdf.PdfFormatProvider = New Telerik.Windows.Documents.Fixed.FormatProviders.Pdf.PdfFormatProvider()
    Dim ms As MemoryStream = New MemoryStream()
    Me.RadPdfViewer1.PdfViewerElement.SaveDocument(ms)
    ms.Seek(0, SeekOrigin.Begin)
    Dim doc As RadFixedDocument = provider.Import(ms)
    Dim page = doc.Pages(paginaCurenta)
    Dim editor As FixedContentEditor = New FixedContentEditor(page)
    editor.Position = New MatrixPosition()
    Dim rotation = page.Rotation

    If rotation = Rotation.Rotate90 Then
        editor.Position.Rotate(90)
    ElseIf rotation = Rotation.Rotate270 Then
        editor.Position.Rotate(270)
    End If

    editor.Position.Translate(pozitiaX, pozitiaY)
    editor.GraphicProperties.FillColor = New RgbColor(67, 123, 123, 123)
    editor.DrawRectangle(New System.Windows.Rect(0, 0, 320, 80))
    Dim newFile As MemoryStream = New MemoryStream()
    provider.Export(doc, newFile)
    Me.RadPdfViewer1.UnloadDocument()
    newFile.Seek(0, SeekOrigin.Begin)
    Me.RadPdfViewer1.LoadDocument(newFile)
End Sub

See Also

In this article