Examples / metafiles / activex_cpp

Metafiles

A complete, runnable activex_cpp program — 87 lines, shipped in your download.

Demonstrates Images

Same example, other languages: c cpp cpp_linux csharp python vbnet

examples/activex_cpp/metafiles/metafiles.cpp 87 lines
// ============================================================================
//  metafiles -- C++ ActiveX (COM) port, following
//  examples/activex/metafiles/metafiles.vbs
//
//  Places three EMF metafiles, each centred and scaled onto its own landscape
//  page, with a red frame drawn around the placed extent.
//
//  GetLogMetafileSize returns a TRectL in the flat API. On the COM surface that
//  record is EXPLODED into four separate out-parameters, so no struct crosses
//  the boundary at all -- four OutVars is the whole of it.
// ============================================================================
#import "..\\..\\wrappers\\activex\\LumasPdfAX.tlb" no_namespace named_guids

#include <windows.h>

#include "axcommon.h"

#include <cstdio>
#include <string>

static const long CLR_RED = 255;
static const double MARGIN = 10.0;
static const char* SRC_DIR = "E:\\LUMASPDFSDK\\examples\\test_files";

static ILumasPDFPtr pdf;

static void PlaceEMFCentered(const std::string& mFile, double width, double height) {
    OutVar l, t, r, b;
    pdf->GetLogMetafileSize(B(mFile), l.Addr(), t.Addr(), r.Addr(), b.Addr());
    double w = (double)(r.AsLong() - l.AsLong());
    double h = (double)(b.AsLong() - t.AsLong());
    width -= 2.0 * MARGIN;
    height -= 2.0 * MARGIN;
    double sx = width / w;
    if (h * sx <= height) {
        double x = MARGIN;
        h = h * sx;
        double y = (height - h) / 2.0;
        pdf->InsertMetafile(B(mFile), x, y, width, 0.0);
        pdf->SetStrokeColor(CLR_RED);
        pdf->Rectangle(x, y, width, h, fmStroke);
    } else {
        sx = height / h;
        w = w * sx;
        double x = (width - w) / 2.0;
        double y = MARGIN;
        pdf->InsertMetafile(B(mFile), x, y, 0.0, height);
        pdf->SetStrokeColor(CLR_RED);
        pdf->Rectangle(x, y, w, height, fmStroke);
    }
}

int main() {
    ChdirToExe();
    ComInit com;
    if (!com.ok()) return 1;
    int rc = 0;
    try {
        if (FAILED(pdf.CreateInstance(L"LumasPdf.PDF"))) _com_issue_error(E_FAIL);
        pdf->RaiseExceptions = VARIANT_TRUE;

        std::string outFile = OutFile();

        pdf->CreateNewPDFA(B(""));
        pdf->SetPageCoords(pcTopDown);

        static const char* EMFS[] = {"\\coords.emf", "\\fulltest.emf", "\\gdi.emf"};
        for (int i = 0; i < 3; ++i) {
            pdf->Append();
            pdf->SetOrientationEx(90);
            PlaceEMFCentered(std::string(SRC_DIR) + EMFS[i],
                             pdf->GetPageWidth(), pdf->GetPageHeight());
            pdf->EndPage();
        }

        if (pdf->HaveOpenDoc()) pdf->OpenOutputFileA(B(outFile));
        if (pdf->CloseFile())
            std::printf("PDF file \"%s\" successfully created!\n", outFile.c_str());
    } catch (const _com_error& e) {
        const _bstr_t d = e.Description();
        std::fprintf(stderr, "%ws\n", d.length() ? (const wchar_t*)d : L"COM error");
        rc = 1;
    }
    pdf = nullptr;
    return rc;
}

This file is in the SDK at examples/activex_cpp/metafiles/metafiles.cpp. The build fails if this page and that file ever differ.