Si estás haciendo una aplicación VCL (lo más común en C++ Builder), podés usar un TOleContainer para incrustar Acrobat Reader dentro del formulario (sí, como un objeto embebido de Office).
Pasos:
Agregá un TOleContainer al formulario.
código para cargar el PDF:
Código:
OleContainer1->CreateObjectFromFile("C:\\ruta\\a\\archivo.pdf", false);
OleContainer1->DoVerb(ovShow);
Esto abre el PDF incrustado en tu app usando el visor predeterminado de Windows (normalmente Adobe Reader o Edge).
Si el usuario no tiene visor PDF instalado, esto puede fallar.
Componentes de terceros (profesionales)
Hay librerías que cargan y renderizan PDFs sin necesidad de Adobe. Algunas opciones:
Debenu Quick PDF Library (muy potente)
WPViewPDF de WPCubed
Gnostice PDFtoolkit
PDFium (open source, pero más complejo de integrar en C++ Builder)
Algunos son pagos, pero tienen versiones de prueba o gratuitas limitadas.
¿Qué necesitas para usar PDFium en C++ Builder?
1. Descargar PDFium ya compilado
Podés bajar una versión precompilada aquí:
https://github.com/bblanchon/pdfium-binaries
Buscá la versión Windows x86 (32 bits) o x64, dependiendo de tu app.
Necesitarás al menos estos archivos:
pdfium.dll
fpdfview.dll.lib (opcional, si vas a hacer linking estático, pero puedes ignorar esto si usás LoadLibrary)
fpdfview.h (cabecera principal)
2. Crear el wrapper en C++ Builder
Primero necesitás cargar dinámicamente la DLL y mapear las funciones que vas a usar.
Cabecera: pdfium_wrapper.h
Código:
#ifndef PDFIUM_WRAPPER_H
#define PDFIUM_WRAPPER_H
#include <windows.h>
#include <fpdfview.h>
class PDFiumWrapper {
private:
HMODULE hPdfium;
bool loaded;
public:
PDFiumWrapper() : hPdfium(NULL), loaded(false) {}
bool LoadPDFium(const String& dllPath) {
hPdfium = LoadLibrary(dllPath.c_str());
if (!hPdfium)
return false;
FPDF_InitLibrary();
loaded = true;
return true;
}
void UnloadPDFium() {
if (loaded) {
FPDF_DestroyLibrary();
FreeLibrary(hPdfium);
loaded = false;
}
}
// Simple test: cargar documento
FPDF_DOCUMENT LoadPDF(const String& filePath) {
return FPDF_LoadDocument(filePath.c_str(), NULL);
}
~PDFiumWrapper() {
UnloadPDFium();
}
};
#endif
Ejemplo de uso en tu Formulario
Código:
#include "pdfium_wrapper.h"
PDFiumWrapper* pdfium;
void __fastcall TForm1::FormCreate(TObject *Sender) {
pdfium = new PDFiumWrapper();
if (!pdfium->LoadPDFium("pdfium.dll")) {
ShowMessage("Error cargando PDFium");
return;
}
FPDF_DOCUMENT doc = pdfium->LoadPDF("ejemplo.pdf");
if (!doc) {
ShowMessage("No se pudo abrir el PDF.");
} else {
ShowMessage("PDF cargado correctamente.");
FPDF_CloseDocument(doc);
}
}
void __fastcall TForm1::FormDestroy(TObject *Sender) {
delete pdfium;
}
Cosas importantes:
No renderiza automáticamente en un TImage. Tendrías que usar FPDF_RenderPageBitmap y dibujar en un HBITMAP o TBitmap.
Necesitás tener pdfium.dll junto al ejecutable.
Vamos a mostrar la primera página de un PDF en un TImage en C++ Builder, usando PDFium.
¿Qué necesitamos?
pdfium.dll en la misma carpeta que el .exe.
Cabecera fpdfview.h (ya incluida en el paso anterior).
Un TImage en tu Form.
PDFium cargado como en la clase PDFiumWrapper.
✨ Paso a paso para renderizar la primera página en un TImage
1. Agrega estos includes:
Código:
#include <fpdfview.h>
#include <fpdf_doc.h>
#include <fpdf_text.h>
#include <fpdf_dataavail.h>
#include <fpdf_formfill.h>
#include <fpdf_save.h>
#include <fpdfedit.h>
2. Crea un método que renderice:
Código:
void RenderPageToImage(FPDF_DOCUMENT doc, int pageIndex, TImage* image) {
FPDF_PAGE page = FPDF_LoadPage(doc, pageIndex);
if (!page) {
ShowMessage("No se pudo cargar la página.");
return;
}
int width = (int)FPDF_GetPageWidth(page);
int height = (int)FPDF_GetPageHeight(page);
// Ajustar tamaño del componente TImage
image->Width = width;
image->Height = height;
image->Picture->Bitmap->SetSize(width, height);
// Crear bitmap compatible con PDFium
FPDF_BITMAP bitmap = FPDFBitmap_Create(width, height, 0); // 0 = sin alpha
FPDFBitmap_FillRect(bitmap, 0, 0, width, height, 0xFFFFFFFF); // blanco
// Renderizar página al bitmap
FPDF_RenderPageBitmap(bitmap, page, 0, 0, width, height, 0, 0);
// Obtener buffer del bitmap
void* buffer = FPDFBitmap_GetBuffer(bitmap);
int stride = FPDFBitmap_GetStride(bitmap);
// Copiarlo a un TBitmap
Bitmap->PixelFormat = pf32bit;
for (int y = 0; y < height; ++y) {
void* dest = image->Picture->Bitmap->ScanLine[y];
void* src = (BYTE*)buffer + y * stride;
memcpy(dest, src, width * 4);
}
FPDFBitmap_Destroy(bitmap);
FPDF_ClosePage(page);
}
3. Llama al render desde ButtonClick:
Código:
void __fastcall TForm1::Button1Click(TObject *Sender) {
PDFiumWrapper* pdfium = new PDFiumWrapper();
if (!pdfium->LoadPDFium("pdfium.dll")) {
ShowMessage("No se pudo cargar PDFium");
return;
}
FPDF_DOCUMENT doc = pdfium->LoadPDF("ejemplo.pdf");
if (!doc) {
ShowMessage("No se pudo abrir el PDF");
return;
}
RenderPageToImage(doc, 0, Image1); // Página 0 en el TImage1
FPDF_CloseDocument(doc);
pdfium->UnloadPDFium();
delete pdfium;
}