Después de unos cuantos días peleando, y con ayuda de internet, conseguí un código que funciona. Son estas cuatro funciones:
1.Establece la configuración de Bullzip
Código:
HRESULT BullzipSetValue(IDispatch *Objeto, const wchar_t *Parametro, const wchar_t *Valor)
{
VARIANT argumentos[2];
VariantInit(&argumentos[0]);
VariantInit(&argumentos[1]);
// Los argumentos se pasan en orden inverso.
argumentos[1].vt = VT_BSTR;
argumentos[1].bstrVal = SysAllocString(Parametro);
argumentos[0].vt = VT_BSTR;
argumentos[0].bstrVal = SysAllocString(Valor);
HRESULT hr = InvocarMetodo(Objeto, L"SetValue", argumentos, 2);
VariantClear(&argumentos[0]);
VariantClear(&argumentos[1]);
return hr;
}
//-----------------------------------------------------------------
2. Escribe la configuración de Bullzip.
Código:
HRESULT BullzipWriteSettings(IDispatch *Objeto)
{
VARIANT argumento;
VariantInit(&argumento);
argumento.vt = VT_BOOL;
argumento.boolVal = VARIANT_TRUE;
HRESULT hr = InvocarMetodo(Objeto, L"WriteSettings", &argumento, 1);
VariantClear(&argumento);
return hr;
}
//-----------------------------------------------------------------
3. Función auxiliar para ejecutar métodos COM mediante IDispatch
Código:
HRESULT InvocarMetodo(IDispatch *Objeto, const wchar_t *Nombre, VARIANT *Argumentos, int NumeroArgumentos)
{
DISPID dispid;
LPOLESTR nombre = (LPOLESTR)Nombre;
HRESULT hr = Objeto->GetIDsOfNames(IID_NULL, &nombre, 1, LOCALE_USER_DEFAULT, &dispid);
if (FAILED(hr))
return hr;
DISPPARAMS parametros;
parametros.rgvarg = Argumentos;
parametros.rgdispidNamedArgs = NULL;
parametros.cArgs = NumeroArgumentos;
parametros.cNamedArgs = 0;
VARIANT resultado;
VariantInit(&resultado);
hr = Objeto->Invoke(dispid, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, ¶metros, &resultado, NULL, NULL);
VariantClear(&resultado);
return hr;
}
//---------------------------------------------------------------------------
4. Genera el PDF
Código:
bool GenerarPDF(TQuickRep *Reporte, AnsiString &FicheroDestino, int ImpPdf)
{
CLSID clsid;
IDispatch *pBullzipSettings = NULL;
try
{
// Inicializar COM.
HRESULT hr = CoInitialize(NULL);
if (FAILED(hr))
throw Exception("Error al inicializar COM.");
// Obtener CLSID de Bullzip.
hr = CLSIDFromProgID( L"Bullzip.PDFPrinterSettings", &clsid);
if (FAILED(hr))
throw Exception("No se encuentra Bullzip PDF Printer Settings.");
// Crear objeto COM.
hr = CoCreateInstance(clsid, NULL, CLSCTX_INPROC_SERVER, IID_IDispatch, (void**)&pBullzipSettings);
if (FAILED(hr))
throw Exception("No se pudo crear el objeto COM de Bullzip.");
// Convertir la ruta a formato Unicode.
WideString rutaPDF = ExtractFilePath(Application->ExeName) + "Impresos\\" + FicheroDestino;
// Configurar destino del PDF.
hr = BullzipSetValue(pBullzipSettings, L"Output", rutaPDF.c_bstr());
if (FAILED(hr))
throw Exception("Error configurando Output.");
// No abrir el lector PDF.
hr = BullzipSetValue(pBullzipSettings, L"ShowPDF", L"no");
if (FAILED(hr))
throw Exception("Error configurando ShowPDF.");
// Ocultar la ventana de configuración.
hr = BullzipSetValue(pBullzipSettings, L"ShowSettings", L"never");
if (FAILED(hr))
throw Exception("Error configurando ShowSettings.");
// Sobrescribir automáticamente.
hr = BullzipSetValue(pBullzipSettings, L"ConfirmOverwrite", L"no");
if (FAILED(hr))
throw Exception("Error configurando ConfirmOverwrite.");
// Guardar configuración para la siguiente impresión.
hr = BullzipWriteSettings(pBullzipSettings);
if (FAILED(hr))
throw Exception("Error escribiendo configuración Bullzip.");
// Liberar objeto COM antes de imprimir.
pBullzipSettings->Release();
pBullzipSettings = NULL;
// Seleccionar Bullzip como impresora.
int impresoraAnterior = Printer()->PrinterIndex;
Printer()->PrinterIndex = ImpPdf;
try
{
// Imprimir directamente el QuickReport.
Reporte->Print();
}
__finally
{
Printer()->PrinterIndex = impresoraAnterior;
}
CoUninitialize();
return true;
}
catch (Exception &e)
{
if (pBullzipSettings != NULL)
pBullzipSettings->Release();
CoUninitialize();
ShowMessage(AnsiString("Error generando PDF: ") + e.Message);
return false;
}
}
//---------------------------------------------------------------------------
Y se usa así:
Código:
if (Printer()->Printers->Strings[Form1->Tag] == "Bullzip PDF Printer")
{
AnsiString cAux = Now().FormatString("'L'ddhhnnss'.pdf'");
if (!GenerarPDF(Form1->QuickRep1, cAux, Form1->Tag))
Mensaje(1, "No se ha generado el fichero " + cAux, "Volver");
}
En el Tag del formualrio guardo la impresora seleccionada, lo que hago a través de otro formulario diferente. Al llamar a la función para generar el PDF paso tres parámetros:
- El QuickReport que quiero imprimir
- El nombre del fichero de destino. Puede pasarse con o sin dirección de la carpeta de destino. Yo paso sólo el nombre porque los guardo siempre en la misma carpeta.
- El valor de la impresora
Y funciona
