XPS ページのイベントベースの変更 | C++
プログラミングにおけるイベントベースのアプローチとは?
プログラミングにおけるイベントベースのアプローチは、イベントとイベント処理の概念を中心としたパラダイムです。このモデルでは、プログラムの流れはイベントによって決定されます。イベントには、ユーザーアクション(マウスのクリックやキーの押下など)、システムによって生成される通知、または他のアプリケーションからのメッセージなどがあります。イベントベースのアプローチの主な側面は次のとおりです。
イベント:イベントは、プログラムにおける重要な出来事を表します。これには、ユーザーによる操作、データの変更、システムの他の部分からのメッセージなどが含まれます。たとえば、ボタンのクリックやファイルの読み込みによってイベントがトリガーされることがあります。
イベントリスナー:イベントに応答するために、プログラマーはイベントリスナー(またはハンドラー)を使用します。イベントリスナーは、特定のイベントが発生したときに実行されるように定義された関数またはメソッドです。たとえば、イベントリスナーは、ユーザーがボタンをクリックしたときに関数を実行するように設定できます。
非同期実行:イベントベースのモデルは、多くの場合、非同期プログラミングをサポートし、イベントが発生するのを待っている間、プログラムが応答性を維持できるようにします。 For example, a web application can continue to operate while waiting for data from a server.
非同期実行: イベントベースモデルは多くの場合、非同期プログラミングをサポートしており、イベントの発生を待機している間もプログラムは応答性を維持できます。たとえば、Webアプリケーションはサーバーからのデータを待機しながら動作を継続できます。
分離: イベントベースのアプローチは、プログラム内の異なる部分間の分離を促進します。コンポーネントは互いの実装の詳細を意識することなくイベントを介して通信できるため、コードのモジュール化が進み、保守が容易になります。
状態管理: イベントドリブンシステムでは、ユーザーインタラクションやイベントに応じてアプリケーションの状態が変化する可能性があるため、状態管理が極めて重要になります。アプリケーションが期待どおりに動作することを保証するため、適切な状態管理戦略がしばしば採用されます。
全体として、イベントベースのアプローチはプログラム内のインタラクションとワークフローを管理する強力な方法であり、応答性とユーザーインタラクションが求められるアプリケーションに特に効果的です。
XPSドキュメント変換中に発生するイベント
Aspose.Page APIを使用してXPSドキュメントの特定のページに変更を加える必要がある場合、通常はアクティブなドキュメント(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または画像に変換すると、プロセスはページごとに発生します。変換ジョブが次のページを処理する準備ができたら、「ページ前」のイベントをトリガーします。ユーザーは、 前にvevasingeventhandlerクラスを拡張することにより、このようなイベントの処理を定義することができ、この記事の紹介セクションで概説されているいくつかの利点を利用できます。
ナビゲーションハイパーリンクの追加例
ここでは、ナビゲーションハイパーリンクの場合に関連する例を示します。また、タスクをもう少し複雑にするために、すべてのページのサブセットのみをPDFに変換します。
イベントハンドラークラス
以下は、 前のeventeventhandler
クラスの拡張です。
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として保存するページを認識する必要があります。したがって、コンストラクターは、オプションの配列プロパティを引数として取得する必要があります。ページ番号の配列が指定されている場合、それらのソートされたコレクションを作成し、同時に複製を回避します。 (ところで、このソリューションは完全に正確ではありません。出力の矛盾を引き起こす可能性があるものを把握できますか?)HyperLinkテキストのフォントデータを含む「XPSFont」オブジェクトも必要です。
オーバーライドされた handle()
メソッドは、すべてが発生する場所です。メソッドの引数は、現在のページの変更API、XPSパッケージ内のドキュメント番号、すべてのドキュメントにわたって *絶対ページ番号 *、現在のドキュメント内の *相対ページ番号 *を含むオブジェクト(パッケージ内の1つのドキュメントの場合の場合の前の番号に等しい)、および *出力ページ番号 *(パッケージ全体を変換する絶対ページ番号に等しい)です。
次の2つの「if」ブロックのロジックは非常に単純です。これは、イベント引数「OutputPageNumber」の解析に基づいており、必要に応じて一部のリンクを省略します。つまり、「[First]」と「[Prev]」リンクは最初のページを除くすべての出力ページに追加され、「[Next]」と「[Last]」リンクは最後のページを除くすべてのページに表示されます。また、ページ番号が指定されているかどうかに関係なく、両方のケースに合わせてロジックが調整されています。
「if」ブロックの後、ページの右下隅にページ番号を追加するためのコードがあります。
最後の行では、PDFビューアのナビゲーションペインに表示されるページのアウトラインエントリを追加します(サポートされている場合)。
変換コード
「前の」イベントハンドラーが定義されたので、ドキュメントを変換するコードを書くことができます。
XPSファイルを開き、フォントデータファイルを使用してストリームオブジェクトをインスタンス化します。次に、「pdfsaveoptions」クラスのインスタンスを作成し、変換する必要があるページの数を指定します。次の行は、「前の」イベントハンドラーが、「前のPageventeventhandlers」コレクションオプションを介してコンバージョンジョブに「接続」される場所です。
ドキュメントの saveaspdf()
メソッドを使用して、PDFへの変換を実行するだけです。
結論
この記事では、プログラミングにおけるイベントベースのアプローチの重要なポイントを調査し、XPSドキュメントのページを変更するための直接的な方法を検討し、例としてナビゲーションハイパーリンクの挿入を使用して、変換プロセス中にすべての出力ページを *繰り返し *変更するためのより高度で洗練された手法を学びました。
完全な例については、 プロジェクトの例を調べてください。