4. Temas y apariencia #
← Base común · Índice · Idioma y RTL →
4.1 Los temas: dos ejes #
Un tema se compone de un estilo y un modo:
| Eje | Valores |
|---|---|
Estilo (is_theme_style) | fluent · metro · office · office2007 · office2003 |
Modo (is_theme_mode) | light · dark |
En total, diez temas, denominados <style>-<mode>: fluent-light, fluent-dark, office2007-light, metro-dark…
4.2 El tema predeterminado de la aplicación (recomendado) #
Establezca el tema una sola vez para toda la aplicación, antes de abrir la primera ventana. Se inyecta en cada componente antes de su primera representación: ningún parpadeo de estilo claro en una aplicación oscura.
// Event open del objeto aplicacion
PBT_SetDefaultTheme("fluent-dark")
PBT_SetDefaultThemeAccent(RGB(0, 120, 212)) // opcional
El cambio en caliente es posible en cualquier momento: todos los componentes ya abiertos cambian de tema al instante.
Cambiar el tema predeterminado no toca el acento de la aplicación: el que fija PBT_SetDefaultThemeAccent se mantiene de un tema a otro, hasta que usted fije otro o -1.
// Conmutacion claro / oscuro desde un boton de la aplicacion
PBT_SetDefaultTheme("fluent-light")
| Función | Efecto |
|---|---|
PBT_SetDefaultTheme (string as_name) | Tema predeterminado del proceso, difundido a todos los componentes; un nombre desconocido se rechaza (-5) y el tema anterior se mantiene |
PBT_GetDefaultTheme ( ) → string | Tema predeterminado actual |
PBT_SetDefaultThemeAccent (long al_accent) | Acento de la aplicación, que siguen todos los componentes — incluidos los de tema local, mientras no tengan el suyo; -1 lo quita (cada tema recupera su acento); un color de sistema de PowerBuilder (por encima de 0xFFFFFF) se rechaza (-5) |
PBT_GetDefaultThemeAccent ( ) → long | Acento de la aplicación, -1 si no hay ninguno |
PBT_SetDefaultFont (string as_family, long al_size_px) | Fuente de toda la aplicación; tamaño en píxeles, 0 = el del tema (ver 4.4) |
4.3 El tema de un componente concreto #
Un componente puede apartarse del tema de la aplicación, eje por eje:
// Solo el estilo: el modo sigue siendo el de la aplicacion, y lo sigue
uo_editor.is_theme_style = uo_editor.THEME_STYLE_OFFICE2007
// Los dos ejes: un tema totalmente local
uo_editor.is_theme_mode = uo_editor.THEME_MODE_DARK
uo_editor.il_theme_accent = RGB(200, 60, 40) // -1 = acento de la aplicacion
// Volver al tema de la aplicacion: los dos ejes vacios
uo_editor.is_theme_style = ""
uo_editor.is_theme_mode = ""
| Propiedad | Tipo | Predeterminado | Función |
|---|---|---|---|
is_theme_style | string | "" | Estilo visual (constantes THEME_STYLE_*). Vacío = el estilo de la aplicación, seguido en cada cambio |
is_theme_mode | string | "" | Variante clara u oscura (constantes THEME_MODE_*). Vacío = el modo de la aplicación, seguido en cada cambio |
il_theme_accent | long | -1 | Color de acento de este componente. -1 = el acento de la aplicación, o el del tema si la aplicación no fija ninguno |
Un of_reset() devuelve los dos ejes y el acento a la aplicación: el componente vuelve a seguir su tema y su acento.
Los dos ejes son independientes: un eje dejado vacío sigue el tema de la aplicación en cada uno de sus cambios, no solo el vigente cuando se fijó el otro eje. Los espacios y las mayúsculas no cuentan; un valor desconocido ("office2010", "sombre") se ignora y el eje conserva su valor. Releer is_theme_style o is_theme_mode devuelve lo que el componente muestra — para un eje vacío, el estilo y el modo de la aplicación —, y il_theme_accent devuelve -1 mientras el componente no tenga acento propio. Un componente con tema local también sigue el acento de la aplicación mientras no tenga el suyo.
💡 Lo más cuidado sigue siendo un único tema para toda la aplicación. Reserve el tema local para los casos particulares (una zona deliberadamente contrastada, una previsualización de tema).
4.4 Recolorear un componente, un grupo o un elemento #
Tres alcances, las mismas propiedades. Nada que nombrar, nada que adivinar.
// El componente entero
uo_ribbon.il_theme_accent = RGB(0, 120, 90)
// Un grupo : todo lo que contiene sigue
uo_ribbon.of_group(/*keys*/ "home/clipboard").il_accent = RGB(0, 120, 90)
// Un elemento
uo_list.of_item(/*keys*/ "delete").il_text_color = RGB(200, 70, 70)
uo_list.of_item(/*keys*/ "delete").il_back_color = RGB(255, 235, 235)
// Los mismos dos, bajo el puntero
uo_list.of_item(/*keys*/ "delete").il_back_color_hover = RGB(255, 220, 220)
// Volver al color del componente
uo_list.of_item(/*keys*/ "delete").il_text_color = -1
| Propiedad | Dónde | Qué recolorea |
|---|---|---|
il_theme_accent | el componente | su acento y todo lo que se deriva de él: el paso del puntero y la pulsación de los botones de acento, las selecciones y estados marcados teñidos, el texto legible encima, el fondo de la aplicación, el subrayado de pestaña |
il_accent | un handle de elemento, grupo, pestaña o barra | lo que esa zona pinta con el acento, descendientes incluidos |
il_back_color · il_text_color | ídem | el fondo y el texto del elemento |
il_back_color_hover · il_text_color_hover | ídem | los mismos dos, bajo el puntero |
-1 restablece el color que da el componente, que a su vez viene del tema. El color de un elemento sobrevive a la reconstrucción del componente: lo lleva una regla de estilo que apunta al elemento, no una propiedad puesta en el nodo del momento. of_reset() lo borra todo.
il_accent solo repinta lo que la zona pinta con el acento — una selección, un subrayado activo, una barra de progreso. Un componente que no lo usa no mostrará nada: para «esta entrada en rojo», il_back_color y il_text_color son las herramientas adecuadas, leídas por todos los componentes con elementos.
La fuente de toda la aplicación #
PBT_SetDefaultFont("Segoe UI", 14)
Una sola llamada viste cada componente vivo y los creados después — la fuente se les inyecta antes de su primer dibujado. Una familia vacía o un tamaño de 0 devuelve esa mitad al tema. El tamaño se expresa en píxeles.
4.5 El fondo del componente se comunica a PowerBuilder #
Cada componente pinta su fondo según el tema y luego notifica su color: el userobject adopta ese color (backcolor) y activa ue_bg_color, para que la ventana y los controles PowerBuilder vecinos se armonicen.
// event ue_bg_color de un componente
parent.backcolor = al_color
st_title.backcolor = al_color
Es lo que permite mezclar componentes PBToolboxAI y controles PowerBuilder nativos sin demarcación visible en tema oscuro.
4.6 Las imágenes y los iconos #
Allí donde un componente espera una ruta de imagen (icono de botón, mosaico, [picture=…]…), se aceptan cuatro formas:
| Forma | Ejemplo | Uso |
|---|---|---|
| Archivo | img\logo.png | Imagen tal cual (png, jpg, gif, bmp, ico, svg, webp) |
| Recurso de DLL | img\packimages.dll:RIBBON | Imagen empaquetada en una DLL de recursos |
mono: | mono:img\save.svg | Color plano en el color del tema: solo cuenta la forma |
tint: | tint:img\logo_couleur.png | Duotono: el relieve interno modula el color del tema |
mono:se utiliza para todos los glifos monocromos (iconos blancos o negros): se recolorean automáticamente tanto en claro como en oscuro.tint:armoniza un icono en color con el tema conservando sus degradados. No debe usarse nunca sobre un glifo blanco (seguiría siendo blanco).- Sin prefijo, la imagen multicolor se deja intacta.
La forma ruta.dll:nombre carga un recurso de una DLL de imágenes (al estilo de packimages.dll), abierta en solo lectura (LOAD_LIBRARY_AS_DATAFILE, sin ejecutar ningún código). Esto evita distribuir cientos de archivos sueltos.
Visualización instantánea: of_icon #
Un pequeño glifo pasado mediante of_icon() se incorpora al comando (sin ninguna ida y vuelta de carga): aparece desde la primera representación, sin el parpadeo de un icono cargado a posteriori.
n_pbt_utils lnv_utils // autoinstantiate : nada que crear, nada que destruir
uo_toolbar.of_add_button(/*keys*/ "main/save", /*text*/ "Guardar", /*image*/ lnv_utils.of_icon(/*path*/ "mono:img\save.svg"), /*tooltip*/ "Guardar")
Para un lote de iconos conocido de antemano, of_preload_icons() calienta la caché de una sola vez, al arrancar: el primer pintado ya no espera nada.
Transparente en su uso: a partir de cierto tamaño, of_icon devuelve la ruta de origen (la imagen se carga entonces y se guarda en caché de forma normal).
4.7 El texto enriquecido con etiquetas #
Cualquier etiqueta de cualquier componente acepta un marcado al estilo BBCode: título de pestaña, etiqueta de botón, texto de barra de estado, mensaje de toast, título de panel, texto de tooltip…
Las entradas de los menús integrados siguen la misma regla — menú contextual de una pestaña, lista ··· de las pestañas que ya no caben, menús de columna de una cuadrícula: la etiqueta que muestra el menú es la del control, marcado incluido.
El texto se representa mediante nodos de texto y <span>: no es posible ninguna inyección HTML.
| Etiqueta | Efecto |
|---|---|
[b] [i] [u] [s] / [strike] | Negrita, cursiva, subrayado, tachado |
[sub] [super] | Subíndice, superíndice |
[red]…[/red] (colores con nombre) | Color de texto (red, green, blue, orange, teal…) |
[accent]…[/accent] | Color de acento del tema actual |
[color=#rrggbb] / [color=accent] | Color de texto |
[bk=#rrggbb] / [backcolor=accent] | Color de fondo |
[font=Consolas] | Fuente |
[size=14] | Tamaño absoluto, en puntos (de 6 a 200) |
[size+=30] / [size-=20] | Tamaño relativo en % (20 % de forma predeterminada) |
[picture=ruta] / [picture=ruta,anch,alt] | Imagen en línea. Acepta también lo que devuelve of_icon() (un data URI); las dimensiones se leen al final del valor. Una ruta de red se rechaza en ella (véase más abajo) |
[symbol=nombre] | Símbolo integrado, monocromo, dibujado en el color del texto que lo rodea (sigue el tema, el paso del ratón, un [accent]) — ningún archivo que distribuir: clock, location, person, people, calendar, repeat, lock, bell, phone, mail, video, note, tag, link, check, star, info, warning. Un nombre desconocido se muestra tal cual |
[br] / [linebreak] / [br:3] | Salto de línea (o n saltos) |
[gap=N] | Salto de línea seguido de un blanco de N % de línea: [gap=100] equivale a [br][br], [gap=50] media línea vacía |
[separator] | Filete horizontal |
[hyperlink=url]…[/hyperlink] | Zona en la que se puede hacer clic: el enlace se abre siempre en el navegador del usuario, en todos los componentes. El evento ue_hyperlink(as_url) se emite además, en los componentes que lo exponen |
[action=id]…[/action] | Zona en la que se puede hacer clic → evento ue_action(as_key), presentada como un enlace |
[invisibleaction=id]…[/invisibleaction] | Zona en la que se puede hacer clic → ue_action, sin el estilo de enlace |
[bullet]…[/bullet] | Viñeta: elemento de lista cuyas líneas siguientes se alinean con la primera en lugar de volver bajo el marcador (sangría francesa). [bullet=-] cambia el marcador |
[foldarea:Título]…[/foldarea] | Bloque plegable: encabezado en el que se puede hacer clic (− / +) sobre un contenido con sangría. El título admite etiquetas |
[foldarea-closed:Título]…[/foldarea] | El mismo bloque, plegado al mostrarse |
[[ / ]] | Escape: [[b]] muestra [b] sin interpretarlo |
uo_text.is_text = "Bienvenido a [b][accent]PBToolboxAI[/accent][/b] [size-=20]v1.0[/size-=20]" &
+ "[br]Consulte la [hyperlink=https://pbtoolboxai.net]documentación[/hyperlink]."
uo_tab.of_add_page(/*key*/ "clients", /*title*/ "[b]Clientes[/b] [size-=20](128)[/size-=20]", /*page*/ uo_clients)
uo_st.is_text = "La etiqueta [[b]] pone en [b]negrita[/b]" // muestra: La etiqueta [b] pone en negrita
Mostrar un dato tal cual. Un valor procedente de su base puede contener una etiqueta conocida — [b], [red], [picture=…]: sería interpretado (una palabra desconocida entre corchetes se muestra tal como está escrita). of_escape_markup(), función de n_pbt_utils, los duplica por usted — envuelva el dato, nunca el marcado que escribe usted mismo.
n_pbt_utils lnv_utils // autoinstantiate : nada que crear, nada que destruir
// Un dato de negocio puede contener una etiqueta CONOCIDA : sin escape se
// INTERPRETA -- el [b] desaparece y lo que sigue pasa a negrita.
ls_label = "Descuento [b]VIP"
uo_st.is_text = "Cliente : " + ls_label // muestra : Cliente : Descuento VIP (VIP en negrita)
uo_st.is_text = "Cliente : " + lnv_utils.of_escape_markup(/*text*/ ls_label) // muestra : Cliente : Descuento [b]VIP
Un texto sin etiquetas no tiene ningún sobrecoste (ruta rápida). Una etiqueta desconocida se muestra tal como está escrita (Saldo [neto] sigue siendo Saldo [neto]). Una etiqueta de cierre solo cierra la suya, y una etiqueta de cierre sin apertura se ignora. Un [hyperlink] se abre en todas partes — etiqueta, título de pestaña, panel de barra de estado, toast, cuadro de diálogo: de ello se encarga la base. El evento ue_action, en cambio, solo lo emiten los componentes de texto interactivos (statictext); en los demás, [action] sirve únicamente para el formato.
Solo se abren http, https y mailto, sea cual sea su uso de mayúsculas (HTTPS:// también). Una etiqueta transporta a menudo un dato venido de su base: confiar al sistema un esquema cualquiera convertiría una etiqueta en un lanzador de programas. Por la misma razón, una imagen del marcado nunca va a buscar un recurso compartido de red ([picture=\\servidor\recurso\x.png] se rechaza): un comentario sin escapar abriría si no una sesión de red hacia cualquier máquina con solo mostrarse. Una imagen de red dentro de un texto pasa por of_icon(), que la incrusta; is_picture y los iconos de los componentes conservan el acceso a la red.
Un [foldarea] es un bloque: ocupa todo el ancho y se pliega con un clic en su encabezado, sin ida y vuelta a PowerBuilder. Los bloques se anidan y, si el componente sigue la altura de su contenido (ib_auto_height), esa altura se vuelve a notificar en cada pliegue. El título también es texto con etiquetas: nada se pone en negrita por usted, de eso se encarga [foldarea:[b]Total[/b]].
← Base común · Índice · Idioma y RTL →
4.8 Las animaciones y el ajuste del puesto #
Windows ofrece un ajuste de accesibilidad — Configuración > Accesibilidad > Efectos visuales > Efectos de animación — y los componentes lo respetan: cuando está desactivado, no se reproduce ningún fotograma clave ni ninguna transición. El gráfico llega a su sitio, no va hacia él.
Es el comportamiento correcto por defecto, y no se discute: quien pidió menos movimiento a su sistema lo pensaba. ib_animated = true no cambia nada.
Una aplicación puede sin embargo insistir:
// Declarar una vez : Function long PBT_SetAnimationPolicy (long al_policy)
// Library "pbtoolboxai.dll"
PBT_SetAnimationPolicy(1) // 1 = animar siempre, 0 = respetar el puesto (defecto)
La llamada vale para todo el proceso y puede hacerse en cualquier momento: los componentes vivos la siguen enseguida, los siguientes la reciben al abrirse.
Ponga
1sólo si su aplicación tiene una razón real para anularlo — un quiosco, un panel mural, una demostración cuyo oficio es precisamente mostrar estas animaciones. En una aplicación de gestión, deje el valor por defecto.
4.9 Componer la apariencia de su aplicación #
La biblioteca entrega diez temas y no permite que una aplicación defina un undécimo: el vocabulario de fichas es interno y así se queda. Lo que ofrece en su lugar son tres palancas que se combinan — así se obtienen «nuestros colores» sin escribir un tema.
// 1. LA BASE: el tema entregado mas cercano al objetivo.
PBT_SetDefaultTheme("office-light")
// 2. EL ACENTO: UN color viste todos los componentes, incluidos los
// creados despues, y todo lo que el tema deriva de el.
PBT_SetDefaultThemeAccent(RGB(0, 105, 92))
// 3. LA FUENTE de toda la aplicacion, en una llamada.
PBT_SetDefaultFont("Segoe UI Semibold", 0)
Ponga estas tres líneas en el evento open del objeto aplicación: alcanzan cada componente antes de su primer dibujado, sin parpadeo alguno.
| Palanca | Alcance | Lo que cambia |
|---|---|---|
PBT_SetDefaultTheme | el proceso | estilo y modo: formas, redondeos, grosores, toda la paleta |
PBT_SetDefaultThemeAccent | el proceso | el acento y lo que el tema deriva de él — paso del puntero y pulsación de los botones de acento, selección, texto legible encima, subrayado de pestaña; incluidos los componentes de tema local, y sobrevive a un cambio de tema |
PBT_SetDefaultFont | el proceso | familia y tamaño; una familia vacía o un tamaño 0 devuelve esa mitad al tema |
il_theme_accent | un componente | su propio acento, cuando una ventana debe distinguirse |
il_back_color · il_text_color | un elemento | una entrada precisa, en rojo porque elimina (véase 4.4) |
Lo que esto no permite #
Redefinir la paleta completa — los grises de superficie, los bordes, el radio de las esquinas — no se ofrece. Un tema es un conjunto coherente de unos sesenta valores que se responden entre sí: abrir la mitad produciría combinaciones ilegibles que nadie habría comprobado. Si su identidad exige más que estas tres palancas, escríbanos: un tema más dentro de la biblioteca es una opción, su tema dentro de su código no lo es.
En la aplicación de demostración: cinta Home > Apariencia > Estilo > Corporate (composed). La entrada combina estas tres palancas — nada reservado a nosotros — con dos diferencias: el tema es
office-lightuoffice-darksegún el botón claro/oscuro de la cinta, y la fuente se fija en 16 píxeles. El código eswf_apply_style, en la ventanaw_demo_home.
4.10 El contraste alto de Windows #
Cuando el usuario activa un tema de Contraste alto de Windows, el motor sustituye los colores de la página por los del sistema, sea cual sea el tema de la biblioteca. Los componentes lo tienen en cuenta: los iconos monocromos (mono:, tint:) toman el color del texto del sistema — el del texto resaltado en una fila seleccionada —, los anillos de foco y las marcas dibujadas como sombra reciben un contorno real, y lo que lleva un significado por su color (un punto de estado, un color elegido por la aplicación) lo conserva. Nada que hacer del lado de la aplicación: ni propiedad, ni llamada.
4.11 El contenido de terceros: navegador web y visor PDF #
webbrowser y pdfviewer muestran un contenido que la biblioteca no dibuja: un sitio web, o el visor PDF del motor. Ese contenido no conoce los temas de la biblioteca, pero lee la preferencia clara u oscura que el navegador le anuncia, como un sitio lee la de Windows. Esa preferencia sigue el tema predeterminado de la aplicación (PBT_SetDefaultTheme) — no el modo de Windows, ni el tema local de un componente: una aplicación en fluent-dark muestra la versión oscura de un sitio que la ofrezca, y el visor PDF en sus colores oscuros. Antes de que la página de terceros haya pintado, la zona toma el fondo del tema en lugar de un rectángulo blanco.