使用 PDF 注释

使用 PDF 注释

在 Aspose.PDF FOSS for C++ 中,PDF 注释由 Annotation 基类及其具体子类型(TextAnnotation、LinkAnnotation、HighlightAnnotation、FreeTextAnnotation、CircleAnnotation、WatermarkAnnotation、WidgetAnnotation 等)表示。每页通过 Page.Annotations() 暴露其注释,该方法返回一个 AnnotationCollection。本指南涵盖向页面添加注释、遍历和删除注释、从现有文档读取注释、附加链接操作、自定义外观以及扁平化注释。


向页面添加注释

创建具体的注释实例,使用 Rectangle 对其进行定位,并通过 AnnotationCollection.Add() 将其添加到页面的集合中。TextAnnotation 表示一种固定在页面某点的便利贴式评论:

#include <aspose/pdf/document.hpp>
#include <aspose/pdf/annotations/text_annotation.hpp>
#include <aspose/pdf/rectangle.hpp>

int main() {
    Aspose::Pdf::Document doc("input.pdf");
    auto& page = doc.Pages()[1];

    Aspose::Pdf::Annotations::TextAnnotation note(doc);
    note.Rect(Aspose::Pdf::Rectangle(100.0, 700.0, 200.0, 720.0, false));
    note.Contents("Reviewed and approved");

    page.Annotations().Add(note);
    doc.Save("annotated.pdf");
}

Annotation.Contents() / Contents(value) 用于获取和设置注释文本,Annotation.Rect() / Rect(value) 用于在页面上定位注释。


遍历和删除注释

AnnotationCollection 支持计数、索引访问、成员检查以及通过值或索引进行删除:

#include <aspose/pdf/document.hpp>

int main() {
    Aspose::Pdf::Document doc("input.pdf");
    auto& annotations = doc.Pages()[1].Annotations();

    std::cout << "Annotation count: " << annotations.Count() << "\n";

    for (int i = 0; i < annotations.Count(); ++i) {
        std::cout << "Contents: " << annotations[i].Contents() << "\n";
    }

    if (annotations.Count() > 0) {
        annotations.Delete(0);   // remove by index
    }
    annotations.Clear();         // remove everything
}

AnnotationCollection.Contains(annotation) 和 Remove(annotation) 在特定的注释引用上操作;Delete(index) 按位置删除,Delete(annotation) 在不需要索引的情况下删除特定注释。IsReadOnly() 报告集合是否可以被修改。


从现有文档读取注释

当文档被加载时,其注释已经被填充,可直接检查,无需添加任何内容。Annotation.AnnotationType() 报告子类型(AnnotationType::Text、AnnotationType::Highlight、AnnotationType::Link、AnnotationType::FreeText、AnnotationType::FileAttachment、AnnotationType::Watermark 等):

#include <aspose/pdf/document.hpp>
#include <aspose/pdf/annotations/annotation_type.hpp>

int main() {
    Aspose::Pdf::Document doc("annotated.pdf");
    auto& annotations = doc.Pages()[1].Annotations();

    for (int i = 0; i < annotations.Count(); ++i) {
        auto& a = annotations[i];
        if (a.AnnotationType() == Aspose::Pdf::Annotations::AnnotationType::Text) {
            std::cout << "Note: " << a.Contents() << "\n";
        }
    }
}

注释的顺序和子类型在保存/重新加载的往返过程中保持不变,因此在加载文档后对 Annotations() 进行索引的代码会看到与文件写入时相同的序列。


链接注释和操作

LinkAnnotation 将可点击区域附加到页面,并在激活时分发一个 PdfAction。NamedAction 跳转到预定义的导航目标,JavascriptAction 运行 ECMAScript 字符串,SubmitFormAction 通过 FileSpecification 将表单数据发送到 URL:

#include <aspose/pdf/document.hpp>
#include <aspose/pdf/annotations/link_annotation.hpp>
#include <aspose/pdf/annotations/named_action.hpp>
#include <aspose/pdf/annotations/predefined_action.hpp>
#include <aspose/pdf/rectangle.hpp>

int main() {
    Aspose::Pdf::Document doc;
    auto page = doc.Pages().Add();

    Aspose::Pdf::Annotations::LinkAnnotation link(
        page, Aspose::Pdf::Rectangle(0.0, 0.0, 100.0, 20.0, false));
    link.Action(Aspose::Pdf::Annotations::NamedAction(
        Aspose::Pdf::Annotations::PredefinedAction::LastPage));

    page.Annotations().Add(link);
    doc.Save("linked.pdf");
}

LinkAnnotation.Action(value) 接受任何 PdfAction 子类型并在内部克隆它,因此注释保留其操作的副本。LinkAnnotation.Destination() / Destination(value) 设置显式的导航目标而非操作,Highlighting() / Highlighting(value) 控制链接被点击时显示的视觉反馈。


注释外观:边框、标志和颜色

每个 Annotation 都公开一个 Border、一个由 AnnotationFlags 组成的位字段,以及一个用于渲染其外观的 Color:

#include <aspose/pdf/annotations/border_style.hpp>
#include <aspose/pdf/annotations/annotation_flags.hpp>
#include <aspose/pdf/color.hpp>

// 'note' is an existing Annotation reference, e.g. from AnnotationCollection.
note.Border().Width(2);
note.Border().Style(Aspose::Pdf::Annotations::BorderStyle::Dashed);
note.Flags(Aspose::Pdf::Annotations::AnnotationFlags::Print);
note.Color(Aspose::Pdf::Color::Red());

Border.Style() 接受 BorderStyle::Solid、Dashed、Beveled、Inset 或 Underline。Border.Effect() 还支持一个带有 EffectIntensity() 用于控制其突出程度的 BorderEffect::Cloudy 轮廓。AnnotationFlags 是一个位字段——将诸如 Print、NoZoom、ReadOnly 和 LockedContents 等值组合起来,以控制注释在查看器中的行为,而不改变其可见内容。


扁平化注释

通过直接调用 Annotation.Flatten(),可以将单个注释扁平化——合并到页面内容中并使其不可交互——:

#include <aspose/pdf/document.hpp>

int main() {
    Aspose::Pdf::Document doc("annotated.pdf");
    auto& annotations = doc.Pages()[1].Annotations();
    for (int i = 0; i < annotations.Count(); ++i) {
        annotations[i].Flatten();
    }
    doc.Save("flattened.pdf");
}

对于全文档的注释操作,PdfAnnotationEditor 遵循在整个 API 中使用的共享 Facade 模式:使用 BindPdf() 绑定源文档,应用一个或多个注释操作,然后使用 Save() 写入结果:

#include <aspose/pdf/facades/pdf_annotation_editor.hpp>

int main() {
    Aspose::Pdf::Facades::PdfAnnotationEditor editor;
    editor.BindPdf("annotated.pdf");
    editor.FlatteningAnnotations();
    editor.Save("flattened.pdf");
}

PdfAnnotationEditor.DeleteAnnotations() 删除绑定文档中的所有注释;DeleteAnnotations(annotType) 将删除限制为单个 AnnotationType。ImportAnnotationsFromXfdf(xfdfFile) 和 ImportAnnotationsFromFdf(fdfFile) 加载从其他 PDF 查看器导出的注释数据。


技巧与最佳实践

  • 在调用 Document.Save() 之前,请务必将新创建的注释添加到 Page.Annotations() —— 未添加到集合中的注释不会写入输出文件。
  • 如果不确定注释仍然存在,请在调用 Remove() 之前使用 AnnotationCollection.Contains(annotation);当注释缺失时,Remove() 返回 false 而不是抛出异常。
  • 在遍历从不可信或第三方 PDF 文件加载的注释时,在进行子类型行为的强制转换或分支之前,请检查 Annotation.AnnotationType()。
  • 在归档文档之前使用 Annotation.Flatten()(或对整个文档使用 PdfAnnotationEditor.FlatteningAnnotations())扁平化注释,这样其他工具的审阅者能够看到您所创建的相同外观。
  • AnnotationFlags 是位域——请将标志与枚举的底层整数值组合,而不要假设一次只能激活一个标志。

常见问题

问题原因修复
保存后注释未显示注释已构造但从未添加到 Page.Annotations()在 doc.Save() 之前调用 page.Annotations().Add(annotation)
Remove() 返回 false传入的注释引用与当前集合中的条目不匹配首先使用 Contains(),或使用 Delete(index) 按索引删除
重新加载后注释类型错误代码在未检查 AnnotationType() 的情况下假设了特定子类型在将对象视为特定子类型之前,先对 Annotation.AnnotationType() 进行分支判断
链接操作在赋值后似乎未设置本地 PdfAction 超出作用域;LinkAnnotation.Action() 返回注释的克隆副本,而不是原始对象通过 link.Action() 读取操作,而不是保留原始的本地变量
PdfAnnotationEditor 操作无效BindPdf() 未被调用,或是使用了不存在的路径进行调用在调用 FlatteningAnnotations() 或 DeleteAnnotations() 之前,请确认 BindPdf() 成功

FAQ

如何向 PDF 页面添加评论式注释?

使用目标 Document 构造一个 TextAnnotation,设置其 Rect() 和 Contents(),然后在保存前将其添加到 page.Annotations()。

我如何查明我正在查看的注释类型?

调用 Annotation.AnnotationType(),它返回一个 AnnotationType 枚举值,例如 Text、Link、Highlight、FreeText、FileAttachment 或 Watermark。

一个注释可以携带多个标志吗?

是的。AnnotationFlags 是一个位字段(Default、Invisible、Hidden、Print、NoZoom、ReadOnly、LockedContents 等),因此可以在单个注释上组合多个标志。

将单个注释扁平化和将整个文档扁平化有什么区别?

Annotation.Flatten() 将单个注释合并到其页面内容中。PdfAnnotationEditor.FlatteningAnnotations()(可通过页面范围以及通过接受 start、end 和 annotType 的重载来使用 AnnotationType 进行范围限定)一次调用即可在整个绑定文档上进行扁平化。

我如何从文档中移除所有某种类型的注释?

使用 PdfAnnotationEditor.BindPdf() 绑定文档,调用带有目标 AnnotationType 的 DeleteAnnotations(annotType),然后 Save() 结果。


API Reference 摘要

类/方法描述
Annotation所有 PDF 注释子类型的抽象基类
Annotation.Rect() / Rect(value)获取或设置注释的边界矩形
Annotation.Contents() / Contents(value)获取或设置注释的文本内容
Annotation.AnnotationType()返回此注释的 AnnotationType 枚举值
Annotation.Flags() / Flags(value)获取或设置 AnnotationFlags 位字段
Annotation.Border() / Border(value)获取或设置注释的 Border
Annotation.Color() / Color(value)获取或设置注释的显示 Color
Annotation.Flatten()将此注释合并到页面内容中,使其不可交互
AnnotationCollection页面上注释的有序集合,由 Page.Annotations() 返回
AnnotationCollection.Add(annotation) / Add(annotation, considerRotation)向集合中添加注释
AnnotationCollection.Count()返回集合中注释的数量
AnnotationCollection.Contains(annotation)报告集合是否持有给定的注释
AnnotationCollection.Remove(annotation)删除特定注释;如果未找到则返回 false
AnnotationCollection.Delete(index) / Delete(annotation)按索引或按引用删除注释
AnnotationCollection.Clear()从集合中删除所有注释
TextAnnotation带有 Open() 和 Icon()(TextIcon)的便签式注释
LinkAnnotation可点击区域通过 Action() / Action(value) 调度 PdfAction
LinkAnnotation.Destination() / Destination(value)获取或设置显式导航目标
HighlightAnnotation使用高亮颜色标记文本片段
FreeTextAnnotation显示文本标注;通过 Justification()、DefaultAppearanceObject()、Callout() 进行配置
CircleAnnotation在注释的矩形内绘制椭圆
WatermarkAnnotation覆盖注释,使用 Opacity() / Opacity(value) 访问器
WidgetAnnotation表单字段外观注释,使用 ReadOnly()、Required()、Exportable()、DefaultAppearance()
NamedAction可附加到 LinkAnnotation 的预定义导航操作(PredefinedAction 枚举)
JavascriptAction通过 Script() / GetECMAScriptString() 运行 ECMAScript 字符串
SubmitFormAction通过 Url() / Url(value) 将表单数据提交至 FileSpecification URL
Border注释边框使用 Width()、Style()(BorderStyle)、Effect()(BorderEffect)
PdfAnnotationEditor用于文档范围内注释导入、修改、扁平化和删除的外观
PdfAnnotationEditor.FlatteningAnnotations()在已绑定的文档中扁平化注释
PdfAnnotationEditor.DeleteAnnotations(annotType)删除给定 AnnotationType 的所有批注
PdfAnnotationEditor.ImportAnnotationsFromXfdf(xfdfFile)从 XFDF 文件导入批注

另请参阅

 中文