Colored search results for programmatic search

PDF-XChange Editor SDK for Developers

Moderators: TrackerSupp-Daniel, Tracker Support, Paul - Tracker Supp, Vasyl-Tracker Dev Team, Chris - Tracker Supp, Sean - Tracker, Ivan - Tracker Software, Tracker Supp-Stefan

Forum rules
DO NOT post your license/serial key, or your activation code - these forums, and all posts within, are public and we will be forced to immediately deactivate your license.

When experiencing some errors, use the IAUX_Inst::FormatHRESULT method to see their description and include it in your post along with the error code.
Post Reply
SMan
User
Posts: 23
Joined: Tue May 15, 2018 10:18 am

Colored search results for programmatic search

Post by SMan »

Hello all,

I am a developer working with PDF-XChange Editor SDK V7 which is used in software our company has been developing in VB.net.

Currently we are working on a new feature of our software which comes after a programmatic search (that doesn't in itself use the PDF-XChange Editor) with a variable set of search terms. The result of that search is generally a list of PDF documents, any of which the user can click on, and at that point PDF-XChange Editor comes in to display the corresponding document. The new feature is to highlight any of the search terms of the preceding search in the PDF document that is being displayed (not all of the matches necessarily occur in the text content of the PDF because the search also is performed on certain metadata other than the PDF content). Everything I've written so far I have been able to achieve.

Now to the part that I am struggling with. When manually searching within a document using its own GUI, the PDF-XChange Editor also allows (via advanced search options) to highlight search results in multiple colors, which we also would very much like to use for highlighting the matches of our programmatical search, but I haven't managed to get that to work.

Admittedly, I am not clear on what the programmatical equivalent of the distinction between "Find" and "Advanced Search" is, if such a distinction exists, and if it does, which one of the both I have been using in my solution.

Here is a stripped-down version of the code I have (with an exemplary list of search terms hard-coded). I have based my solution on the example given in https://sdkhelp.pdf-xchange.com/view/PXV:op_search, converted it to VB.net and made some minor adaptations. I also attempted to employ the solution from this thread, but it made no difference: the search terms are all highlighted in the same color either way.

Code: Select all

...
Friend docPageToSelect As Integer = -1 
'helps to make sure that on a multiple-page doc the current page gets set to the first, not the last, one with a search result
...

    Friend Sub SearchOperation(Doc As PDFXEdit.IPXV_Document, Inst As PDFXEdit.PXV_Inst)

        Dim nID As Integer = Inst.Str2ID("op.search", False)
        Dim Op As PDFXEdit.IOperation = Inst.CreateOp(nID)
        Dim input As PDFXEdit.ICabNode = Op.Params.Root("Input")
        input.Add().v = Doc.CoreDoc
        'begin this-does-not-help
        Dim b As Boolean = Inst.Settings("Misc.ColoredSearchRes").Bool
        If Not b Then
            Inst.ExecUICmd("cmd.search.coloredResults")
        End If
        'end this-does-not-help
        
        Dim options As PDFXEdit.ICabNode = Op.Params.Root("Options")
        options("OR").Add().v = "quick"
        options("OR").Add().v = "fox"
        options("OR").Add().v = "alfuqarlgfbqaewr"    'does actually not appear in document contents
        options("OR").Add().v = "lazy"

        Dim clbk As SearchCallback = New SearchCallback(frmMain.IoPdfEditor.Inst)
        options("Callback").v = clbk
        options("Flags").v = (CInt(PDFXEdit.PXV_SearchFlags.PXV_SearchFlag_GetTextQuads) Or CInt(PDFXEdit.PXV_SearchFlags.PXV_SearchFlag_IncludePageText))
        docPageToSelect = -1
        Op.Do()
    End Sub

...

Public Class SearchCallback
    Implements PDFXEdit.IPXV_SearchCallback

    Private m_Inst As PDFXEdit.IPXV_Inst = Nothing

    Public Sub New(Inst As PDFXEdit.IPXV_Inst)
        m_Inst = Inst
    End Sub


    Public Sub OnStart() Implements IPXV_SearchCallback.OnStart

    End Sub

    Public Sub OnFinish(nResCode As Integer) Implements IPXV_SearchCallback.OnFinish

    End Sub

    Public Sub OnStartPtr(pPtr As IPXV_SearchPtr) Implements IPXV_SearchCallback.OnStartPtr

    End Sub

    Public Sub OnStopPtr(pPtr As IPXV_SearchPtr, bIncomplete As Boolean) Implements IPXV_SearchCallback.OnStopPtr

    End Sub

    Public Sub OnNewEntry(pEntry As IPXV_SearchEntry) Implements IPXV_SearchCallback.OnNewEntry
        'Highlighting items in the document
        Dim i As UInteger = 0
        Dim doc As PDFXEdit.IPXC_Document = Nothing
        Dim vDoc As PDFXEdit.IPXV_Document = Nothing
        Dim page As PDFXEdit.IPXC_Page = Nothing
        Dim highlighter As PDFXEdit.IPXV_DocHighlighter = Nothing

        While i < pEntry.Count

            Dim item As PDFXEdit.IPXV_SearchEntryItem = pEntry(i)
            Dim ptr As PDFXEdit.IPXV_SearchPtr = item.Ptr

            For j As UInteger = 0 To ptr.Count - 1
                Dim chunk As PDFXEdit.PXV_SearchPtrChunk = ptr(j)

                'First we get the document
                If chunk.nType = CUInt(PDFXEdit.PXV_SearchPtrChunkType.PXV_SearchPtrChunk_Document) Then
                    doc = ptr.Doc(chunk.nValue)
                    vDoc = m_Inst.FindDocByCoreDoc(doc)

                    'Now we'll need to check whether the document is opened so that we can highlight it
                    If Not IsNothing(vDoc) Then
                        highlighter = vDoc.AddNewHighlighter(PDFXEdit.PXV_DocHighlightType.PXV_DocHighlight_Page)
                    End If
                ElseIf chunk.nType = CUInt(PDFXEdit.PXV_SearchPtrChunkType.PXV_SearchPtrChunk_Page) Then
                    If Not IsNothing(doc) Then
                        page = doc.Pages(chunk.nValue)
                    End If
                    If Not IsNothing(page) Then
                        'Now we have the page where the text is found
                        For k As UInteger = 0 To item.TextRangesCount - 1
                            'Now we need to get the coordinates of the highlight boxes
                            Dim quads As PDFXEdit.IPXC_QuadsF = item.GetTextRangeQuads(k)
                            'Highlighting the search results
                            If Not IsNothing(highlighter) Then
                                Dim ha As PDFXEdit.PXV_DocHighlightAdvanced = New PDFXEdit.PXV_DocHighlightAdvanced()
                                highlighter.Add(page, quads, Nothing, Nothing, ha, 0)
                                'Setting the current page of the document to the first page with a search result
                                If docPageToSelect = -1 Then
                                    docPageToSelect = page.Number
                                    vDoc.ActiveView.PagesView.Layout.CurrentPage = page.Number
                                End If
                            End If
                        Next
                    End If
                End If
            Next
            i += 1
        End While
    End Sub
End Class
I suspect that the "Misc.ColoredSearchRes" setting makes no difference because SearchCallback is called separately for each match and therefore every match is always the first one within the scope of SearchCallback. But is there any way around this?
Sasha - Tracker Dev Team
User
Posts: 5522
Joined: Fri Nov 21, 2014 8:27 am
Contact:

Re: Colored search results for programmatic search

Post by Sasha - Tracker Dev Team »

Hello SMan,

When you use the IPXV_DocHighlighter::AddPage method, you don't include the custom brush and/or pen thus the default yellow color is being used instead.

Also tip: you may use the WordIndex з IPXV_SearchEntryItem::GetTextRange to assign different colors for different WordIndex'es.

Cheers,
Alex
Subscribe at:
https://www.youtube.com/channel/UC-TwAMNi1haxJ1FX3LvB4CQ
SMan
User
Posts: 23
Joined: Tue May 15, 2018 10:18 am

Re: Colored search results for programmatic search

Post by SMan »

Hello Sasha,

Thanks for your suggestions. At the moment I'm working on a different task, but when I get back to the feature that involves highlighting search results, I will certainly make use of them and report back on my results.

Regards,
SMan
Sasha - Tracker Dev Team
User
Posts: 5522
Joined: Fri Nov 21, 2014 8:27 am
Contact:

Colored search results for programmatic search

Post by Sasha - Tracker Dev Team »

:)
Subscribe at:
https://www.youtube.com/channel/UC-TwAMNi1haxJ1FX3LvB4CQ
SMan
User
Posts: 23
Joined: Tue May 15, 2018 10:18 am

Re: Colored search results for programmatic search

Post by SMan »

Hi again,

I've now had a little time to look at this issue again and must say that while I appreciate the pointers, I still am a little confused about how to apply them.

When you write about the IPXV_DocHighlighter::AddPage method, I assume you actually mean IPXV_DocHighlighter::Add which in my code is used in this way:

Code: Select all

highlighter.Add(page, quads, Nothing, Nothing, ha, 0)
Here the two arguments that are set to "Nothing" are indeed arguments of type IUIX_Brush and IUIX_Pen, so it seems these are the ones I need to use. But I must admit I am not yet clear about what I need to do to (declare, initialize, pass) to use a custom brush and/or pen in the context of my code. Searching the forum for examples I only found this thread which seems to show a completely different mechanism. (Tried to apply it to my code anyway, didn't work.)

Sasha - Tracker Dev Team wrote: Tue Jun 30, 2020 1:13 pmAlso tip: you may use the WordIndex з IPXV_SearchEntryItem::GetTextRange to assign different colors for different WordIndex'es.
OK, I managed to use this hint to find out how to differentiate the various search matches by WordIndex, such that the value of WordIndex is the same iff the content of the search match is the same. Presumably I can use this to assign each value of WordIndex a different color so that I can highlight the text using a custom brush with that color. Does this mean I have to define the color for each possible value of WordIndex myself or can I somehow make use of the standard (?) color palette that the PDF-XChange Editor uses in its own advanced search with colored search results?
Sasha - Tracker Dev Team
User
Posts: 5522
Joined: Fri Nov 21, 2014 8:27 am
Contact:

Re: Colored search results for programmatic search

Post by Sasha - Tracker Dev Team »

Hello SMan,

The IUIX_Inst::CreateNewBrush and IUIX_Inst::CreateNewPen should be used to create the IUIX_Brush and IUIX_Pen objects. Then you should fill them with the needed color and pass to the method.

Cheers,
Alex
Subscribe at:
https://www.youtube.com/channel/UC-TwAMNi1haxJ1FX3LvB4CQ
SMan
User
Posts: 23
Joined: Tue May 15, 2018 10:18 am

Re: Colored search results for programmatic search

Post by SMan »

Hello Sasha,

Thanks, this should help. So I need to define the color for each possible value of WordIndex myself? There is no easy way to make use of the color palette that the PDF-XChange Editor uses in its own advanced search with colored search results?
Sasha - Tracker Dev Team
User
Posts: 5522
Joined: Fri Nov 21, 2014 8:27 am
Contact:

Re: Colored search results for programmatic search

Post by Sasha - Tracker Dev Team »

Hello SMan,

Yup, if you want to use your own colors then you'll have to assign them manually.

Cheers,
Alex
Subscribe at:
https://www.youtube.com/channel/UC-TwAMNi1haxJ1FX3LvB4CQ
SMan
User
Posts: 23
Joined: Tue May 15, 2018 10:18 am

Re: Colored search results for programmatic search

Post by SMan »

Hi again,

I can create a custom brush and a custom pen with the IUIX_Inst::CreateNewBrush and IUIX_Inst::CreateNewPen methods, so far so good. But is there any guidance (documentation, examples) on how to use them?

I assume that in IPXV_DocHighlighter::Add the IUIX_Brush argument affects the interior and the IUIX_Pen argument the border of the highlighted area, is that correct?

IUIX_Brush has properties Color0 and Color1 of type ULONG, but which of the two does what and how do ULONG values map to particular colors?

As for the IUIX_Pen interface, according to the documentation that does not even have a Color property or any property I can change that looks to me like it could affect the color. It does have a Brush property of type IUIX_Brush, but that is read-only. (IUIX_Pen::Inside might look like a possibility at first glance until you notice that its type is VARIANT_BOOL, patently unsuitable to encode even the most limited kind of color range if it is to be called that meaningfully.) IUIX_Inst::CreateNewPen takes no arguments at all, so what options do I have?
SMan
User
Posts: 23
Joined: Tue May 15, 2018 10:18 am

Re: Colored search results for programmatic search

Post by SMan »

Sasha - Tracker Dev Team wrote: Tue Jul 21, 2020 8:00 amYup, if you want to use your own colors then you'll have to assign them manually.
A clarification: I actually would prefer not having to define my own colors and would be perfectly happy to have PDF-XChange Editor SDK choose the colors for me, as long as they are different colors for different search results.

In this way we could also bypass the whole issue about how to actually assign my own colors programmatically, which I'd still need help with anyway.

Edit:
To maybe explain better what I mean, I've made a screenshot where I used the PDF-XChange Editor embedded in one of our products from the SDK and performed a search using the Editor's own search functionality:
colored_search2.jpg
Here the search results are highlighted in different colors and I need to achieve the same way of highlighting with our programmatic search. I have managed to get as far as highlighting the search results, but not in different colors.
Sasha - Tracker Dev Team
User
Posts: 5522
Joined: Fri Nov 21, 2014 8:27 am
Contact:

Re: Colored search results for programmatic search

Post by Sasha - Tracker Dev Team »

Hello SMan,

The Pen of the Highlighter is a border of it, while the Brush is the inner part.
The CreatePen/CreateBrush methods allow you to create new empty pen and brush that you can fill as you like.
If we take the IUIX_Pen for instance all of those properties and methods allow you to set the different pen types - dashed, solid, set it's width and also it's IUIX_Brush. Basically you can create a border with a fill inside of it if needed (like 2 color sandwich border for instance) - a Brush is a Fill color and a Pen is a Stroke color.
And the IUIX_Brush of the highlighter is the fill of the rectangle that highlights something. The two colors are needed for the gradient if you require one. Basically you should set the Color0 in the form of 0xFFAABBCC for basic fill, where the FF in this case is Opacity factor.

Cheers,
Alex
Subscribe at:
https://www.youtube.com/channel/UC-TwAMNi1haxJ1FX3LvB4CQ
SMan
User
Posts: 23
Joined: Tue May 15, 2018 10:18 am

Re: Colored search results for programmatic search

Post by SMan »

Hi Alex,

Thanks again, that clears up some of my questions. But as far as I can tell, the IUIX_Pen::Brush property is read-only (according to the documentation and also in the SDK build we have installed, which is admittedly not the most current), so how can I set it?

Also, I have to ask again because my boss would very strongly prefer that I don't have to use time and effort to define and assign the colors myself. Is there really no way how I can let the PDF-XChange Editor SDK choose and assign the colors for the different search results for me, like in the screenshot above?

Edit: The SDK is now updated to the newest version, but that makes no difference as far as this issue is concerned.

Best regards,
Sven (SMan)
Sasha - Tracker Dev Team
User
Posts: 5522
Joined: Fri Nov 21, 2014 8:27 am
Contact:

Re: Colored search results for programmatic search

Post by Sasha - Tracker Dev Team »

Hello SMan,

You don't need the Pen's brush - you will need to pass the new brush (fill) with needed color when creating the highlighter.
As for the colors - just store a map with random color generation or something like that. Or you can take a list of colors and get them by index as the document count grows.

Cheers,
Alex
Subscribe at:
https://www.youtube.com/channel/UC-TwAMNi1haxJ1FX3LvB4CQ
SMan
User
Posts: 23
Joined: Tue May 15, 2018 10:18 am

Re: Colored search results for programmatic search

Post by SMan »

Hi Alex,
Sasha - Tracker Dev Team wrote: Mon Aug 10, 2020 9:20 amAs for the colors - just store a map with random color generation or something like that. Or you can take a list of colors and get them by index as the document count grows.
Yes, I realize that I'm supposedly able to do that, but that is precisely the task I was hoping to avoid, especially seeing that the Editor already has implemented a solution for its manual advanced search which I would be quite happy to piggyback on.

So do I understand you correctly that there is no way around my coding my own color assignment process?

If so, then I am running against the next obstacles. You wrote:
Sasha - Tracker Dev Team wrote: Wed Aug 05, 2020 8:40 am The Pen of the Highlighter is a border of it, while the Brush is the inner part.
The CreatePen/CreateBrush methods allow you to create new empty pen and brush that you can fill as you like.
If we take the IUIX_Pen for instance all of those properties and methods allow you to set the different pen types - dashed, solid, set it's width and also it's IUIX_Brush. Basically you can create a border with a fill inside of it if needed (like 2 color sandwich border for instance) - a Brush is a Fill color and a Pen is a Stroke color.
So I need the IUIX_Pen for the border of the highlighted area. But how am I to set the color of that border? I can see no property of IUIX_Pen that has any bearing on its color, except presumably IUIX_Pen::Brush, but Brush is read-only so I can't change it! (Leaving the IUIX_Pen unchanged after calling IUIX_Inst::CreateNewPen and passing that IUIX_Pen into IPXV_DocHighlighter::Add results in highlighted text areas with a dark grey border.)

Edit: I just double-checked, there is no method either that sets the Brush property of an existing IUIX_Pen object.

Next: the IUIX_Brush.
Sasha - Tracker Dev Team wrote: Wed Aug 05, 2020 8:40 am Basically you should set the Color0 in the form of 0xFFAABBCC for basic fill, where the FF in this case is Opacity factor.
What are the AA, BB and CC hex bytes standing for in 0xFFAABBCC? I expected that AA would be the value for red, BB for green and CC for blue - but that gives me some unexpected results. I made the following routine to which I can pass an argument of type System.Drawing.Color, plus an optional one of type Integer to override the opacity, which should output a UInteger value such that I can pass that to IUIX_Brush::Color0. Maybe someone can spot a mistake?

Code: Select all

    Private Function ToUInt(col As Color, Optional opacity As Integer = -1) As UInteger
        Dim uValue As UInteger
        If opacity < 0 Then
            uValue = col.A
        ElseIf opacity > 255 Then
            uValue = 255
        Else
            uValue = opacity
        End If
        uValue = uValue * 256 + col.R
        uValue = uValue * 256 + col.G
        uValue = uValue * 256 + col.B
        Return uValue
    End Function
If I pass values Color.Yellow, Color.Red and Color.Blue into that function, each time with opacity value 127, and then pass the result to IUIX_Brush::Color0, the resulting highlights look cyan, blue, and red, respectively.

Wait a moment...

Code: Select all

        ...
        uValue = uValue * 256 + col.B
        uValue = uValue * 256 + col.G
        uValue = uValue * 256 + col.R
        ...
Now at least the highlight interiors look as they should. But doesn't that mean that the UInt values for Color0 and Color1 encode the channels for opacity, red, green and blue in an unusual order?

Regards,
Sven (SMan)
Last edited by SMan on Fri Aug 14, 2020 7:46 am, edited 1 time in total.
SMan
User
Posts: 23
Joined: Tue May 15, 2018 10:18 am

Re: Colored search results for programmatic search

Post by SMan »

Something else: I tried to set the IUIX_Pen::Width property of the IUIX_Pen passed to the highlighter to zero, but that causes the entire program to abort with code -1073740771 (0xc000041d) on the next call of Application.DoEvents() without an exception being thrown.

Regards,
Sven (SMan)

Edit: I found out now that if I set Width to 0.1, then the program doesn't crash and the border of the highlighted area is still effectively invisible. Good enough for me as a workaround (both for the issue I raised in this post and for the fact that I can't get the border to be any other color than grey), but you might still want to look into this matter.
Sasha - Tracker Dev Team
User
Posts: 5522
Joined: Fri Nov 21, 2014 8:27 am
Contact:

Re: Colored search results for programmatic search

Post by Sasha - Tracker Dev Team »

Hello SMan,

There are different color schemes in the PDF Specifications. In this case, the BGRA (the reversed notation) is used from what I see.
As for the crash - thanks - we'll look into it.

Cheers,
Alex
Subscribe at:
https://www.youtube.com/channel/UC-TwAMNi1haxJ1FX3LvB4CQ
SMan
User
Posts: 23
Joined: Tue May 15, 2018 10:18 am

Re: Colored search results for programmatic search

Post by SMan »

Hello Alex,

actually it seems to me like the actual byte order corresponds to ABGR.

Also, while we can live with the workaround where we set the highlight border to be effectively invisible, we would still be interested to have highlights with an actually visible border in a color other than grey. Assuming that the IUIX_Pen::Brush property is what defines the color in which the highlight border drawn with that Pen appears, then either the IUIX_Pen::Brush property needs to be writable so that we can assign any IUIX_Brush to it, or there needs to be another way to set or change IUIX_Pen::Brush, maybe with an additional method. Or, as a final resort, it could be a method of IPXV_DocHighlighter to set/change the IUIX_Brush of the Pen for the highlight border.

Regards,
Sven (SMan)

Edit: I've been experimentally playing around with the border width a little bit and found out that the border actually appears black if the width is set to 3. So the actual color of the IUIX_Pen resulting from CreateNewPen seems to be black in fact, the border is just rendered in a grey tone when the pen width is 1.
Sasha - Tracker Dev Team
User
Posts: 5522
Joined: Fri Nov 21, 2014 8:27 am
Contact:

Re: Colored search results for programmatic search

Post by Sasha - Tracker Dev Team »

Hello SMan,

Here's how you should set a border for the highlight:
image.png
Cheers,
Alex
Subscribe at:
https://www.youtube.com/channel/UC-TwAMNi1haxJ1FX3LvB4CQ
SMan
User
Posts: 23
Joined: Tue May 15, 2018 10:18 am

Re: Colored search results for programmatic search

Post by SMan »

Hello Alex,

Thanks for the code sample. This has led me to learning about the pointer member access operator (->), but unfortunately, this is one of the few constructs in C# which don't have an equivalent in VB.NET. So as far as I can tell at the moment, it seems I can't change the highlight border in VB.NET with the current SDK.

We'll stick with the workaround I described above for now, and if future releases include a proper method to change the highlight border, that would be cool. Thanks for all the assistance so far!
Sasha - Tracker Dev Team
User
Posts: 5522
Joined: Fri Nov 21, 2014 8:27 am
Contact:

Colored search results for programmatic search

Post by Sasha - Tracker Dev Team »

:)
Subscribe at:
https://www.youtube.com/channel/UC-TwAMNi1haxJ1FX3LvB4CQ
Post Reply