使用 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 文件导入批注 |