examples/activex_cpp/collections2/collections2.cpp
130 lines
// ============================================================================
// collections2 -- C++ ActiveX (COM) port, GENERATED by
// tools/gen_activex_cpp_examples.py from examples/cpp/collections2/collections2.cpp
//
// DO NOT EDIT BY HAND unless you also fix the generator: the next run
// overwrites this file. If a case cannot be expressed mechanically, teach the
// generator the rule -- that is what keeps the other 87 honest.
//
// This drives the SAME engine as examples/cpp/collections2/collections2.cpp, but through the COM
// object wrappers/activex exposes rather than the flat C API, so it exercises
// the marshalling layer no compiled language exercised before.
// ============================================================================
#import "..\\..\\..\\wrappers\\activex\\LumasPdfAX.tlb" no_namespace named_guids
#include <windows.h>
#include <cstdio>
#include <cstring>
#include <string>
#include <vector>
// Output goes beside the EXECUTABLE, at the same relative path delphi's lands
// at, because tools/compare_lang_outputs.py keys on exactly that.
static std::string exeDir() {
char buf[MAX_PATH];
GetModuleFileNameA(nullptr, buf, MAX_PATH);
std::string s(buf);
size_t p = s.find_last_of("\\/");
return p == std::string::npos ? std::string(".") : s.substr(0, p);
}
// collections2 -- C++ port of examples\Vb6\collections2\collections2.bas
// Like collections, but adds sortable collection fields and per-item field
// values, then validates the collection.
#include "repo_root.h"
#include <cstdio>
#include <string>
static const char* TF = LUMAS_REPO_ROOT "/examples/test_files/";
// The Delphi original passes Delphi `string` (UnicodeString) to CreateNewPDF,
// OpenImportFile, CreateCollectionField, AttachFile and OpenOutputFile, so
// every one of those calls resolves to the WIDE overload rather than the *A
// twins used here before. (CreateColItemNumber has no W twin at all -- it stays
// ANSI here exactly as it is in the Delphi original.)
// wchar_t is wchar_t on Windows and char16_t elsewhere, so literals must use the
// header's own () macro -- a bare u"..." does not convert to wchar_t*
// under MSVC and a bare L"..." is 4 bytes wide off Windows.
#define W_(s) ((s))
static std::basic_string<wchar_t> WS(const std::string& s){
return std::basic_string<wchar_t>(s.begin(), s.end());
}
int main(int argc, char** argv) {
(void)argc; (void)argv;
if (FAILED(CoInitialize(nullptr))) return 1;
int _rc = 0;
try {
ILumasPDFPtr pdf;
if (FAILED(pdf.CreateInstance(L"LumasPdf.PDF")))
_com_issue_error(E_FAIL);
pdf->RaiseExceptions = VARIANT_TRUE;
pdf->CreateNewPDFW(W_("")); // The output file is opened later
pdf->SetImportFlags(ifImportAll | ifImportAsPage);
std::string cover = std::string(TF) + "collection_en.pdf";
if(pdf->OpenImportFileW((wchar_t*)WS(cover).c_str(), ptOpen, "") < 0){
printf("Input file \"%s\" not found!\n", cover.c_str());
return 0;
}
pdf->ImportPDFFile(1, 1.0, 1.0);
pdf->CloseImportFile();
pdf->CreateCollection(civTile);
// Add a user defined field Index so that we can sort in any order we want.
long ef = pdf->CreateCollectionFieldW(cisCustomNumber, 0, W_("File index"), "Index", 0, 1);
pdf->SetColSortField(ef, 1);
pdf->CreateCollectionFieldW(cisFileName, 1, W_("File name"), "", 1, 1);
pdf->CreateCollectionFieldW(cisSize, 2, W_("File size"), "", 1, 0);
pdf->CreateCollectionFieldW(cisModDate, 3, W_("Modification date"), "", 1, 0);
std::string taxform = std::string(TF) + "taxform.pdf";
std::string emf = std::string(TF) + "fulltest.emf";
std::string txt = std::string(TF) + "sample.txt";
ef = pdf->AttachFileW((wchar_t*)WS(taxform).c_str(), W_("A PDF file..."), 1);
pdf->SetColDefFile(ef);
pdf->CreateColItemNumber(ef, "Index", 0.0, "");
ef = pdf->AttachFileW((wchar_t*)WS(emf).c_str(), W_("An EMF file..."), 1);
pdf->CreateColItemNumber(ef, "Index", 1.0, "");
ef = pdf->AttachFileW((wchar_t*)WS(txt).c_str(), W_("A text file..."), 1);
pdf->CreateColItemNumber(ef, "Index", 2.0, "");
// Let's check whether the collection is valid.
pdf->CheckCollection();
std::string outFile;
if(pdf->HaveOpenDoc() != 0){
outFile = exeDir() + "/out.pdf";
if(pdf->OpenOutputFileW((wchar_t*)WS(outFile).c_str()) == 0){
return 0;
}
}
pdf->CloseFile();
printf("PDF Collection \"%s\" successfully created!\n", outFile.c_str());
return 0;
} catch (const _com_error& e) {
const _bstr_t d = e.Description();
if (d.length())
std::fprintf(stderr, "COM error 0x%08lx: %ws\n",
(unsigned long)e.Error(), (const wchar_t*)d);
else
std::fprintf(stderr, "COM error 0x%08lx: %s\n",
(unsigned long)e.Error(), e.ErrorMessage());
_rc = 1;
}
CoUninitialize();
return _rc;
}
This file is in the SDK at examples/activex_cpp/collections2/collections2.cpp.
The build fails if this page and that file ever differ.