PBToolboxAI v4 ← Site

pdfviewer — u_pbt_pdfviewer #

← Component reference · Guide contents

Built-in PDF viewer: displays a local document or one published on the web, straight inside your window, with pagination, zoom and printing.

▶ See it live — Demo application, PDF viewer tile: the preview, the code behind it and this page, side by side.


At a glance #

Userobjectu_pbt_pdfviewer
Item class— (component without items)
Used forDisplaying an invoice, a purchase order, a contract or a manual without launching an external application
Opt-in options—

The component replaces the classic "save the PDF to a temporary file, then call ShellExecute": the document stays inside your application, and the user never leaves the current screen.


Quick start #

// window open event : display a document stored on disk
uo_pdf.is_source = "C:\factures\FA-2026-0142.pdf"
// ue_load_completed event of uo_pdf : (string as_source)
uo_status.of_panel(/*key*/ "main").is_text = "Document displayed"

That is all: setting is_source is enough to load and display the document.


Properties #

PropertyTypeDefaultPurpose
is_sourcestring""Document to display: a file path (absolute, relative to the application or on the network; a # is part of the name), a file:/// address, a web address https://… served as application/pdf, or a data:application/pdf address. Setting the value triggers the load; setting "" clears the viewer. Anything else is refused and reported by ue_load_failed — http:// included. Reads back as you wrote it
ii_pageinteger0Page displayed, counted from 1 (0 = the document's first page). A page set before is_source applies to that document; otherwise a new document opens at its first page. Every change reloads the document and raises ue_load_completed again: the reader only reads its page when a document loads. Write only: reading it back gives the last page you asked for, not the one on screen. The reader is the one built into the web engine, and it reports nothing.
ii_zoominteger0Zoom in percent (0 = left to the viewer). Setting a zoom cancels is_fit, which contradicts it. Write only, like ii_page: if the user zooms with the reader's own toolbar, this property does not follow.
is_fitstring""Fit mode: FIT_PAGE, FIT_WIDTH, FIT_HEIGHT, or "" for none. Cancels ii_zoom
ib_viewer_toolbarbooleantrueShows the viewer's own toolbar (page number, zoom, print, download). Hide it when your window carries those commands itself
ib_allow_savebooleantrueOffers the Save and Save as commands of the reader's toolbar and of its menu. At false, the document is shown without offering to save a copy. It is not a protection: the file stays readable on the disk. Every change reloads the document on screen
ib_allow_printbooleantrueOffers the Print command of the reader's toolbar and of its menu. of_print still prints: your application decides. Every change reloads the document on screen
is_theme_stylestring""Visual style of the component (THEME_STYLE_* constants); empty = the application's, followed at every change
is_theme_modestring""Light or dark variant (THEME_MODE_* constants); empty = the application's, followed at every change
il_theme_accentlong-1Accent colour of this component (-1 = the application accent, or the theme's)

Methods #

MethodPurpose
of_refresh ( )Reads the current document again (from disk or the network) without touching the settings: the way to show a file regenerated at the same path. The scrolling position is not kept: the reader starts again at ii_page. After a failure, tries the same document again. A refused document is judged again: ue_load_failed is raised again. Returns 0 once asked, -4 without a document (is_source empty), -2 if the component is not created
of_print ( ) · of_print (boolean)Opens the print preview of the document — not of the page that frames it. Returns 0 once the preview is asked for, -4 when no document is on screen, -2 when the component is not created. The argument has no effect here: it is always the PDF reader's preview
of_print_to_pdf (string)Returns -4 on this component, without writing anything: the printed page would only be the reader's frame, never the document. The document already is a PDF: copy the file of is_source
of_reset ( )Clears the viewer and resets every property to its default. Returns 0 once applied, -2 when the component is not created
of_set_redraw (boolean)Groups a burst of changes into a single render. Returns 0 once applied, -2 when the component is not created
of_save_as_png (string) · of_save_as_jpg (string)Exports the rendering as an image. Returns 0 once the image is written, -4 when writing fails, -2 when the component is not created

Events #

EventRaised when
ue_load_completed (string as_source)The document is on screen; as_source is is_source as you wrote it. Also raised by of_refresh and by every change of page, zoom, fit or viewer toolbar. Never raised on a failure
ue_load_failed (string as_source, string as_reason)The document could not be shown; as_reason is one of the REASON_* constants below. The viewer stays empty
ue_link_clicked (string as_url)The user followed a link in the document. The viewer stays on the document: open as_url wherever you want (the system browser, a webbrowser…). as_url is the link's address as is (https://…, mailto:…); a link to a local file — relative to the document included — arrives as a disk path
ue_ready ( )The component has finished loading; everything sent beforehand has been replayed
ue_runtime_missing ( )The WebView2 runtime is missing: the component stays empty
ue_bg_color (long al_color)The component has computed its theme background color; the userobject has already adopted it (backcolor)

Why a document is not shown #

as_reason of ue_load_failed is one of these u_pbt_pdfviewer constants. A PDF is recognised this way: a local file has the .pdf extension and starts with the %PDF- signature; a remote document is served with the application/pdf type (the only one the engine hands to its reader); a data: address announces application/pdf.

ConstantValueCause
REASON_NOT_FOUND"notfound"Missing or unreadable file, address answering 404
REASON_NOT_PDF"notpdf"Not a PDF: local file without the %PDF- signature, remote answer that is not application/pdf, data: of another type
REASON_TOO_LARGE"toolarge"File too large for this process (beyond 64 MB in 32-bit, 512 MB in 64-bit), or a data: address of more than 2 MB of characters (about 1.5 MB of PDF)
REASON_INSECURE"insecure"http://: not supported, serve the document over https://
REASON_UNSUPPORTED"unsupported"Another kind of address (ftp:, blob:…)
REASON_NETWORK"network"Server unreachable, unknown name, connection cut
REASON_CERTIFICATE"certificate"The site's certificate is invalid, expired or revoked
REASON_AUTH"auth"The site or the proxy asks for authentication
REASON_HTTP"http"Another server error (403, 500…)
REASON_REFUSED"refused"The site refuses to be shown in a frame, or sends the PDF as a download — the file is not downloaded for all that
REASON_FAILED"failed"Any other cause

What the user can do, without a single line of code #

The viewer displays its built-in toolbar above the document. There is nothing for you to program: it is provided and localized by the system.

ActionHow
PaginationMouse wheel and scroll bar, or type the page number directly in the n / total counter
Zoom+ / − buttons, fit to page or fit to width
SearchThe search button of the toolbar, in the text of the document
PrintingThe printer button of the toolbar (can be hidden with ib_allow_print), or of_print from your code
SavingThe download button, to save a copy of the document (can be hidden with ib_allow_save)
RotationPage rotation from the toolbar menu
KeyboardAs soon as the component has the focus (Tab or of_focus_webview): PageDown, the arrows, Home / End scroll the document, without a click first

The browser's shortcuts — Ctrl+F, Ctrl+P, Ctrl + wheel — are switched off in every component, this one included: use the buttons of the reader's toolbar.

What the reader does not say #

The reader is the one built into the web engine: nothing to install, printing, search, PDF forms and full screen included. In return, it reports nothing to your application: not the page on screen, not the number of pages, not the real zoom, not the selected text, and search cannot be driven from code. ii_page and ii_zoom say where to open the document, not where the user is. This is a deliberate choice for 4.0; a scriptable rendering would need an external library.


Examples #

Opening a local document #

// Absolute path, or relative to the application directory
uo_pdf.is_source = "doc\conditions-generales.pdf"

Opening a document published on the web #

// A web address loads exactly like a local file
uo_pdf.is_source = "https://www.monsite.fr/tarifs/catalogue-2026.pdf"

An internet connection is of course required; the load is asynchronous, and ue_load_completed tells you when it is done.

Displaying the PDF a DataWindow has just produced #

// Local variables
string ls_file

// One file per day, in the temporary folder
ls_file = "C:\temp\report_" + String(Today(), "yyyymmdd") + ".pdf"

// The DataWindow produces the file...
dw_report.SaveAs(ls_file, PDF!, false)

// ...and the viewer displays it immediately
uo_pdf.is_source = ls_file

Refreshing after the file has been regenerated #

// The file was rewritten in the same location : reload without touching is_source
uo_pdf.of_refresh()

Chaining several documents in the same viewer #

// ue_row_changed event of dw_list : display the attachment of the current row
string ls_pdf

// The path of the PDF of the current row
ls_pdf = dw_list.GetItemString(dw_list.GetRow(), "pdf_path")

// No attachment empties the viewer ; otherwise it shows it
if ls_pdf = "" then
    uo_pdf.of_reset()          // no attachment : empty viewer
else
    uo_pdf.is_source = ls_pdf
end if

Tracking the end of the load #

// ue_load_completed event of uo_pdf : (string as_source)
uo_wait.Hide()

// of_print prints the document on screen
uo_print_button.ib_enabled = true

Saying why the document is not there #

// ue_load_failed event of 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 = "Document not found: " + as_source
	case uo_pdf.REASON_NOT_PDF
		uo_status.of_panel(/*key*/ "main").is_text = "This file is not a PDF"
	case else
		uo_status.of_panel(/*key*/ "main").is_text = "Document unavailable (" + as_reason + ")"
end choose
// ue_link_clicked event of uo_pdf : (string as_url)
// The viewer stays on the document : the link opens in the window's browser
uo_web.is_address = as_url

Printing the document #

// clicked of the Print button : the PDF reader's preview, on the document itself
if uo_pdf.of_print() = -4 then
	uo_status.of_panel(/*key*/ "main").is_text = "No document to print"
end if

Showing without letting save or print #

// A confidential document : neither Save nor Print in the reader's bar
uo_pdf.ib_allow_save = false
uo_pdf.ib_allow_print = false
uo_pdf.is_source = is_current_document

Set them before is_source: every change reloads the document. It is not a protection: the file stays readable on the disk, and of_print still prints.

Preview in a tab, next to data entry #

// open event : the viewer takes one tab page, data entry the other
uo_tab.of_add_page(/*key*/ "entry",  /*title*/ "Entry",   /*page*/ uo_page_entry)
uo_tab.of_add_page(/*key*/ "preview",  /*title*/ "Preview",   /*page*/ uo_page_preview)

// The viewer sits inside uo_page_preview like any other control
uo_pdf.is_source = is_current_document

The component is hosted with no special precautions inside a tab or a dockcontainer panel.

Checking the file before displaying it #

// Local variables
string ls_path

// The file of the invoice on screen
ls_path = "C:\factures\" + is_number + ".pdf"

// No file, nothing to show : clear the viewer rather than leave the previous document
if not FileExists(ls_path) then
    uo_pdf.of_reset()
    uo_status.of_panel(/*key*/ "main").is_text = "Invoice not found"
    return
end if

// Otherwise, the invoice is shown
uo_pdf.is_source = ls_path

Accepted formats and paths #

Form of is_sourceExampleNote
Absolute path"C:\docs\contrat.pdf"The most reliable
Relative path"doc\notice.pdf"Relative to the application directory
Network path"\\serveur\partage\bon.pdf"The user must have read permissions
Name with #"C:\devis\Devis #12.pdf"The # is part of the file name
file: address"file:///C:/docs/contrat.pdf"Converted to a path, like an absolute path; file://localhost/C:/… and the four-slash UNC form file:////server/share/… too
Web address"https://…/catalogue.pdf"Served as application/pdf, asynchronous load. A #page=… written in the address is ignored: use ii_page
In-memory document"data:application/pdf;base64,…"Nothing is written to disk. Beyond 2 MB of characters (about 1.5 MB of PDF), ue_load_failed with REASON_TOO_LARGE: write the file and give its path
http:// address"http://intranet/bon.pdf"Not supported: ue_load_failed with REASON_INSECURE. Serve the document over https://
Empty""Clears the viewer

This component only supports PDF: anything else is refused and reported by ue_load_failed (REASON_NOT_PDF). For an image, use picture; for an HTML page, webbrowser.


Best practices #

Inherited from the common base #

These members exist on every visual component — they are not specific to this one. They are detailed once, in the transverse chapters; this table only says where to read them.

MembersRoleDetailed in
of_resetPut the component back to zero3.6 Resetting a component: of_reset()
of_register_shortcut · of_clear_shortcutsThe component's keyboard chords3.5 Keyboard shortcuts
of_is_created · of_is_ready · of_get_last_errorWhether it was born, whether it is ready, what failed3.7 Diagnostics
of_save_as_png · of_save_as_jpgExport the rendering as an image3.8 Exporting the rendering as an image
of_set_redrawGroup changes into a single repaint3.10 Best practices
of_preload_iconsIcons shown with no delayInstant display: of_icon
of_set_translationTranslate one of the component's labels5.2 Adapting a label: of_set_translation
of_focus_webviewGive the component the focus6.4 Keyboard and focus
of_print · of_print_to_pdfPrint, or write a PDF6.9 Printing
of_set_property · of_get_property · of_component_nameDriving a property by its name3.1 The property engine

Two helpers are not inherited: of_icon and of_escape_markup live on n_pbt_utils. Declare one — n_pbt_utils lnv_utils, nothing to create — and call them on it.


← Component reference · Guide contents