如果您需要为一个在编辑器上已经打开的PDF的多个页面添加注释, 需要注意的事,开发包示例中的接口为FRPageViewAddAnnot(),只能对已加载过视图的(用户浏览过的)页面添加注释。如果要对还未加载的页面添加注释,可以使用FRDocAddAnnot()接口添加注释。
示例代码如下:
void CreateAnnot()
{
FS_FloatPoint pointLeftTop, pointRightBottom;
pointLeftTop.m_PointX = 100;
pointRightBottom.m_PointX = 400;
pointLeftTop.m_PointY = 200;
pointRightBottom.m_PointY=100;
FR_Document frDocument = FRAppGetActiveDocOfPDDoc();
FPD_Document fpdDocument = FRDocGetPDDoc(frDocument);
FR_DocView frDocView = FRDocGetCurrentDocView(frDocument);
FR_PageView frPageView = FRDocViewGetCurrentPageView(frDocView);
for (int i = 0; i < FPDDocGetPageCount(fpdDocument); i++)
{
FS_FloatRect rectFirst;
rectFirst.left = pointLeftTop.m_PointX;
rectFirst.right = pointRightBottom.m_PointX;;
rectFirst.bottom = pointRightBottom.m_PointY;
rectFirst.top = pointLeftTop.m_PointY;
FR_Annot frAnnot = FRDocAddAnnot(frDocument, i, "Stamp", rectFirst);
FPD_Annot fpdAnnot = FRAnnotGetPDFAnnot(frAnnot);
FR_Page frPage = FRDocGetPage(frDocument, i);
FPD_Page fpdPage = FPDPageNew();
FPD_Object pPageDict = FPDDocGetPage(fpdDocument, i);
FPDPageLoad(fpdPage, fpdDocument, pPageDict, TRUE);
FPD_Object fpdObject =
FPDAnnotGetAnnotDict(fpdAnnot);// FPDDictionaryNew();
//set subtype of the annot
FPD_Object fpdfstringAnnot = FPDNameNew("Annot");
FPDDictionaryAddValue(fpdObject, "Type", fpdfstringAnnot);
FPDDictionaryAddValue(fpdObject, "Subtype", FPDNameNew("Stamp"));
FPDDictionaryAddValue(fpdObject, "Subj", FPDStringNew(FSByteStringNew3("Stamp", -1), 0));
//set quadpoints of the annot
FPD_Object quad = FPDArrayNew(); //{x1, y1, x2, y2, x3, y3, x4, y5}
FPDArrayAddNumber(quad, rectFirst.left); //x1
FPDArrayAddNumber(quad, rectFirst.top);//y1
FPDArrayAddNumber(quad, rectFirst.right);//x2
FPDArrayAddNumber(quad, rectFirst.top);//y2
FPDArrayAddNumber(quad, rectFirst.left);//x3
FPDArrayAddNumber(quad, rectFirst.bottom);//y3
FPDArrayAddNumber(quad, rectFirst.right);//x4
FPDArrayAddNumber(quad, rectFirst.bottom);//y4
FPDDictionaryAddValue(fpdObject, "QuadPoints", quad);
FPDDictionaryAddValue(fpdObject, "NM", FPDNameNew("TextName"));
FPDDictionaryAddValue(fpdObject, "T", FPDNameNew("AuthorTest"));
FPD_Object quadColor = FPDArrayNew();
FS_COLORREF color = RGB(255, 215, 0);
//set color of the annot
FPDArrayAddNumber(quadColor, (FS_FLOAT)GetRValue(color) / 255.0f); //1 means RGB Color
FPDArrayAddNumber(quadColor, (FS_FLOAT)GetGValue(color) / 255.0f); //Defines the color
FPDArrayAddNumber(quadColor, (FS_FLOAT)GetBValue(color) / 255.0f); //Defines the color
FPDDictionaryAddValue(fpdObject, "C", quadColor);
FS_LPCWSTR ws = (FS_LPCWSTR)L"This is initial text";
FPD_Object fpdfstringPopout = FPDStringNewW(ws);
//set comment info of the annot
FPDDictionaryAddValue(fpdObject, "Contents", fpdfstringPopout);
//set BBox of the annot
FPDDictionarySetAtRect(fpdObject, "Rect", rectFirst);
auto pAPDict = FPDDictionaryGetDict(fpdObject, "AP");
if (pAPDict == nullptr)
{
pAPDict = FPDDictionarySetNewAt(fpdObject, "AP", FPD_OBJ_DICTIONARY);
}
FS_DWORD dwApObjNum = 0;
FS_DIBitmap pBitmap = FSDIBitmapLoadFromPNGIcon(L"D:\\test\\thumbnail_image001.png");
FPD_Object pObj = CreateAppearanceDict(fpdDocument, pBitmap, 0, &dwApObjNum);
FPDDictionarySetAtReferenceToDoc(pAPDict, "N", fpdDocument, dwApObjNum);
FPDDictionaryAddValue(fpdObject, "AP", pAPDict);
//将新增注释添加到侧边栏的注释列表中
if (frAnnot != NULL)
{
FR_MarkupPanel panel = FRMarkupPanelGetMarkupPanel();
if (panel)
{
FRMarkupPanelAddAnnot(panel, frAnnot, TRUE, TRUE);
}
}
}
//刷新当前页面,让注释显示
FRDocReloadPage(frDocument, FRPageViewGetPageIndex(FRDocViewGetCurrentPageView(frDocView)), FALSE);
}
上面这个示例是添加的”图章”注释,所以会用到。如果是其他类型注释例如”高亮”不一定需要下面的代码
//添加注释外观
FPD_Object CreateAppearanceDict(FPD_Document pdfDoc, FS_DIBitmap bitmap, int nRotate, FS_DWORD* pObjNum)
{
if (!pdfDoc || !bitmap)
return nullptr;
FS_DWORD dwNewObjNumber = 0;
FPD_Object apperenceDict = FPDDictionaryNew();
FS_AffineMatrix streamMatrix;
switch (nRotate)
{
case 0:
{
streamMatrix.a = 1.0f;
streamMatrix.b = 0.0f;
streamMatrix.c = 0.0f;
streamMatrix.d = 1.0f;
}
break;
case 90:
{
streamMatrix.a = 0.0f;
streamMatrix.b = 1.0f;
streamMatrix.c = -1.0f;
streamMatrix.d = 0.0f;
}
break;
case 180:
{
streamMatrix.a = -1.0f;
streamMatrix.b = 0.0f;
streamMatrix.c = 0.0f;
streamMatrix.d = -1.0f;
}
break;
case 270:
{
streamMatrix.a = 0.0f;
streamMatrix.b = -1.0f;
streamMatrix.c = 1.0f;
streamMatrix.d = 0.0f;
}
break;
default:
break;
}
streamMatrix.e = 0;
streamMatrix.f = 0;
FPDDictionarySetAtMatrix(apperenceDict, "Matrix", streamMatrix);
FPD_Object resourcesDict = FPDDictionaryNew();
FPD_Object xObject = FPDDictionaryNew();
FPD_Image image = FPDImageNew(pdfDoc);
//ON_SCOPE_EXIT([&] {
//});
FPDImageSetImage(image, bitmap, FALSE, nullptr);
FPD_Object imgStream = FPDImageGetStream(image);
if (imgStream)
{
dwNewObjNumber = FPDDocAddIndirectObject(pdfDoc, imgStream);
FPDDictionarySetAtReferenceToDoc(xObject, "ImgSignature", pdfDoc, dwNewObjNumber);
}
FPDDictionarySetAt(resourcesDict, "XObject", xObject, nullptr);
FPD_Object extGStateDict = FPDDictionaryNew();
FPDDictionarySetAtNumber(extGStateDict, "CA", 1);
FPDDictionarySetAtNumber(extGStateDict, "ca", 1);
FS_DWORD dwNewExtGStateObjNumber = FPDDocAddIndirectObject(pdfDoc, extGStateDict);
FPD_Object extGStateDictRef = FPDDictionaryNew();
FPDDictionarySetAtReferenceToDoc(extGStateDictRef, "FXE1", pdfDoc, dwNewExtGStateObjNumber);
FPDDictionarySetAt(resourcesDict, "ExtGState", extGStateDictRef, nullptr);
FPDDictionarySetAt(apperenceDict, "Resources", resourcesDict, nullptr);
int bmpWidth = FSDIBitmapGetWidth(bitmap);
int bmpHeight = FSDIBitmapGetHeight(bitmap);
FPD_Object streamBBox = FPDArrayNew();
FPDArrayAddNumber(streamBBox, 0);
FPDArrayAddNumber(streamBBox, 0);
FPDArrayAddNumber(streamBBox, bmpWidth);
FPDArrayAddNumber(streamBBox, bmpHeight);
FPDDictionarySetAt(apperenceDict, "BBox", streamBBox, nullptr);
FPDDictionarySetAtName(apperenceDict, "Type", "XObject");
FPDDictionarySetAtName(apperenceDict, "Subtype", "Form");
FS_ByteString apStreamData = FSByteStringNew();
FSByteStringFormat(apStreamData, "q\n/FXE1 gs\n%d 0 0 %d 0 0 cm\n/ImgSignature Do\nQ", bmpWidth, bmpHeight);
auto pNewContents = FPDStreamNew();
FPDStreamInitStream(pNewContents, NULL, 0, apperenceDict);
FPDStreamSetData(pNewContents, (FS_LPBYTE)FSByteStringCastToLPCBYTE(apStreamData),
FSByteStringGetLength(apStreamData), FALSE, FALSE);
auto dwObjNum = FPDDocAddIndirectObject(pdfDoc, pNewContents);
if (pObjNum)
*pObjNum = dwObjNum;
FSByteStringDestroy(apStreamData);
FPDImageDestroy(image);
return pNewContents;
}
效果如下:
![](https://support.foxitsoftware.cn/wp-content/uploads/2024/07/image-19.png)