איך לעבוד עם הערות PDF ב-C++
Aspose.PDF FOSS for C++ מייצגת כל הערת PDF (Annotation) כתת-מחלקה של מחלקת הבסיס המשותפת Annotation, וחושפת את ההערות בעמוד דרך AnnotationCollection המוחזר מ-Page::Annotations(). מדריך זה מוסיף לעמוד הערת טקסט פשוטה והערה מעוצבת באמצעות TextAnnotation, שומר את המסמך, פותח אותו מחדש כדי לקרוא את ההערות ולהסיר אחת מהן. ניתן להתקין את הספרייה מ-NuGet (Aspose.PDF.Cpp.FOSS) ב-Visual Studio, או לשלב אותה בפרויקט 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 מאשרת שהספרייה מקושרת.
שלב 2: ייבא מחלקות נדרשות
#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;שלב 3: צור מסמך והוסף דף
צור מסמך חדש והוסף אליו דף. PageCollection::Add() מחזיר את ה-Page החדש שנוסף:
Document doc;
Page page = doc.Pages().Add();שלב 4: הוסף הערת טקסט לדף
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);שלב 5: עצב הערה שנייה עם צבע, גבול ודגלים
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);שלב 6: שמור את המסמך
לא נכתב דבר לדיסק עד ש-Save() רץ:
doc.Save("annotated.pdf");שלב 7: פתח מחדש את קובץ ה-PDF וקרא את ההערות שלו
פתח מחדש את הקובץ השמור וקרא את ה-AnnotationCollection של הדף הראשון בחזרה. AnnotationCollection הוא מבוסס על 0, ו-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";
}
}שלב 8: הסר הערה ושמור מחדש
AnnotationCollection::Delete(index) מסיר הערה לפי המיקום שלה שמבוסס על 0. מחק את ההערה הראשונה ושמור את התוצאה לקובץ חדש:
annots.Delete(0);
reopened.Save("annotated-cleaned.pdf");בעיות נפוצות ופתרונות
לא קורה שינוי ב-PDF השמור לאחר הקריאה Annotations().Add()
שתי דברים נפוצים שיכולים להשתבש כאן. ראשית, PageCollection הוא מבוסס על 1 (doc.Pages()[1] הוא הדף הראשון) בעוד AnnotationCollection הוא מבוסס על 0 (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 הוא שדה ביטים, ולכן יש לשלב ערכים באמצעות bitwise OR, לדוגמה AnnotationFlags::Print | AnnotationFlags::ReadOnly.
האם מחיקת הערה מ-AnnotationCollection מסירה אותה מקובץ ה-PDF על הדיסק?
רק אחרי שה-Document::Save() רץ. Delete(), Remove() ו-Clear() משנים רק את האוסף בזיכרון — ה-PDF על הדיסק נשאר ללא שינוי עד שהמסמך נשמר.