examples/activex_cpp/signature_ap/signature_ap.cpp
99 lines
// ============================================================================
// signature_ap -- C++ ActiveX (COM) port, following
// examples/activex/signature_ap/signature_ap.vbs
//
// Builds a signature field with a CUSTOM APPEARANCE drawn using ordinary PDF
// operators -- two axial shadings clipped to a rectangle and an ellipse, plus
// text -- and then signs the file with a self-signed certificate.
//
// CreateSigFieldAP opens an appearance TEMPLATE; everything between it and
// EndTemplate is drawn into that template, not onto the page. The validation
// icon is placed BEFORE the appearance is created: its unscaled size is always
// 100x100 units and it must sit fully inside the template.
// ============================================================================
#import "..\\..\\wrappers\\activex\\LumasPdfAX.tlb" no_namespace named_guids
#include <windows.h>
#include "axcommon.h"
#include <cstdio>
#include <string>
// NO_COLOR is a type-library enumerator; local re-declaration is C2365.
// The engine's colour order is 0x00BBGGRR, which is what r + g*256 + b*65536 is.
static long RGBv(long r, long g, long b) { return r + g * 256 + b * 65536; }
int main() {
ChdirToExe();
ComInit com;
if (!com.ok()) return 1;
ILumasPDFPtr pdf;
if (FAILED(pdf.CreateInstance(L"LumasPdf.PDF"))) return 1;
pdf->RaiseExceptions = VARIANT_FALSE;
pdf->CreateNewPDFW(B(""));
pdf->Append();
pdf->SetFontW(B("Arial"), fsNone, 14, VARIANT_TRUE, cp1252);
std::string body =
"This file is digitally signed with a self sign certificate. "
"The appearance of the signature field is created with normal PDF functions. However, it "
"would also be possible to import a PDF page, an EMF file, or an image into the "
"appearance template.";
body += '\n'; body += '\n';
body +=
"When creating an individual signature appearance make sure to place the validation icon "
"properly with PlaceSigFieldValidateIcon(). The unscaled size of that icon is always "
"100.0 x 100.0 Units and it must be placed fully inside the appearance template.";
pdf->WriteFTextW(taLeft, B(body));
long sigField = pdf->CreateSigField(B("Signature"), -1, 200, 500, 200, 80);
pdf->SetFieldColor(sigField, fcBorderColor, csDeviceRGB, NO_COLOR);
pdf->PlaceSigFieldValidateIcon(sigField, 0, 15, 50, 50);
pdf->CreateSigFieldAP(sigField);
pdf->SaveGraphicState();
pdf->Rectangle(0, 0, 200, 80, fmNoFill);
pdf->ClipPath(cmWinding, fmNoFill);
long sh = pdf->CreateAxialShading(0, 0, 200, 0, 0.5, RGBv(120, 120, 220),
RGBv(255, 255, 255), VARIANT_TRUE, VARIANT_TRUE);
pdf->ApplyShading(sh);
pdf->RestoreGraphicState();
pdf->SaveGraphicState();
pdf->Ellipse(50.5, 1, 148.5, 78, fmNoFill);
pdf->ClipPath(cmWinding, fmNoFill);
sh = pdf->CreateAxialShading(0, 0, 0, 78, 2, RGBv(255, 255, 255),
RGBv(120, 120, 220), VARIANT_TRUE, VARIANT_TRUE);
pdf->ApplyShading(sh);
pdf->RestoreGraphicState();
pdf->SetFontW(B("Arial"), fsBold | fsUnderlined, 11, VARIANT_TRUE, cp1252);
pdf->SetFillColor(RGBv(120, 120, 220));
pdf->WriteFTextExW(50, 60, 150, -1, taCenter, B("Digitally signed by:"));
pdf->SetFontW(B("Arial"), fsBold | fsItalic, 18, VARIANT_TRUE, cp1252);
pdf->SetFillColor(RGBv(100, 100, 200));
pdf->WriteFTextExW(50, 45, 150, -1, taCenter, B("LumasPdf"));
pdf->EndTemplate();
pdf->EndPage();
std::string outFile = OutFile();
if (pdf->HaveOpenDoc())
if (!pdf->OpenOutputFileW(B(outFile))) {
std::printf("OpenOutputFile failed\n");
return 1;
}
std::string cert = OutFile("test_cert.pfx");
if (pdf->CloseAndSignFile(B(cert), B("123456"), B("Test"), B("")))
std::printf("PDF file \"%s\" successfully created and signed!\n", outFile.c_str());
else
std::printf("CloseAndSignFile failed: %ws\n",
(const wchar_t*)pdf->GetLastErrorMessage());
return 0;
}
This file is in the SDK at examples/activex_cpp/signature_ap/signature_ap.cpp.
The build fails if this page and that file ever differ.