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 (número de página, zoom, impresión, descarga). Ocúltela cuando su ventana lleve esos comandos ella misma
ib_navigation_panebooleanfalseAbre 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_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
is_findstring""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_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. 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_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_fullscreenbooleantrueOfrece 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_stylestring""Estilo visual del componente (constantes THEME_STYLE_*); vacío = el de la aplicación, seguido en cada cambio
is_theme_modestring""Variante clara u oscura (constantes THEME_MODE_*); 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)

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) — 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 #

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

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, 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_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
of_is_created · of_is_ready · of_get_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 · of_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