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 (tabla de contenido, número de página, zoom, giro, búsqueda, impresión, guardado). Ocúltela cuando su ventana lleve esos comandos ella misma. El lector integrado en WebView2 no tiene comando Pantalla completa |
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 |
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. La búsqueda pertenece al usuario (también con Ctrl+F): el lector no ofrece ninguna búsqueda dirigida por 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_navigation_pane | boolean | true | Ofrece el botón Tabla de contenido de la barra del lector, arriba a la izquierda: abre el panel lateral con los marcadores y las miniaturas de las páginas. En false, el botón desaparece. Que el panel esté abierto es cosa del lector y del usuario: su aplicación ofrece el botón o no. 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 de la superficie propia del componente: lo que el visor muestra mientras no contiene ningún documento (antes del primero, tras is_source = "" o un documento rechazado). El lector PDF conserva su aspecto: sigue el tema de la aplicación (PBT_SetDefaultTheme), solo claro u oscuro, porque WebView2 da a todos sus lectores PDF un mismo esquema de colores. Vacío = el de la aplicación, seguido en cada cambio |
is_theme_mode | string | "" | Variante clara u oscura de la superficie propia del componente, visible mientras el visor no contiene ningún documento. El lector PDF no la sigue: su barra y sus márgenes toman el claro o el oscuro del tema de la aplicación (PBT_SetDefaultTheme). 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). Sin efecto visible aquí: ni el lector PDF ni el visor vacío dibujan con un acento. El valor se conserva y se relee tal como se asignó |
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) — is_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, destino o de un comando ib_allow_* — 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 y formularios PDF 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: el lector ignora los parámetros de apertura que resaltarían un texto o abrirían su panel lateral. No tiene comando Pantalla completa y sigue el tema claro u oscuro de la aplicación, nunca el del componente. 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.
Abrir en un capítulo #
// Abierto en el capitulo "prices" del catalogo; el boton Tabla de contenido del lector lista los marcadores
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,is_destination,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 |
ib_created · ib_ready · is_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 · is_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.