Examples / metafiles_gui / activex_cpp

Metafiles Gui

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

Demonstrates Images

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

examples/activex_cpp/metafiles_gui/metafiles_gui.cpp 83 lines
// ============================================================================
//  metafiles_gui -- C++ ActiveX (COM) port, following
//  examples/activex/metafiles_gui/metafiles_gui.vbs
//
//  The original is a GUI app: a tree of metafile records, a paintbox and zoom
//  controls. That UI is dropped here (headless), as the VBScript sibling does --
//  what remains is the part that actually exercises the engine: load an EMF,
//  place it centred on a page with the default conversion flags, write out.pdf.
//
//  The VB6 mirror used a fixed in.emf that is not in the tree; a real metafile
//  from test_files is used instead, matching the sibling.
// ============================================================================
#import "..\\..\\wrappers\\activex\\LumasPdfAX.tlb" no_namespace named_guids

#include <windows.h>

#include "axcommon.h"

#include <cstdio>
#include <string>

static const double MARGIN = 10.0;
static const char* IN_FILE = "E:\\LUMASPDFSDK\\examples\\test_files\\coords.emf";

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) {
        pdf->InsertMetafile(B(mFile), MARGIN, MARGIN, width, 0.0);
    } else {
        sx = height / h;
        w = w * sx;
        double x = MARGIN + (width - w) / 2.0;
        pdf->InsertMetafile(B(mFile), x, MARGIN, 0.0, height);
    }
}

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->SetCompressionFilter(cfFlate);
        pdf->SetJPEGQuality(70);

        pdf->CreateNewPDFA(B(""));
        pdf->SetCompressionLevel(clNone);
        pdf->SetCompressionFilter(cfFlate);
        pdf->SetColorSpace(csDeviceRGB);
        pdf->SetMetaConvFlags(mfDefault);
        pdf->SetPageCoords(pcTopDown);
        pdf->Append();
        pdf->SetResolution(300);
        pdf->SetJPEGQuality(70);
        PlaceEMFCentered(IN_FILE, pdf->GetPageWidth(), pdf->GetPageHeight());
        pdf->EndPage();

        if (pdf->HaveOpenDoc())
            if (pdf->OpenOutputFileA(B(outFile)))
                if (pdf->CloseFile())
                    std::printf("OK: %s\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_gui/metafiles_gui.cpp. The build fails if this page and that file ever differ.