PowerBuilder
Un MessageBox moderno para toda la aplicación, sin reescribir sus pantallas

0 visualizaciones
La idea no consiste en buscar y reemplazar cientos de llamadas. El overlay conserva la expresión MessageBox(...) que ya existe y cambia, durante el enlace de la aplicación, la función que atiende esa llamada.
El problema de una aplicación madura
Una aplicación PowerBuilder con años de evolución puede contener MessageBox en ventanas, menús, DataWindows, UserObjects y NVO. Cambiar cada llamada introduce trabajo repetitivo y un riesgo innecesario: se puede alterar una combinación de botones, perder un código de retorno o modificar una condición que ya funciona.
Este framework evita esa migración masiva. La aplicación conserva instrucciones como estas:
1MessageBox("Información", "Proceso terminado.")2MessageBox("Confirmación", "¿Desea continuar?", Question!, YesNo!)3li_respuesta = MessageBox("Advertencia", &4 "Existen cambios sin guardar.", Exclamation!, OKCancel!, 2)
La llamada tradicional abre una ventana Response moderna, integrada con el tema activo. La pantalla consumidora no conoce los controles internos del nuevo mensaje.
Qué significa overlay en este proyecto
El overlay es una capa de compatibilidad formada por el objeto global messagebox.srf. Este declara el mismo nombre y las combinaciones de parámetros utilizadas por el MessageBox estándar: dos argumentos; título, texto e icono; icono y botones; y la firma completa con botón predeterminado.
Cuando los objetos de la aplicación se recompilan, PowerBuilder resuelve sus llamadas contra estas funciones globales disponibles en el target. La nueva función recibe exactamente la información que antes llegaba al diálogo estándar, la traduce a una solicitud y delega la presentación al framework.
Paso 1: replicar las firmas públicas
La transparencia comienza en los prototipos. El consumidor sigue compilando porque el nombre, los tipos y el orden de los argumentos coinciden con las formas habituales de llamada.
1forward prototypes2global function integer messagebox (string as_titulo, string as_mensaje)3global function integer messagebox (string as_titulo, string as_mensaje, icon ai_icono)4global function integer messagebox (string as_titulo, string as_mensaje, &5 icon ai_icono, button abotones)6global function integer messagebox (string as_titulo, string as_mensaje, &7 icon ai_icono, button abotones, integer ai_predeterminado)8end prototypes
Las sobrecargas cortas desembocan en la implementación completa. Así se evita duplicar decisiones y se conserva un único camino para iconos, botones y respuesta predeterminada.
Paso 2: traducir tipos nativos sin cambiar el contrato
La firma completa convierte las enumeraciones nativas Icon y Button en valores internos. Por ejemplo, Question! se transforma en el tipo pregunta y YesNoCancel! en una disposición de tres botones. El botón predeterminado también viaja en la solicitud.
1Choose Case ai_icono2 Case StopSign!3 li_tipo = 44 Case Exclamation!5 li_tipo = 36 Case Question!7 li_tipo = 58 Case Else9 li_tipo = 110End Choose1112Choose Case abotones13 Case OKCancel!14 li_botones = 215 Case YesNo!16 li_botones = 317 Case YesNoCancel!18 li_botones = 419 Case RetryCancel!20 li_botones = 521 Case AbortRetryIgnore!22 li_botones = 723 Case Else24 li_botones = 125End Choose
Luego el overlay crea el servicio, construye una solicitud normalizada y devuelve un entero. Desde el punto de vista del evento original, nada ha cambiado.
1lnvo_servicio = Create nvo_servicio_mensajes2lnvo_solicitud = lnvo_servicio.of_crear_solicitud( &3 as_titulo, as_mensaje, li_tipo, li_botones)4lnvo_solicitud.ii_boton_predeterminado = ai_predeterminado5li_resultado = lnvo_servicio.of_mostrar_mensaje(lnvo_solicitud)6Destroy lnvo_solicitud7Destroy lnvo_servicio8Return li_resultado
Paso 3: separar la solicitud, el servicio y la ventana
nvo_solicitud_mensaje transporta título, mensaje, tipo, botones, detalles técnicos, copia, cuenta regresiva e indicador de historial. nvo_servicio_mensajes abre la ventana modal mediante OpenWithParm; la ventana recupera el objeto desde Message.PowerObjectParm.
1If Not IsValid(anvo_solicitud) Then Return 02of_inicializar()3OpenWithParm(w_mensaje_moderno, anvo_solicitud)4ls_resultado = Message.StringParm5li_resultado = of_normalizar_resultado(ls_resultado)6If anvo_solicitud.ib_registrar_historial Then &7 inv_historial.of_registrar(anvo_solicitud, li_resultado)8Return li_resultado
La ventana moderna configura texto, icono, tema y botones a partir de la solicitud. Cuando el usuario responde, utiliza CloseWithReturn. El servicio normaliza el texto devuelto y entrega el mismo código entero que espera el código heredado.
1Timer(0)2ls_retorno = String(ai_resultado) + "|" + as_texto3CloseWithReturn(this, ls_retorno)4Return ai_resultado
Paso 4: adoptar el tema activo de PowerBuilder
nvo_gestor_temas consulta GetTheme() y calcula una paleta clara u oscura. La ventana aplica fondo, texto, acento e iconografía cada vez que se abre. El mensaje parece una parte natural de la aplicación porque responde al tema que ya está activo, no a una apariencia fija.
La misma capa global bajo Flat Design Dark: contraste, botones, icono y foco se adaptan sin cambiar la llamada que originó el mensaje.
Apariencia
Paleta clara u oscura, color del tema, tipografía Segoe UI e iconos SVG por categoría.
Comportamiento
Botón predeterminado, Enter, Escape, retorno modal y sonido estándar de Windows.
Servicios
Historial en memoria, detalles técnicos, copia al portapapeles y cuenta regresiva opcional.
El escenario RetryCancel conserva los códigos tradicionales: Reintentar devuelve 4 y Cancelar devuelve 2.
Paso 5: integrar el overlay en una aplicación existente
• Importe messagebox.srf y los objetos de soporte: nvo_solicitud_mensaje, nvo_respuesta_mensaje, nvo_servicio_mensajes, nvo_gestor_temas, nvo_gestor_historial, u_icono_mensaje y w_mensaje_moderno.
• Guárdelos en una PBL del target o en una nueva PBL incluida en el LibList. La función global debe estar disponible para la resolución de todas las llamadas.
• Conserve recursos/svg y theme directamente bajo la raíz del demo. Las rutas absolutas se construyen en ejecución con GetCurrentDirectory(); no existen rutas fijas del equipo ni búsquedas en carpetas superiores.
• Ejecute un Full Build. Este paso recompila los objetos consumidores y vuelve a enlazar las llamadas existentes con la función global del overlay.
• Pruebe cada combinación utilizada por la aplicación: OK!, OKCancel!, YesNo!, YesNoCancel!, RetryCancel! y AbortRetryIgnore!, incluidos los botones predeterminados.
• Valide los flujos que comparan el resultado numérico. La compatibilidad visual no basta: las decisiones posteriores deben recibir 1, 2, 3, 4, 5, 6 o 7 según corresponda.
Antes y después, sin tocar el evento
Antes del overlay
PowerBuilder atiende MessageBox(...) con el diálogo estándar. El evento recibe un entero y continúa su lógica.
Después del overlay
La función global compatible crea la solicitud, abre la ventana Response moderna y devuelve el mismo tipo de resultado. El evento continúa exactamente igual.
1li_respuesta = MessageBox("Confirmación", &2 "¿Desea aplicar la configuración seleccionada?", &3 Question!, YesNo!)45If li_respuesta = 6 Then6 // Continúa el proceso existente.7End If
Alcance real y límites
• El overlay cubre las firmas declaradas en messagebox.srf. Conviene inventariar variantes no contempladas antes del Full Build.
• Intercepta llamadas PowerScript que se resuelven durante la compilación del target.
• No reemplaza diálogos producidos internamente por el Runtime, Windows, DLL, ActiveX, COM, controladores de base de datos o componentes externos.
• Los recursos SVG deben formar parte del despliegue; el sonido usa MessageBeep de Windows y no necesita archivos de audio.
• La prueba debe incluir temas claros, oscuros y High DPI, además de teclado, cierre con la X y códigos de retorno.
Conclusión
La modernización más segura no siempre es la que reescribe más código. En este framework, una función global compatible actúa como overlay, conserva el contrato de MessageBox y desvía la presentación hacia una ventana Response moderna. El resultado es una actualización transversal: temas automáticos, iconos SVG, retornos compatibles, historial, detalles y sonido, mientras las ventanas y eventos existentes permanecen intactos.
La clave es combinar tres ideas sencillas: mismas firmas públicas, un servicio central y un Full Build que reenlace toda la aplicación. Así, un sistema ya terminado puede adoptar una experiencia visual moderna sin convertir la migración en una búsqueda manual de cientos de llamadas.