![]() |
![]() |
| Paypal | FTP | CCD | Buscar | Trucos | Trabajo | Foros |
|
|||||||
| Registrarse | FAQ | Miembros | Calendario | Guía de estilo | Buscar | Temas de Hoy | Marcar Foros Como Leídos |
![]() |
|
|
Herramientas | Buscar en Tema | Desplegado |
|
#1
|
||||
|
||||
|
Automatizar el uso de Bullzip PDF Printer
Tengo instalado este programa para cuando necesito imprimir en formato PDF y me gustaría que en un programa que estoy desarrollando si selecciono como destino esta impresora se automatizara el proceso sin necesidad de mostrar cuadros de diálogo y demás. Lo malo es que el único código aparentemente completo que he encontrado está en VBA y no tengo ni idea de como funciona. ¿Alguno puede ayudarme con la traducción?
Cita:
Código:
#include <windows.h>
#include <iostream>
#include <comdef.h>
// Reemplaza esta ruta por la localización real de tu archivo de configuración de Bullzip si fuese necesario.
// Sin embargo, instanciarlo por su ProgID ("Bullzip.PDFPrinterSettings") suele ser suficiente.
int main() {
// 1. Inicializar el entorno COM de Windows
HRESULT hr = CoInitialize(NULL);
if (FAILED(hr)) {
std::cerr << "Error al inicializar COM." << std::endl;
return 1;
}
try {
// 2. Obtener el CLSID a partir del ProgID de Bullzip
CLSID clsid;
hr = CLSIDFromProgID(L"Bullzip.PDFPrinterSettings", &clsid);
if (FAILED(hr)) {
throw std::runtime_error("No se encontró el componente COM de Bullzip. ¿Está instalado?");
}
// 3. Crear la instancia del objeto de configuración
IDispatch* pBullzipSettings = nullptr;
hr = CoCreateInstance(clsid, NULL, CLSCTX_INPROC_SERVER, IID_IDispatch, (void**)&pBullzipSettings);
if (FAILED(hr)) {
throw std::runtime_error("No se pudo crear la instancia de Bullzip Settings.");
}
// Helper Lambda para invocar métodos (SetValue, WriteSettings) mediante IDispatch
auto invokeMethod = [](IDispatch* obj, OLECHAR* name, VARIANT* args, int argCount) -> _variant_t {
DISPID dispid;
HRESULT hr = obj->GetIDsOfNames(IID_NULL, &name, 1, LOCALE_USER_DEFAULT, &dispid);
if (FAILED(hr)) return _variant_t();
DISPPARAMS params = { args, NULL, (UINT)argCount, 0 };
_variant_t result;
hr = obj->Invoke(dispid, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, ¶ms, &result, NULL, NULL);
return result;
};
// 4. Configurar los parámetros de impresión automática
// Nota: Los argumentos en Invoke se pasan en orden inverso (derecha a izquierda)
// Parámetro: Output -> Ruta donde se guardará el PDF
VARIANT argsOutput[2];
argsOutput[1].vt = VT_BSTR; argsOutput[1].bstrVal = SysAllocString(L"Output");
argsOutput[0].vt = VT_BSTR; argsOutput[0].bstrVal = SysAllocString(L"C:\\destino\\mi_documento.pdf");
invokeMethod(pBullzipSettings, L"SetValue", argsOutput, 2);
SysFreeString(argsOutput[1].bstrVal); SysFreeString(argsOutput[0].bstrVal);
// Parámetro: ShowPDF -> "no" (Evita que se abra el lector de PDF tras crear el archivo)
VARIANT argsShow[2];
argsShow[1].vt = VT_BSTR; argsShow[1].bstrVal = SysAllocString(L"ShowPDF");
argsShow[0].vt = VT_BSTR; argsShow[0].bstrVal = SysAllocString(L"no");
invokeMethod(pBullzipSettings, L"SetValue", argsShow, 2);
SysFreeString(argsShow[1].bstrVal); SysFreeString(argsShow[0].bstrVal);
// Parámetro: ShowSettings -> "never" (Oculta por completo la interfaz gráfica de Bullzip)
VARIANT argsShowSettings[2];
argsShowSettings[1].vt = VT_BSTR; argsShowSettings[1].bstrVal = SysAllocString(L"ShowSettings");
argsShowSettings[0].vt = VT_BSTR; argsShowSettings[0].bstrVal = SysAllocString(L"never");
invokeMethod(pBullzipSettings, L"SetValue", argsShowSettings, 2);
SysFreeString(argsShowSettings[1].bstrVal); SysFreeString(argsShowSettings[0].bstrVal);
// Parámetro: ConfirmOverwrite -> "no" (Sobrescribe de forma automática si el archivo ya existe)
VARIANT argsOverwrite[2];
argsOverwrite[1].vt = VT_BSTR; argsOverwrite[1].bstrVal = SysAllocString(L"ConfirmOverwrite");
argsOverwrite[0].vt = VT_BSTR; argsOverwrite[0].bstrVal = SysAllocString(L"no");
invokeMethod(pBullzipSettings, L"SetValue", argsOverwrite, 2);
SysFreeString(argsOverwrite[1].bstrVal); SysFreeString(argsOverwrite[0].bstrVal);
// 5. Confirmar y escribir la configuración en el archivo temporal 'runonce.ini'
// El método WriteSettings acepta un booleano (true para escribir la configuración de inmediato)
VARIANT argsWrite[1];
argsWrite[0].vt = VT_BOOL; argsWrite[0].boolVal = VARIANT_TRUE;
invokeMethod(pBullzipSettings, L"WriteSettings", argsWrite, 1);
// 6. Liberar el objeto COM de configuración
pBullzipSettings->Release();
// 7. Lanzar la impresión real del documento usando la API de Windows
// Esto envía el archivo a la cola de Bullzip, la cual procesará el runonce.ini que acabamos de crear.
std::cout << "Configuración inyectada. Enviando archivo a 'Bullzip PDF Printer'..." << std::endl;
// Ejemplo para mandar a imprimir un archivo de texto existente silenciosamente:
ShellExecute(NULL, L"printto", L"C:\\origen\\documento.txt", L"\"Bullzip PDF Printer\"", NULL, SW_HIDE);
} catch (const std::exception& e) {
std::cerr << "Excepción: " << e.what() << std::endl;
}
// Cerrar el entorno COM
CoUninitialize();
return 0;
}
|
|
#2
|
||||
|
||||
|
Pregunto, ¿tiene que ser ese programa?
Hay otros que puedes usar y funcionan perfectamente. E incluso creo recordar que el propio windows ya permite instalar una impresora pdf directamente.
__________________
La otra guía de estilo | Búsquedas avanzadas | Etiquetas para código | Colabora mediante Paypal |
|
#3
|
|||
|
|||
|
Try this: (CONSOLE for tests... )
Última edición por emailx45 fecha: Hace 4 Días a las 22:57:44. |
|
#4
|
||||
|
||||
|
Cita:
Muchas gracias por el esfuerzo, pero no era trasladarlo a Delphi. Eso se me olvidó ponerlo: era para C++. |
|
#5
|
||||
|
||||
|
Prueba el pdfcreator, está en nuestro ftp:
https://terawiki.clubdelphi.com/Delp...PdfCreator.zip Eso crea una impresora virtual a donde puedes enviar todo lo que quieras imprimir a formato pdf. La versión última de ese componente me temo que lo ha comprado una empresa y ahora e de pago, pero esa versión que está en nuestro ftp es la anterior que era gratis. Y funciona perfectamente.
__________________
La otra guía de estilo | Búsquedas avanzadas | Etiquetas para código | Colabora mediante Paypal |
|
#6
|
||||
|
||||
|
Y si necesitas código C++ para lo que te ha pasado en Delphi emailx45, pásaselo a cualquier IA y le indicas que te lo convierta al lenguaje que quieras.
__________________
La otra guía de estilo | Búsquedas avanzadas | Etiquetas para código | Colabora mediante Paypal |
|
#7
|
||||
|
||||
|
Cita:
|
|
#8
|
|||
|
|||
|
Lamentablemente, no domino CBuilder / C++.
Por lo tanto, creo que un ejemplo en Delphi sería de ayuda. Como nunca he utilizado BullZIP, no he probado el código que muestras en el ejemplo. Sin embargo, he notado que algo no funciona como se esperaba en la línea "LRetorno := ...", ya que no obtengo un valor de retorno de 32 o superior. Por consiguiente, sería necesario analizar la versión actual de BullZIP y consultar el sitio web del desarrollador para verificar qué es lo que realmente se espera en la configuración... Otra forma más sencilla sería tener la aplicación instalada en su sistema y utilizar el menú de Delphi para obtener la API traducida de la DLL de BullZip; de este modo, los comandos resultarían más nativos para su uso en Delphi. Consulte el menú Component -> Importar Component (DLL); incluso sería posible crear un componente de Delphi si le interesa estudiar las llamadas a esta DLL. Última edición por emailx45 fecha: Hace 4 Días a las 16:41:46. |
|
#9
|
|||
|
|||
|
Otra forma sería utilizar únicamente la DLL de GhostScript (y nada más) para enviar el archivo PDF directamente a la impresión; de este modo, no dependerías de ninguna impresora virtual instalada. Solo necesitarías la DLL de GhostScript (la versión 10.0.8, por ejemplo, ya está disponible en el sitio https://ghostscript.com/releases/gsdnld.html).
Con esto, accederías directamente a la API de GhostScript sin necesidad de instalar ninguna aplicación; bastaría con copiar la DLL para tu uso particular. Delphi puede cargar la DLL mediante la función "LoadLibrary" y obtener los métodos necesarios a través de "GetProcAddress()"; ambos forman parte de la unidad "WinApi.Windows". Se trataría de muy pocas líneas de código, unas 100 aproximadamente (ya que tendrías que definir los parámetros, la forma de acceso, las variables, el manejo de errores, etc.), todo ello bastante sencillo. Aquí tienes un esquema básico para que te hagas una idea de lo fácil que resultaría: ![]()
Aquí estoy usando Chrome como mi aplicación predeterminada para abrir archivos PDF. ![]() Última edición por emailx45 fecha: Hace 4 Días a las 19:01:22. |
|
#10
|
||||
|
||||
|
Gracias por tu respuesta. La leeré con atención, aunque no sé que versión de está instalada con BullZip.
|
|
#11
|
|||
|
|||
|
Esto debería redirigir la salida a una impresora física instalada y utilizada por defecto en el sistema.
|
|
#12
|
||||
|
||||
|
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;
}
//-----------------------------------------------------------------
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;
}
//-----------------------------------------------------------------
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;
}
//---------------------------------------------------------------------------
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;
}
}
//---------------------------------------------------------------------------
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");
}
![]() Última edición por Angel.Matilla fecha: Hace 11 Horas a las 11:03:19. |
![]() |
| Herramientas | Buscar en Tema |
| Desplegado | |
|
|
Temas Similares
|
||||
| Tema | Autor | Foro | Respuestas | Último mensaje |
| Automatizar web login | amadis | Internet | 2 | 13-08-2010 15:15:42 |
| automatizar instalación de mysql | Aprendiendo | MySQL | 3 | 10-02-2010 17:19:58 |
| Automatizar OpenOffice. | Critter | Servers | 2 | 31-07-2007 20:41:24 |
| Automatizar BACKUPS y RESTORES | AMINOA2R | Firebird e Interbase | 12 | 20-10-2005 17:11:16 |
| Automatizar Login | JoseQ | Internet | 0 | 30-03-2005 13:35:50 |
|