Изменения страницы XPS на основе событий | С++

Что такое событийный подход в программировании?

Событийный подход в программировании — это парадигма, которая вращается вокруг концепции событий и обработки событий. В этой модели поток программы определяется событиями, которые могут быть действиями пользователя (например, щелчками мыши или нажатиями клавиш), системными уведомлениями или сообщениями от других приложений. Вот некоторые ключевые аспекты событийного подхода:

В целом, подход на основе событий — это мощный способ управления взаимодействиями и рабочими процессами в программе, что делает его особенно эффективным для приложений, требующих быстроты реагирования и взаимодействия с пользователем.

События, происходящие во время преобразования документа XPS

Когда вам нужно внести изменения в определенную страницу документа XPS с помощью API Aspose.Page, вы обычно выбираете активный документ (если в файле XPS несколько документов), выбираете активную страницу, а затем вносите сами изменения.

Теперь предположим, что вам нужно внести повторяющиеся изменения во все страницы в файле XPS, а затем преобразовать результат в PDF или формат изображения. Некоторые примеры таких изменений включают размещение водяного знака на страницах или добавление навигационных гиперссылок. Прямой способ внесения таких изменений включает в себя обход документов в пакете XPS, обход страниц в текущем активном документе и затем, наконец, применение ваших изменений. Таким образом, код для выполнения этой задачи будет выглядеть следующим образом:

 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);

Если вам также нужно внести некоторые нерегулярные изменения перед повторяющимися, этот подход может привести к некоторой путанице или избыточному обходу документов и страниц, не говоря уже о том, что эти циклы могут показаться немного громоздкими.

Когда вы конвертируете документ XPS в PDF или изображение, процесс происходит страница за страницей. Когда задание конвертации готово обработать следующую страницу, оно запускает событие «before-page». Пользователь может определить обработку таких событий, расширив класс BeforePageSavingEventHandler, тем самым воспользовавшись некоторыми преимуществами, описанными во вводном разделе этой статьи.

Пример добавления навигационных гиперссылок

Здесь мы приведем пример, связанный со случаем навигационных гиперссылок. И чтобы немного усложнить задачу, мы преобразуем в PDF только подмножество всех страниц, как указано в свойстве PdfSaveOptions.PageNumbers.

Класс обработчика событий

Ниже представлено расширение класса 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}

Класс обработчика должен знать, какие страницы мы хотим сохранить в формате PDF, чтобы создать правильные цели гиперссылок. Поэтому конструктор должен принимать свойство массива параметров в качестве аргумента. Если указан массив номеров страниц, мы создаем их отсортированную коллекцию, избегая при этом дубликатов. (Кстати, это решение не совсем точное. Можете ли вы понять, что может вызвать несоответствие в выводе?) Нам также понадобится объект XpsFont, содержащий данные шрифта для текста гиперссылки.

Переопределенный метод Handle() — это то место, где все это происходит. Аргумент метода — это объект, который содержит API модификации для текущей страницы, номер документа в пакете XPS, абсолютный номер страницы по всем документам, относительный номер страницы в текущем документе (который равен предыдущему номеру в случае только одного документа в пакете) и выходной номер страницы (который равен абсолютному номеру страницы, когда мы преобразуем весь пакет).

Логика следующих двух блоков if довольно проста. Она основана на анализе аргумента события OutputPageNumber, чтобы опустить некоторые ссылки там, где это уместно: ссылки [First] и [Prev] будут добавлены на все страницы вывода, кроме первой, в то время как ссылки [Next] и [Last] появятся на всех страницах, кроме последней. Логика также адаптирована для обоих случаев, независимо от того, указаны ли номера страниц или нет.

После блоков if идет код для добавления номера страницы в правом нижнем углу страницы.

Последняя строка добавляет запись структуры страницы, элемент, который будет отображаться в навигационной панели средства просмотра PDF (если поддерживается).

Код преобразования

Теперь, когда обработчик событий “before-page” определен, мы можем написать код, который преобразует документ:

Мы открываем XPS-файл, а затем создаем экземпляр потокового объекта с файлом данных шрифта. Затем мы создаем экземпляр класса PdfSaveOptions и указываем количество страниц, которые нам нужно преобразовать. В следующей строке обработчик событий «before-page» становится «подключенным» к заданию преобразования через параметр коллекции BeforePageSavingEventHandlers.

Осталось только запустить преобразование в PDF с помощью метода SaveAsPdf() документа.

Заключение

В этой статье мы изучили ключевые моменты событийного подхода в программировании, рассмотрели прямой метод изменения страниц документа XPS и изучили более продвинутую и сложную технику внесения повторяющихся изменений во все выходные страницы в процессе преобразования, используя в качестве примера вставку навигационных гиперссылок.

Для полных примеров изучите наш Example project.

Have any questions about Aspose.Page?



Subscribe to Aspose Product Updates

Get monthly newsletters & offers directly delivered to your mailbox.