pdfviewer — u_pbt_pdfviewer #
← Referencia de componentes · Índice de la guía
Visor de PDF integrado: muestra un documento local o publicado en la web, directamente dentro de su ventana, con paginación, zoom e impresión.
▶ Verlo en vivo — Aplicación de demostración, mosaico PDF viewer: la vista previa, el código que lo genera y esta página, uno al lado del otro.
De un vistazo #
| Userobject | u_pbt_pdfviewer |
| Clase de items | — (componente sin items) |
| Sirve para | Mostrar una factura, un pedido, un contrato o un manual sin abrir una aplicación externa |
| Opciones opt-in | — |
El componente sustituye al clásico «guardar el PDF en un fichero temporal y después llamar a ShellExecute»: el documento permanece dentro de su aplicación y el usuario nunca abandona la pantalla en curso.
Inicio rápido #
// event open de la ventana : mostrar un documento presente en el disco
uo_pdf.is_source = "C:\factures\FA-2026-0142.pdf"
// event ue_load_completed de uo_pdf : (string as_source)
uo_status.of_panel(/*key*/ "main").is_text = "Documento mostrado"
Eso es todo: basta con asignar is_source para cargar y mostrar el documento.
Propiedades #
| Propiedad | Tipo | Predeterminado | Función |
|---|---|---|---|
is_source | string | "" | Documento que se muestra: una ruta de fichero (absoluta, relativa a la aplicación o de red; un # forma parte del nombre), una dirección file:///, una dirección web https://… servida como application/pdf, o una dirección data:application/pdf. Asignar el valor lanza la carga; asignar "" (o solo espacios) vacía el visor y conserva sus ajustes. Todo lo demás se rechaza y se señala con ue_load_failed — incluido http:// y una dirección que lleva usuario y contraseña (https://nombre:secreto@…). Un PDF contenido en un blob se muestra con of_load_blob. Se relee tal como lo escribió |
ii_page | integer | 0 | Página de apertura, contada a partir de 1 (0 = la primera página del documento). Asignada mientras se muestra un documento, es la página de ese documento: se vuelve a cargar, abierto en ella. Asignada con el visor vacío, vale para el documento siguiente; si no, un documento nuevo se abre en su primera página. Para abrir un documento en una página, asigne is_source y luego ii_page: una sola carga. Cada cambio vuelve a cargar el documento y activa de nuevo ue_load_completed: el lector solo lee su página al cargar; el mismo valor asignado otra vez no hace nada. Solo escritura: releerla da la última página pedida, no la mostrada. El lector es el del motor web y no informa de nada. |
ii_zoom | integer | 0 | Zoom en porcentaje, de 25 a 500 — el rango de los botones del lector (0 = a cargo del visor). Un valor fuera de ese rango se lleva dentro de él y se relee tal como se aplicó. Asignar un zoom anula is_fit, que lo contradice. Solo escritura, como ii_page: si el usuario hace zoom con la barra del lector, esta propiedad no lo sigue. |
is_fit | string | "" | Ajuste: FIT_PAGE, FIT_WIDTH, FIT_HEIGHT, o "" para ninguno. Anula ii_zoom |
ib_viewer_toolbar | boolean | true | Muestra la barra propia del visor (número de página, zoom, impresión, descarga). Ocúltela cuando su ventana lleve esos comandos ella misma |
ib_navigation_pane | boolean | false | Abre el panel lateral del lector: las miniaturas de las páginas y los marcadores del documento. El panel llega con la barra del lector. Cada cambio vuelve a cargar el documento mostrado |
is_destination | string | "" | Abre el documento en un destino con nombre del PDF — el destino de un marcador, escrito por la herramienta que generó el fichero. "" para ninguno; un nombre que el documento no tiene lo abre en su primera página. Se conserva para los documentos siguientes hasta que lo cambie. Cada cambio vuelve a cargar el documento mostrado |
is_find | string | "" | Un texto del documento, resaltado donde aparece por primera vez, con el lector desplazándose hasta él: la línea de una factura de la que habla su aplicación. "" para ninguno; un texto que el documento no contiene no cambia nada. No es una búsqueda dirigida por código (ni recuento, ni siguiente coincidencia): el usuario busca con la barra del lector. Se conserva para los documentos siguientes hasta que lo cambie. Cada cambio vuelve a cargar el documento mostrado |
ib_allow_save | boolean | true | Ofrece los comandos Guardar y Guardar como de la barra del lector y de su menú. En false, el documento se muestra sin proponer guardar una copia. Cada visor conserva su propio ajuste: el de otra ventana no cambia nada aquí. No es una protección: el fichero sigue siendo legible en el disco. Cada cambio vuelve a cargar el documento mostrado; asignado antes de is_source, el documento se carga una sola vez |
ib_allow_print | boolean | true | Ofrece el comando Imprimir de la barra del lector y de su menú. of_print sigue imprimiendo: decide su aplicación. Cada visor conserva su propio ajuste. Cada cambio vuelve a cargar el documento mostrado; asignado antes de is_source, el documento se carga una sola vez |
ib_allow_search | boolean | true | Ofrece el comando Buscar de la barra del lector. is_find sigue resaltando un texto: decide su aplicación. Cada visor conserva su propio ajuste. Cada cambio vuelve a cargar el documento en pantalla; asignada antes de is_source, el documento se carga una sola vez |
ib_allow_rotate | boolean | true | Ofrece el comando Girar de la barra del lector. Cada visor conserva su propio ajuste. Cada cambio vuelve a cargar el documento en pantalla; asignada antes de is_source, el documento se carga una sola vez |
ib_allow_fullscreen | boolean | true | Ofrece el comando Pantalla completa de la barra del lector. Cada visor conserva su propio ajuste. Cada cambio vuelve a cargar el documento en pantalla; asignada antes de is_source, el documento se carga una sola vez |
is_theme_style | string | "" | Estilo visual del componente (constantes THEME_STYLE_*); vacío = el de la aplicación, seguido en cada cambio |
is_theme_mode | string | "" | Variante clara u oscura (constantes THEME_MODE_*); vacío = la de la aplicación, seguida en cada cambio |
il_theme_accent | long | -1 | Color de acento de este componente (-1 = acento de la aplicación, o el del tema) |
Métodos #
| Método | Función |
|---|---|
of_refresh ( ) | Vuelve a leer el documento actual (del disco o de la red) sin tocar los ajustes: el modo de mostrar un fichero regenerado en la misma ruta. La posición de desplazamiento no se conserva: el lector vuelve a empezar en ii_page. Tras un fallo, reintenta el mismo documento. Un documento rechazado se juzga de nuevo: ue_load_failed se vuelve a lanzar. Devuelve 0 una vez solicitado, -4 sin documento (is_source vacío), -2 si el componente no está creado |
of_load_blob (blob ablb_pdf) · of_load_blob (blob ablb_pdf, string as_name) | Muestra un PDF contenido en un blob — leído de la base de datos (SELECTBLOB) o recibido de un servicio — sin escribir un fichero, sea cual sea su tamaño: los bytes se quedan en memoria y solo se sirven a este visor. El segundo argumento es el nombre que devuelven is_source y ue_load_completed / ue_load_failed (document.pdf sin él). El blob mostrado antes se libera; este, con el documento siguiente o of_reset. Devuelve 0 una vez pedido (sigue ue_load_completed), -5 si el blob está vacío o no es un PDF, -4 si es demasiado grande para este proceso (64 MB en 32 bits, 512 MB en 64 bits) — of_get_last_error dice por qué —, -2 si el componente no está creado |
of_print ( ) · of_print (boolean) | Abre la vista previa de impresión del documento — no de la página que lo enmarca. Devuelve 0 una vez solicitada la vista previa, -4 cuando no se muestra ningún documento, -2 si el componente no está creado. El argumento no tiene efecto aquí: siempre es la vista previa del lector PDF |
of_print_to_pdf (string) · of_print_to_pdf (string, boolean) | Devuelve -4 en este componente, sin escribir nada: la página impresa solo sería el marco del lector, nunca el documento. El documento ya es un PDF: copie el fichero de is_source |
of_reset ( ) | Vacía el visor y restablece todas las propiedades a su valor predeterminado. Devuelve 0 una vez aplicado, -2 si el componente no está creado |
of_set_redraw (boolean) | Agrupa una ráfaga de modificaciones en una sola representación. Devuelve 0 una vez aplicado, -2 si el componente no está creado |
of_save_as_png (string) · of_save_as_jpg (string) | Exporta la representación como imagen. Devuelve 0 una vez escrita la imagen, -4 si la escritura falla, -2 si el componente no está creado |
Eventos #
| Evento | Se activa cuando |
|---|---|
ue_load_completed (string as_source) | El documento está en pantalla; as_source es is_source tal como lo escribió (para un blob, el nombre dado a of_load_blob). También lo activan of_refresh y cada cambio de página, zoom, ajuste, barra del lector, panel, destino, texto resaltado, ib_allow_save o ib_allow_print — asígnelos antes de is_source para una sola carga; el mismo valor asignado otra vez no lo activa. Nunca se activa en un fallo |
ue_load_failed (string as_source, string as_reason) | No se ha podido mostrar el documento; as_reason es una de las constantes REASON_* de más abajo. El visor permanece vacío |
ue_link_clicked (string as_url) | El usuario ha seguido un enlace del documento. El visor permanece en el documento: abra as_url donde quiera (navegador del puesto, webbrowser…). as_url es la dirección del enlace tal cual (https://…, mailto:…); un enlace relativo de un documento local llega como ruta de disco. Un enlace a un fichero local del puesto (file:///) en un PDF no se sigue: el lector de PDF de WebView2 lo bloquea; no se activa ningún ue_link_clicked |
ue_ready ( ) | El componente ha terminado de cargarse; todo lo enviado antes se ha reproducido |
ue_runtime_missing ( ) | El runtime WebView2 está ausente: el componente permanece vacío |
ue_bg_color (long al_color) | El componente ha calculado el color de fondo de su tema; el userobject ya lo ha adoptado (backcolor) |
Por qué no se muestra un documento #
as_reason de ue_load_failed es una de estas constantes de u_pbt_pdfviewer. Un PDF se reconoce así: un fichero local tiene la extensión .pdf y empieza por la firma %PDF-; un documento remoto se sirve con el tipo application/pdf (el único que el motor entrega a su lector); una dirección data: anuncia application/pdf.
| Constante | Valor | Causa |
|---|---|---|
REASON_NOT_FOUND | "notfound" | Fichero ausente o ilegible, dirección que responde 404 |
REASON_NOT_PDF | "notpdf" | No es un PDF: fichero local sin la firma %PDF-, respuesta remota que no es application/pdf (un servidor de ficheros que responde application/octet-stream: descargue antes el documento, vea los ejemplos), data: o blob de otro tipo |
REASON_TOO_LARGE | "toolarge" | Fichero demasiado grande para este proceso (más de 64 MB en 32 bits, 512 MB en 64 bits), o una dirección data: de más de 2 MB de caracteres (unos 1,5 MB de PDF) |
REASON_INSECURE | "insecure" | http://: no admitido, sirva el documento en https:// |
REASON_UNSUPPORTED | "unsupported" | Otro tipo de dirección (ftp:, blob:…), o una dirección que lleva usuario y contraseña (https://nombre:secreto@…) |
REASON_NETWORK | "network" | Servidor inaccesible, nombre desconocido, conexión cortada |
REASON_CERTIFICATE | "certificate" | Certificado del sitio no válido, caducado o revocado |
REASON_AUTH | "auth" | El sitio o el proxy pide una autenticación: descargue el documento con el restclient (token, credenciales) y luego muéstrelo (vea los ejemplos) |
REASON_HTTP | "http" | Otro error del servidor (403, 500…) |
REASON_REFUSED | "refused" | El sitio se niega a mostrarse en un marco, o envía el PDF como descarga — el fichero no se descarga por ello |
REASON_FAILED | "failed" | Cualquier otra causa |
Lo que el usuario puede hacer, sin una sola línea de código #
El visor muestra su barra de herramientas integrada encima del documento. Usted no tiene que programar nada: la proporciona y la traduce el sistema.
| Acción | Cómo |
|---|---|
| Paginación | Rueda del ratón y barra de desplazamiento, o escritura directa del número de página en el contador n / total |
| Zoom | Botones + / −, ajuste a la página o al ancho |
| Búsqueda | El botón de búsqueda de la barra de herramientas, en el texto del documento |
| Impresión | Botón de impresora de la barra de herramientas (se oculta con ib_allow_print), o of_print desde su código |
| Guardado | Botón de descarga, para guardar una copia del documento (se oculta con ib_allow_save) |
| Rotación | Rotación de las páginas desde el menú de la barra de herramientas |
| Teclado | En cuanto el componente tiene el foco (Tab u of_focus_webview): AvPág, las flechas, Inicio / Fin desplazan el documento, sin clic previo |
Los atajos del navegador — Ctrl+F, Ctrl+P, Ctrl + rueda — están desactivados en todos los componentes, este incluido: use los botones de la barra del lector.
Lo que el lector no dice #
El lector es el integrado en el motor web: nada que instalar, impresión, búsqueda, formularios PDF y pantalla completa incluidos. A cambio, no informa de nada a su aplicación: ni la página mostrada, ni el número de páginas, ni el zoom real, ni el texto seleccionado, y la búsqueda no se dirige desde el código (is_find resalta un texto al abrir, nada más). ii_page e ii_zoom dicen dónde abrir el documento, no dónde está el usuario. Un PDF protegido por contraseña: el lector la pide él mismo al usuario, su aplicación no puede proporcionarla. Es una elección deliberada; un renderizado programable requeriría una biblioteca externa.
Ejemplos #
Abrir un documento local #
// Ruta absoluta, o relativa al directorio de la aplicacion
uo_pdf.is_source = "doc\conditions-generales.pdf"
Abrir un documento publicado en la web #
// Una direccion web se carga exactamente como un fichero local
uo_pdf.is_source = "https://www.monsite.fr/tarifs/catalogue-2026.pdf"
Evidentemente se necesita una conexión a internet; la carga es asíncrona y ue_load_completed le indica el final.
Mostrar el PDF que acaba de producir una DataWindow #
// Local variables
string ls_file
// Un fichero por dia, en la carpeta temporal
ls_file = "C:\temp\report_" + String(Today(), "yyyymmdd") + ".pdf"
// La DataWindow produce el fichero...
dw_report.SaveAs(ls_file, PDF!, false)
// ...y el visor lo muestra inmediatamente
uo_pdf.is_source = ls_file
Actualizar después de regenerar el fichero #
// El fichero se ha reescrito en la misma ubicacion : recargar sin modificar is_source
uo_pdf.of_refresh()
Encadenar varios documentos en el mismo visor #
// event rowfocuschanged de dw_list : (long currentrow)
// Local variables
string ls_pdf
// La ruta del PDF de la fila actual
ls_pdf = dw_list.GetItemString(currentrow, "pdf_path")
// Sin adjunto el visor se vacia (conserva sus ajustes) ; si no, lo muestra
if ls_pdf = "" then
uo_pdf.is_source = ""
else
uo_pdf.is_source = ls_pdf
end if
Seguir el final de la carga #
// event ue_load_completed de uo_pdf : (string as_source)
uo_wait.Hide()
// of_print imprime el documento mostrado
uo_print_button.ib_enabled = true
Decir por qué el documento no está #
// event ue_load_failed de uo_pdf : (string as_source, string as_reason)
uo_wait.Hide()
choose case as_reason
case uo_pdf.REASON_NOT_FOUND
uo_status.of_panel(/*key*/ "main").is_text = "Documento no encontrado: " + as_source
case uo_pdf.REASON_NOT_PDF
uo_status.of_panel(/*key*/ "main").is_text = "Este fichero no es un PDF"
case else
uo_status.of_panel(/*key*/ "main").is_text = "Documento no disponible (" + as_reason + ")"
end choose
Abrir en otro sitio un enlace del documento #
// event ue_link_clicked de uo_pdf : (string as_url)
// El visor permanece en el documento : el enlace se abre en el navegador de la ventana
uo_web.is_address = as_url
Imprimir el documento #
// clicked del boton Imprimir : la vista previa del lector PDF, sobre el propio documento
if uo_pdf.of_print() = -4 then
uo_status.of_panel(/*key*/ "main").is_text = "Ningun documento que imprimir"
end if
Mostrar sin dejar guardar ni imprimir #
// Un documento confidencial : ni Guardar ni Imprimir en la barra del lector
uo_pdf.ib_allow_save = false
uo_pdf.ib_allow_print = false
uo_pdf.is_source = is_current_document
Asígnelos antes de is_source: el documento se carga una sola vez. Cada visor conserva su propio ajuste. No es una protección: el fichero sigue siendo legible en el disco, y of_print sigue imprimiendo.
Vista previa en una pestaña, junto a la entrada de datos #
// event open : el visor ocupa una pagina de pestana, la entrada de datos la otra
uo_tab.of_add_page(/*key*/ "entry", /*title*/ "Entrada", /*page*/ uo_page_entry)
uo_tab.of_add_page(/*key*/ "preview", /*title*/ "Vista previa", /*page*/ uo_page_preview)
// El visor se coloca en uo_page_preview como cualquier otro control
uo_pdf.is_source = is_current_document
El componente se aloja sin ninguna precaución especial dentro de un tab o de un panel dockcontainer.
Comprobar el fichero antes de mostrarlo #
// Local variables
string ls_path
// El fichero de la factura mostrada
ls_path = "C:\factures\" + is_number + ".pdf"
// Sin fichero, nada que mostrar : vaciamos el visor en lugar de dejar el documento anterior
if not FileExists(ls_path) then
uo_pdf.is_source = ""
uo_status.of_panel(/*key*/ "main").is_text = "Factura no encontrada"
return
end if
// Si no, se muestra la factura
uo_pdf.is_source = ls_path
Mostrar un PDF leído de la base de datos (blob) #
// Local variables
blob lblb_pdf
// La factura guardada en la base de datos, leida en un blob
SELECTBLOB pdf_file INTO :lblb_pdf FROM invoice WHERE invoice_no = :is_number USING SQLCA;
// Mostrada directamente desde la memoria : ningun fichero temporal, sea cual sea su tamano
if SQLCA.SQLCode = 0 then
uo_pdf.of_load_blob(/*pdf*/ lblb_pdf, /*name*/ "invoice-" + is_number + ".pdf")
end if
El nombre dado vuelve en is_source y en ue_load_completed; el blob se libera con el documento siguiente o con of_reset.
Señalar una línea concreta del documento #
// El lector se abre en el primer pasaje de este texto, resaltado
uo_pdf.is_find = "Delivery and assembly"
uo_pdf.is_source = "C:\factures\FA-2026-0142.pdf"
Abrir en un capítulo, marcadores visibles #
// El panel lateral y sus marcadores, abierto en el capitulo "prices" del catalogo
uo_pdf.ib_navigation_pane = true
uo_pdf.is_destination = "prices"
uo_pdf.is_source = "doc\catalogue-2026.pdf"
El nombre de un destino es el que escribió la herramienta que generó el PDF: su generador de documentos lo conoce.
Un documento detrás de un token, o servido como octet-stream #
// Local variables
long ll_status
string ls_file
// El restclient (inv_rest, preparado al abrir la ventana) envia el token y descarga el fichero
ls_file = "C:\temp\invoice-4152.pdf"
ll_status = inv_rest.of_download(/*url*/ "/orders/4152/invoice.pdf", /*path*/ ls_file)
// Luego el visor muestra el fichero, sea cual sea el tipo anunciado por el servidor
if ll_status = 200 then
uo_pdf.is_source = ls_file
end if
El lector del motor no sabe enviar un token ni mostrar una respuesta application/octet-stream (REASON_AUTH, REASON_NOT_PDF): el restclient lo hace por él.
Formatos y rutas admitidos #
Forma de is_source | Ejemplo | Observación |
|---|---|---|
| Ruta absoluta | "C:\docs\contrat.pdf" | La más fiable |
| Ruta relativa | "doc\notice.pdf" | Relativa al directorio de la aplicación |
| Ruta de red | "\\serveur\partage\bon.pdf" | El usuario debe tener permisos de lectura |
Nombre con # | "C:\devis\Devis #12.pdf" | El # forma parte del nombre del fichero |
Dirección file: | "file:///C:/docs/contrat.pdf" | Convertida en ruta, como una ruta absoluta; también file://localhost/C:/… y la forma UNC de cuatro barras file:////servidor/recurso/… |
| Dirección web | "https://…/catalogue.pdf" | Servida como application/pdf, carga asíncrona. Un #page=… escrito en la dirección se ignora: use ii_page. Una dirección que lleva credenciales (https://nombre:secreto@…) se rechaza (REASON_UNSUPPORTED): pase por el restclient |
| Documento en memoria | "data:application/pdf;base64,…" | No se escribe nada en el disco. Más allá de 2 MB de caracteres (unos 1,5 MB de PDF), ue_load_failed con REASON_TOO_LARGE: para un documento en memoria más grande, of_load_blob |
Dirección http:// | "http://intranet/bon.pdf" | No admitida: ue_load_failed con REASON_INSECURE. Sirva el documento en https:// |
| Vacío | "" | Vacía el visor y conserva sus ajustes; un valor hecho de espacios también |
Este componente solo admite PDF: lo demás se rechaza y se señala con ue_load_failed (REASON_NOT_PDF). Para una imagen, utilice picture; para una página HTML, webbrowser.
Buenas prácticas #
- Vigile
ue_load_failed: una ruta no válida, un fichero que no es un PDF o un sitio inaccesible se señala ahí con su causa, y el visor permanece vacío. - Para vaciar el visor (cambio de fila sin adjunto), asigne
is_source = "": de lo contrario, el documento anterior permanece visible.of_reset()también lo vacía, pero además devuelve todos los ajustes a su valor por defecto — Guardar e Imprimir incluidos. of_refresh()es el modo de mostrar un fichero regenerado en la misma ruta: vuelve a leer el fichero sin tocar los ajustes. No conserva la posición de desplazamiento — el lector vuelve a empezar enii_page.- Cada cambio de
ii_zoom,is_fit,ib_viewer_toolbar,ib_navigation_pane,is_destination,is_find,ib_allow_saveoib_allow_printvuelve a cargar el documento (el lector solo lee sus ajustes al cargar) y activa de nuevoue_load_completed: asígnelos antes deis_sourcepara una sola carga. El mismo valor asignado otra vez no vuelve a cargar nada.ii_pageasignado mientras se muestra un documento vale para ese documento: para abrir otro en una página, asigneis_sourcey luegoii_page. - Prevea un indicador de espera para los documentos remotos o voluminosos, y ocúltelo en
ue_load_completedy enue_load_failed. - Dé al componente una superficie cómoda (al menos la mitad de la ventana): la barra de herramientas integrada y el documento necesitan espacio para seguir siendo legibles.
- Para mostrar una página web en lugar de un PDF, utilice webbrowser; para una imagen, picture.
Heredado de la base común #
Estos miembros existen en todos los componentes visuales — no son propios de este. Se detallan una sola vez, en los capítulos transversales; esta tabla solo dice dónde leerlos.
| Miembros | Función | Detallado en |
|---|---|---|
of_reset | Poner el componente a cero | 3.6 Poner un componente a cero: of_reset() |
of_register_shortcut · of_clear_shortcuts | Atajos de teclado del componente | 3.5 Los atajos de teclado |
of_is_created · of_is_ready · of_get_last_error | Si ha nacido, si está listo, qué ha fallado | 3.7 Diagnóstico |
of_save_as_png · of_save_as_jpg | Exportar el render como imagen | 3.8 Exportar la representación como imagen |
of_set_redraw | Agrupar los cambios en un solo repintado | 3.10 Buenas prácticas |
of_preload_icons | Iconos mostrados sin retardo | Visualización instantánea: of_icon |
of_set_translation | Traducir una etiqueta del componente | 5.2 Adaptar una etiqueta: of_set_translation |
of_focus_webview | Dar el foco al componente | 6.4 Teclado y foco |
of_print · of_print_to_pdf | Imprimir, o escribir un PDF | 6.9 Imprimir |
of_set_property · of_get_property · of_component_name | Controlar una propiedad por su nombre | 3.1 El motor de propiedades |
is_accessible_name · is_accessible_description | El nombre y la descripción que dice un lector de pantalla | 3.4 Propiedades y eventos opcionales |
Dos ayudas no se heredan: of_icon y of_escape_markup viven en n_pbt_utils. Declare uno — n_pbt_utils lnv_utils, nada que crear — y llámelas sobre él.