PBToolboxAI v5 ← Site

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 #

Userobjectu_pbt_pdfviewer
Clase de items— (componente sin items)
Sirve paraMostrar 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 #

PropiedadTipoPredeterminadoFunción
is_sourcestring""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_pageinteger0Pá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_zoominteger0Zoom 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_fitstring""Ajuste: FIT_PAGE, FIT_WIDTH, FIT_HEIGHT, o "" para ninguno. Anula ii_zoom
ib_viewer_toolbarbooleantrueMuestra 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_destinationstring""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_savebooleantrueOfrece 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_printbooleantrueOfrece 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_searchbooleantrueOfrece 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_rotatebooleantrueOfrece 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_panebooleantrueOfrece 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_stylestring""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_modestring""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_accentlong-1Color 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étodoFunció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 #

EventoSe 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.

ConstanteValorCausa
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ónCómo
PaginaciónRueda del ratón y barra de desplazamiento, o escritura directa del número de página en el contador n / total
ZoomBotones + / −, ajuste a la página o al ancho
BúsquedaEl botón de búsqueda de la barra de herramientas, en el texto del documento
ImpresiónBotón de impresora de la barra de herramientas (se oculta con ib_allow_print), o of_print desde su código
GuardadoBotón de descarga, para guardar una copia del documento (se oculta con ib_allow_save)
RotaciónRotación de las páginas desde el menú de la barra de herramientas
TecladoEn 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_sourceEjemploObservació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 #

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.

MiembrosFunciónDetallado en
of_resetPoner el componente a cero3.6 Poner un componente a cero: of_reset()
of_register_shortcut · of_clear_shortcutsAtajos de teclado del componente3.5 Los atajos de teclado
ib_created · ib_ready · is_last_errorSi ha nacido, si está listo, qué ha fallado3.7 Diagnóstico
of_save_as_png · of_save_as_jpgExportar el render como imagen3.8 Exportar la representación como imagen
of_set_redrawAgrupar los cambios en un solo repintado3.10 Buenas prácticas
of_preload_iconsIconos mostrados sin retardoVisualización instantánea: of_icon
of_set_translationTraducir una etiqueta del componente5.2 Adaptar una etiqueta: of_set_translation
of_focus_webviewDar el foco al componente6.4 Teclado y foco
of_print · of_print_to_pdfImprimir, o escribir un PDF6.9 Imprimir
of_set_property · of_get_property · is_component_nameControlar una propiedad por su nombre3.1 El motor de propiedades
is_accessible_name · is_accessible_descriptionEl nombre y la descripción que dice un lector de pantalla3.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.


← Referencia de componentes · Índice de la guía