نحوه کار با حاشیهنویسیهای PDF در C++
Aspose.PDF FOSS برای C++ هر حاشیهنویسی PDF را به عنوان یک زیرکلاس از کلاس پایهٔ مشترک Annotation نشان میدهد و حاشیهنویسیها را در یک صفحه از طریق AnnotationCollection که توسط Page::Annotations() برگردانده میشود، در دسترس میگذارد. این راهنما یک حاشیهنویسی یادداشت متنی ساده و یک حاشیهنویسی استایلدار را با TextAnnotation به یک صفحه اضافه میکند، سند را ذخیره مینماید، سپس آن را دوباره باز میکند تا حاشیهنویسیها را بخواند و یکی را حذف کند. کتابخانه به عنوان یک وابستگی زیرپوشهای در پروژهٔ CMake یکپارچه شده است — هیچ مرحلهٔ نصب از طریق رجیستری بسته وجود ندارد.
راهنمای گام به گام
گام 1: نصب بسته
کتابخانه را به عنوان یک زیرپوشهٔ CMake اضافه کنید و هدف کتابخانهٔ استاتیک را لینک کنید:
add_subdirectory(aspose.pdf-foss-for-cpp)
target_link_libraries(your_app PRIVATE aspose_pdf_foss)اطمینان حاصل کنید که زنجیره ابزار و مرحلهٔ لینک بهدرستی با یک برنامهٔ حداقل حل میشوند:
#include <aspose/pdf/document.hpp>
#include <iostream>
int main() {
Aspose::Pdf::Document doc;
std::cout << "Linked OK — pages: " << doc.Pages().Count() << "\n";
}یک ساخت موفق که pages: 0 را چاپ میکند، تأیید میکند که کتابخانه لینک شده است.
مرحله ۲: وارد کردن کلاسهای مورد نیاز
#include <aspose/pdf/document.hpp>
#include <aspose/pdf/page_collection.hpp>
#include <aspose/pdf/rectangle.hpp>
#include <aspose/pdf/color.hpp>
#include <aspose/pdf/annotations/annotation.hpp>
#include <aspose/pdf/annotations/annotation_collection.hpp>
#include <aspose/pdf/annotations/annotation_type.hpp>
#include <aspose/pdf/annotations/annotation_flags.hpp>
#include <aspose/pdf/annotations/border.hpp>
#include <aspose/pdf/annotations/border_style.hpp>
#include <aspose/pdf/annotations/text_annotation.hpp>
using namespace Aspose::Pdf;
using namespace Aspose::Pdf::Annotations;مرحله ۳: ایجاد یک سند و افزودن یک صفحه
یک سند جدید ایجاد کنید و یک صفحه به آن اضافه کنید. PageCollection::Add() سند تازه اضافهشده را Page برمیگرداند:
Document doc;
Page page = doc.Pages().Add();مرحله ۴: افزودن یک حاشیهنویسی متنی به صفحه
TextAnnotation بهصورت یک نظر به سبک یادداشت چسبی نمایش داده میشود. آن را از Document مالک ساخته، موقعیت آن را با Rect() تنظیم کنید و پیام آن را با Contents() تعیین کنید، سپس آن را به AnnotationCollection صفحه اضافه کنید:
TextAnnotation note{doc};
note.Rect(Rectangle(100.0, 700.0, 200.0, 720.0, false));
note.Contents("Reviewed and approved.");
page.Annotations().Add(note);مرحله ۵: استایلدهی به حاشیهنویسی دوم با رنگ، حاشیه و پرچمها
Annotation همچنین Color()، Border() و Flags() را در دسترس قرار میدهد. Flags() یک فیلد بیتی AnnotationFlags میگیرد — برای تنظیم بیش از یک پرچم همزمان، مقادیر را با عملگر OR بیتی ترکیب کنید:
TextAnnotation flagged{doc};
flagged.Rect(Rectangle(100.0, 600.0, 300.0, 650.0, false));
flagged.Contents("Needs follow-up");
flagged.Color(Color::FromRgb(220, 20, 20));
flagged.Flags(AnnotationFlags::Print | AnnotationFlags::ReadOnly);
flagged.Border().Width(2);
flagged.Border().Style(BorderStyle::Dashed);
page.Annotations().Add(flagged);مرحله ۶: ذخیرهسازی سند
هیچچیزی تا زمانی که Save() اجرا نشود، روی دیسک نوشته نمیشود:
doc.Save("annotated.pdf");مرحله ۷: باز کردن مجدد PDF و خواندن حاشیهنویسیهای آن
فایل ذخیرهشده را باز کنید و AnnotationCollection صفحه اول آن را مجدداً بخوانید. AnnotationCollection از صفر شروع میشود و Count() تعداد حاشیهنویسیهای موجود در صفحه را گزارش میدهد:
Document reopened("annotated.pdf");
auto& annots = reopened.Pages()[1].Annotations();
std::cout << "Annotation count: " << annots.Count() << "\n";
for (int i = 0; i < annots.Count(); ++i) {
const auto& a = annots[i];
if (a.AnnotationType() == AnnotationType::Text) {
std::cout << "Text annotation: " << a.Contents() << "\n";
}
}مرحله ۸: حذف یک حاشیهنویسی و ذخیره مجدد
AnnotationCollection::Delete(index) یک حاشیهنویسی را بر اساس موقعیت صفر-مبنایی آن حذف میکند. اولین حاشیهنویسی را حذف کنید و نتیجه را در یک فایل جدید ذخیره کنید:
annots.Delete(0);
reopened.Save("annotated-cleaned.pdf");مشکلات رایج و راهحلها
هیچچیزی در PDF ذخیرهشده پس از فراخوانی تغییر نمیکند Annotations().Add()
دو نکته معمولاً در اینجا اشتباه میشود. اول، PageCollection بر پایهٔ ۱ است (doc.Pages()[1] اولین صفحه است) در حالی که AnnotationCollection بر پایهٔ ۰ است (annots[0] اولین حاشیهنویسی است) — اشتباه در ترکیب دو طرح نمایهگذاری منجر به کار بر روی شیء اشتباه میشود. دوم، تأیید کنید که Document::Save() واقعاً پس از افزودن حاشیهنویسی اجرا میشود؛ تا آن زمان هیچچیزی روی دیسک نوشته نمیشود.
AnnotationCollection ایندکسینگ یا Delete(index) throws std::out_of_range
شاخصهای معتبر از 0 تا Count() - 1 هستند. ارسال یک شاخص منفی یا شاخصی برابر یا بزرگتر از Count() بهصورت پیشفرض استثنای std::out_of_range را پرتاب میکند. ابتدا Count() را فراخوانی کنید تا هر حلقه یا جستجویی محدود شود.
Remove() returns false دومین باری که آن را روی همان حاشیهنویسی فراخوانی میکنم
این یک خطا نیست. Remove() گزارش میدهد که آیا حاشیهنویسی به عنوان bool یافت شده و حذف شده است؛ فراخوانی دوباره آن روی حاشیهنویسیای که قبلاً حذف شده، عملی بیاثر است که false را برمیگرداند. به جای فرض اینکه Remove() همیشه موفق میشود، مقدار بازگشتی را بررسی کنید.
تنظیم مقدار جدید AnnotationFlags مقدار پرچمهایی را که قبلاً تنظیم کرده بودم پاک میکند
Flags(value) کل مجموعهٔ پرچمها را جایگزین میکند — با مقدار قبلی ادغام نمیشود. برای افزودن یا پاک کردن یک پرچم منفرد، ابتدا پرچمهای فعلی را بخوانید و با عملگرهای بیتی ترکیب کنید، برای مثال a.Flags(a.Flags() | AnnotationFlags::Print) برای افزودن یک پرچم، یا a.Flags(a.Flags() & ~AnnotationFlags::Print) برای پاک کردن یک پرچم در حالی که بقیه دستنخورده میمانند.
سوالات متداول
رابطهٔ Annotation، TextAnnotation و سایر زیرنوعهای حاشیهنویسی چیست؟
Annotation کلاس پایهٔ مشترک است. TextAnnotation و سایر انواع حاشیهنویسی واقعی هر کدام آن را برای یک زیرنوع حاشیهنویسی PDF تخصصی میکنند، در حالی که دسترسیهای Rect()، Contents()، Color()، Flags() و Border() کلاس پایه را به اشتراک میگذارند.
آیا حاشیهنویسیها به کل سند یا به یک صفحه محدود میشوند؟
هر صفحه AnnotationCollection خود را دارد که توسط متد Annotations() آن صفحه بازگردانده میشود. حاشیهنویسیها همیشه به صفحهای که به آن اضافه شدهاند محدود میشوند، نه به کل سند.
چگونه میتوانم تعداد حاشیهنویسیهای موجود در یک صفحه را شمارش کنم؟
متد Count() را بر روی AnnotationCollection که توسط Page::Annotations() بازگردانده میشود، فراخوانی کنید.
آیا یک حاشیهنویسی میتواند همزمان چاپپذیر و فقط-خواندنی باشد؟
بله. AnnotationFlags یک فیلد بیتی است، بنابراین مقادیر را با عملگر OR بیتی ترکیب کنید، برای مثال AnnotationFlags::Print | AnnotationFlags::ReadOnly.
آیا حذف یک حاشیهنویسی از AnnotationCollection آن را از فایل PDF روی دیسک حذف میکند؟
فقط پس از اجرای Document::Save(). Delete()، Remove() و Clear() فقط مجموعه در حافظه را تغییر میدهند — PDF روی دیسک تا زمان ذخیرهسازی سند بدون تغییر میماند.