Ereignisbasierte Änderungen der XPS-Seite | C++

Was ist der ereignisbasierte Ansatz in der Programmierung?

Der ereignisbasierte Ansatz in der Programmierung ist ein Paradigma, das sich um das Konzept von Ereignissen und der Ereignisbehandlung dreht. In diesem Modell wird der Programmablauf durch Ereignisse bestimmt, bei denen es sich um Benutzeraktionen (wie Mausklicks oder Tastendrücke), vom System generierte Benachrichtigungen oder Nachrichten von anderen Anwendungen handeln kann. Hier sind einige Schlüsselaspekte des ereignisbasierten Ansatzes:

Insgesamt ist der ereignisbasierte Ansatz eine leistungsstarke Möglichkeit, Interaktionen und Arbeitsabläufe innerhalb eines Programms zu verwalten, was ihn besonders effektiv für Anwendungen macht, die Reaktionsfähigkeit und Benutzerinteraktion erfordern.

Ereignisse, die während der XPS-Dokumentkonvertierung auftreten

Wenn Sie mithilfe der Aspose.Page-API Änderungen an einer bestimmten Seite eines XPS-Dokuments vornehmen müssen, wählen Sie normalerweise das aktive Dokument aus (wenn die XPS-Datei mehrere Dokumente enthält), wählen Sie die aktive Seite aus und nehmen Sie dann die Änderungen selbst vor .

Angenommen, Sie müssen wiederholte Änderungen an allen Seiten in einer XPS-Datei vornehmen und das Ergebnis dann in PDF oder ein Bildformat konvertieren. Einige Beispiele für solche Änderungen umfassen das Platzieren eines Wasserzeichens über den Seiten oder das Hinzufügen von Navigations-Hyperlinks. Der direkte Weg, solche Änderungen vorzunehmen, besteht darin, die Dokumente im XPS-Paket zu durchsuchen, die Seiten im aktuell aktiven Dokument zu durchsuchen und schließlich Ihre Änderungen anzuwenden. Daher würde der Code zum Ausführen dieser Aufgabe wie folgt aussehen:

 1for (uint32_t i = 1; i <= document->DocumentCount(); i++)
 2{
 3    document->SelectActiveDocument(i);
 4    for (uint32_t j = 1; j <= document->PageCount(); j++)
 5    {
 6        document->SelectActivePage(j);
 7        // Your changes ...
 8    }
 9}
10document->SaveAsPdf(u"file-name.pdf", saveOptions);

Wenn Sie vor den sich wiederholenden Änderungen auch einige unregelmäßige Änderungen vornehmen müssen, kann dieser Ansatz zu Verwirrung oder übermäßigem Durchlaufen von Dokumenten und Seiten führen, ganz zu schweigen davon, dass diese Schleifen etwas umständlich erscheinen.

Wenn Sie ein XPS-Dokument in ein PDF oder ein Bild konvertieren, erfolgt der Vorgang Seite für Seite. Wenn der Konvertierungsauftrag bereit ist, die nächste Seite zu verarbeiten, löst er ein „Before-Page“-Ereignis aus. Der Benutzer kann die Behandlung solcher Ereignisse definieren, indem er die Klasse BeforePageSavingEventHandler erweitert und so einige Vorteile nutzt, die im Einführungsabschnitt dieses Artikels beschrieben werden.

Hier stellen wir ein Beispiel für Navigations-Hyperlinks vor. Und um die Aufgabe etwas komplizierter zu machen, konvertieren wir nur eine Teilmenge aller Seiten in PDF, wie durch die Eigenschaft „PdfSaveOptions.PageNumbers“ angegeben.

Die Event-Handler-Klasse

Unten ist die Erweiterung der Klasse „BeforePageSavingEventHandler“:

 1    /// <summary>
 2    /// The class to handle the before-page event while converting an XPS document.
 3    /// </summary>
 4    class NavigationInjector : public Aspose::Page::XPS::Features::EventBasedModifications::BeforePageSavingEventHandler
 5    {
 6        typedef NavigationInjector ThisType;
 7        typedef Aspose::Page::XPS::Features::EventBasedModifications::BeforePageSavingEventHandler BaseType;
 8        
 9        typedef ::System::BaseTypesInfo<BaseType> ThisTypeBaseTypesInfo;
10        RTTI_INFO_DECL();
11        
12    public:
13    
14        NavigationInjector(System::SharedPtr<Aspose::Page::XPS::XpsModel::XpsFont> font, System::ArrayPtr<int32_t> pageNumbers);
15        
16        /// <summary>
17        /// The action itself to be triggered on a before-page event.
18        /// </summary>
19        /// <param name="args">The event arguments.</param>
20        void Handle(System::SharedPtr<Aspose::Page::XPS::Features::EventBasedModifications::BeforeSavingEventArgs<System::SharedPtr<Aspose::Page::XPS::Features::EventBasedModifications::PageAPI>>> args) override;
21        
22    private:
23    
24        System::SharedPtr<Aspose::Page::XPS::XpsModel::XpsFont> _font;
25        System::SharedPtr<System::Collections::Generic::SortedList<int32_t, int32_t>> _pageNumbers;
26        
27    };
 1ModifyXpsPageOnConversion::NavigationInjector::NavigationInjector(System::SharedPtr<Aspose::Page::XPS::XpsModel::XpsFont> font, System::ArrayPtr<int32_t> pageNumbers)
 2{
 3    _font = font;
 4    if (pageNumbers == nullptr)
 5    {
 6        return;
 7    }
 8    
 9    // Turn the page number array into a sorted collection of unique values.
10    _pageNumbers = System::MakeObject<System::Collections::Generic::SortedList<int32_t, int32_t>>();
11    for (int32_t pn : pageNumbers)
12    {
13        _pageNumbers->idx_set(pn, 0);
14    }
15    
16}
17
18void ModifyXpsPageOnConversion::NavigationInjector::Handle(System::SharedPtr<Aspose::Page::XPS::Features::EventBasedModifications::BeforeSavingEventArgs<System::SharedPtr<Aspose::Page::XPS::Features::EventBasedModifications::PageAPI>>> args)
19{
20    System::SharedPtr<PageAPI> api = args->get_ElementAPI();
21    
22    System::SharedPtr<XpsGlyphs> glyphs;
23    // For all pages in the output PDF except the first one...
24    if (args->get_OutputPageNumber() > 1)
25    {
26        // ...insert a hyperlink to the first page...
27        glyphs = api->CreateGlyphs(_font, 15.f, 5.f, api->get_Height() - 10.f, u"[First]");
28        glyphs->set_Fill(api->CreateSolidColorBrush(System::Drawing::Color::get_Blue()));
29        glyphs->set_HyperlinkTarget(System::MakeObject<XpsPageLinkTarget>(_pageNumbers == nullptr ? 1 : _pageNumbers->get_Keys()->idx_get(0)));
30        api->Add<System::SharedPtr<XpsGlyphs>>(glyphs);
31        
32        // ...and to the previous page.
33        glyphs = api->CreateGlyphs(_font, 15.f, 60.f, api->get_Height() - 10.f, u"[Prev]");
34        glyphs->set_Fill(api->CreateSolidColorBrush(System::Drawing::Color::get_Blue()));
35        glyphs->set_HyperlinkTarget(System::MakeObject<XpsPageLinkTarget>(_pageNumbers == nullptr ? args->get_AbsolutePageNumber() - 1 : _pageNumbers->get_Keys()->idx_get(args->get_OutputPageNumber() - 2)));
36        api->Add<System::SharedPtr<XpsGlyphs>>(glyphs);
37    }
38    
39    // For all pages in the output PDF except the last one...
40    if ((_pageNumbers != nullptr && args->get_OutputPageNumber() < _pageNumbers->get_Count()) || (_pageNumbers == nullptr && args->get_OutputPageNumber() < api->get_TotalPageCount()))
41    {
42        // ...insert a hyperlink to the next page...
43        glyphs = api->CreateGlyphs(_font, 15.f, 110.f, api->get_Height() - 10.f, u"[Next]");
44        glyphs->set_Fill(api->CreateSolidColorBrush(System::Drawing::Color::get_Blue()));
45        glyphs->set_HyperlinkTarget(System::MakeObject<XpsPageLinkTarget>(_pageNumbers == nullptr ? args->get_AbsolutePageNumber() + 1 : _pageNumbers->get_Keys()->idx_get(args->get_OutputPageNumber())));
46        api->Add<System::SharedPtr<XpsGlyphs>>(glyphs);
47        
48        // ...and to the last page.
49        glyphs = api->CreateGlyphs(_font, 15.f, 160.f, api->get_Height() - 10.f, u"[Last]");
50        glyphs->set_Fill(api->CreateSolidColorBrush(System::Drawing::Color::get_Blue()));
51        glyphs->set_HyperlinkTarget(System::MakeObject<XpsPageLinkTarget>(_pageNumbers == nullptr ? api->get_TotalPageCount() : _pageNumbers->get_Keys()->idx_get(_pageNumbers->get_Keys()->get_Count() - 1)));
52        api->Add<System::SharedPtr<XpsGlyphs>>(glyphs);
53    }
54    
55    // Insert a page number in the bottom-right corner.
56    glyphs = api->CreateGlyphs(_font, 15.f, api->get_Width() - 20.f, api->get_Height() - 10.f, System::Convert::ToString(args->get_OutputPageNumber()));
57    glyphs->set_Fill(api->CreateSolidColorBrush(System::Drawing::Color::get_Black()));
58    api->Add<System::SharedPtr<XpsGlyphs>>(glyphs);
59    
60    // Add an outline entry to display the links to the converted pages in the navigation pane of a PDF viewer.
61    api->AddOutlineEntry(System::String::Format(u"Page {0}", args->get_OutputPageNumber()), 1, args->get_AbsolutePageNumber());
62}

Die Handler-Klasse sollte wissen, welche Seiten wir als PDF speichern möchten, um die richtigen Hyperlink-Ziele zu erstellen. Daher sollte der Konstruktor die Array-Eigenschaft der Optionen als Argument verwenden. Wenn das Array von Seitenzahlen angegeben ist, erstellen wir eine sortierte Sammlung davon und vermeiden gleichzeitig Duplikate. (Übrigens ist diese Lösung nicht ganz korrekt. Können Sie herausfinden, was zu Inkonsistenzen in der Ausgabe führen könnte?) Wir benötigen außerdem ein „XpsFont“-Objekt, das die Schriftartdaten für den Hyperlink-Text enthält.

In der überschriebenen Methode „Handle()“ geschieht alles. Das Argument der Methode ist ein Objekt, das die Änderungs-API für die aktuelle Seite, die Dokumentnummer innerhalb des XPS-Pakets, die absolute Seitenzahl über alle Dokumente hinweg, die relative Seitenzahl innerhalb des aktuellen Dokuments (die gleich ist) enthält vorherige Nummer, falls sich nur ein Dokument im Paket befindet) und die Ausgabeseitennummer (die der absoluten Seitenzahl entspricht, wenn wir das gesamte Paket konvertieren).

Die Logik der folgenden zwei „Wenn“-Blöcke ist recht einfach. Es basiert auf der Analyse des Ereignisarguments „OutputPageNumber“, um gegebenenfalls einige der Links wegzulassen: Die Links [First] und [Prev] werden allen Ausgabeseiten außer der ersten hinzugefügt, während die Links „ Die Links [Weiter] und [Letzte] werden auf allen Seiten außer der letzten angezeigt. Die Logik ist auch auf beide Fälle zugeschnitten, unabhängig davon, ob Seitenzahlen angegeben sind oder nicht.

Nach den „if“-Blöcken gibt es Code zum Hinzufügen einer Seitenzahl in der unteren rechten Ecke der Seite.

Die letzte Zeile fügt den Gliederungseintrag der Seite hinzu, das Element, das im Navigationsbereich eines PDF-Viewers angezeigt wird (sofern unterstützt).

Der Konvertierungscode

Nachdem nun der Ereignishandler „before-page“ definiert ist, können wir den Code schreiben, der das Dokument konvertiert:

Wir öffnen eine XPS-Datei und instanziieren dann ein Stream-Objekt mit der Schriftartdatendatei. Als nächstes erstellen wir eine Instanz der Klasse „PdfSaveOptions“ und geben die Anzahl der Seiten an, die wir konvertieren müssen. In der nächsten Zeile wird der Ereignishandler „before-page“ über die Sammlungsoption „BeforePageSavingEventHandlers“ mit dem Konvertierungsauftrag „verbunden“.

Jetzt müssen Sie nur noch die Konvertierung in PDF mit der Methode „SaveAsPdf()“ des Dokuments durchführen.

Abschluss

In diesem Artikel haben wir die wichtigsten Punkte des ereignisbasierten Ansatzes in der Programmierung untersucht, die direkte Methode zum Ändern von Seiten eines XPS-Dokuments untersucht und eine fortgeschrittenere und ausgefeiltere Technik kennengelernt, um während des Vorgangs wiederholende Änderungen an allen Ausgabeseiten vorzunehmen Konvertierungsprozess am Beispiel des Einfügens von Navigations-Hyperlinks. Die vollständigen Beispiele finden Sie in unserem Beispielprojekt.

Have any questions about Aspose.Page?



Subscribe to Aspose Product Updates

Get monthly newsletters & offers directly delivered to your mailbox.