statictext — u_pbt_statictext #
← Component reference · Guide contents
Rich text block: markup, alignments, clickable links and actions, header look, scrolling mode (marquee) and file drop zone.
▶ See it live — Demo application, Statictext tile: the preview, the code behind it and this page, side by side.
At a glance #
| Userobject | u_pbt_statictext |
| Item class | — (component without items) |
| Used for | Replacing a PowerBuilder statictext with a formatted, clickable text block that can act as a header, a scrolling banner or a drop zone |
| Opt-in options | ib_auto_height, ib_auto_width, ib_follow_end, ib_track_mouse, ib_track_cycle, ib_allow_drop, ib_selectable, ib_hover_effect |
Quick start #
// window open event
uo_text.is_text = "Welcome to [b][accent]PBToolboxAI[/accent][/b][br]" &
+ "See the [hyperlink=https://pbtoolboxai.net]documentation[/hyperlink]."
uo_text.is_align = uo_text.ALIGN_CENTER
uo_text.is_valign = uo_text.VALIGN_CENTER
The text accepts rich text markup: this is the component that makes the most of it, since it is the only one that makes [action=…] areas clickable (a [hyperlink=…] opens everywhere).
Constants #
| Constant | Value | For |
|---|---|---|
ALIGN_START · ALIGN_CENTER · ALIGN_END · ALIGN_JUSTIFY | "start" "center" "end" "justify" | is_align |
VALIGN_TOP · VALIGN_CENTER · VALIGN_BOTTOM | "top" "center" "bottom" | is_valign |
start and end are logical: they follow the writing direction (Language and RTL). The physical values left and right are still accepted as aliases.
Properties #
Text and formatting #
| Property | Type | Default | Purpose |
|---|---|---|---|
is_text | string | "" | The text displayed, with rich text markup: [b], [i], [u], colors, [picture=…], [hyperlink=…], [action=…] |
is_align | string | "start" | Horizontal alignment: ALIGN_START, ALIGN_CENTER, ALIGN_END, ALIGN_JUSTIFY |
is_valign | string | "top" | Vertical alignment within the control: VALIGN_TOP, VALIGN_CENTER, VALIGN_BOTTOM |
ib_wrap | boolean | true | Automatic word wrap. false forces a single line |
ib_ellipsis | boolean | false | With ib_wrap = false, truncates the overflow with an ellipsis instead of cutting it off |
ib_ellipsis_tooltip | boolean | false | Opt-in: when the text does not fit the box, show it in full in a tooltip (markup included). Never replaces a tooltip you set yourself with is_tooltip or is_super_tooltip_*: yours wins |
is_font_family | string | "" | Default font for the block (empty = font from the theme) |
ii_font_size | integer | 0 | Default size in points (0 = size from the theme) |
il_text_color | long | -1 | Text color as RGB() (-1 = color from the theme). [color] tags still take precedence over their own span |
ii_line_spacing | integer | 0 | Line spacing as a percentage, from 50 to 400 (150 = 1.5 lines; 0 = default). A value out of that range is brought back to the nearest bound, and read back as applied |
ib_enabled | boolean | true | Block enabled or grayed out (links and actions are inert when it is grayed out) |
ib_selectable | boolean | false | Opt-in: lets the user select the text and copy it with Ctrl+C (off by default, like a label). Releasing the mouse after a selection does not raise ue_clicked |
Block look (the "header" look) #
| Property | Type | Default | Purpose |
|---|---|---|---|
il_back_color | long | -1 | Block background as RGB() (-1 = background from the theme). With ii_corner_radius it follows the rounded corners, and outside them the block shows the color of the object it sits on |
il_border_color | long | -1 | Border color (-1 = no border) |
ii_border_width | integer | 0 | Border thickness in pixels (0 = no border) |
ii_corner_radius | integer | 0 | Corner rounding radius, in pixels. The border AND the il_back_color background follow it |
ii_padding | integer | -1 | Inner margin in pixels: -1 = the theme's margin (default), 0 = no margin at all (the text lines up with the edge of a neighbouring field), more = pixels |
ib_hover_effect | boolean | false | Opt-in: slight darkening on hover (lightening on a dark theme), for a label acting as a button |
Scrolling mode (marquee) #
| Property | Type | Default | Purpose |
|---|---|---|---|
ib_marquee | boolean | false | Turns the block into a horizontally scrolling banner |
ii_marquee_speed | integer | 60 | Scrolling speed, in pixels per second (0 = default speed, 60) |
is_marquee_direction | string | MARQUEE_START | Scrolling direction: MARQUEE_START (toward the start of the reading direction) or MARQUEE_END. The physical aliases "left" / "right" are accepted: they stay physical, whatever the reading direction. Any other value is taken, and read back, as MARQUEE_START |
ib_marquee_overflow_only | boolean | false | Opt-in: scroll only when the text is too wide for the box. A banner scrolling a text that already fits is pure visual noise. Off by default, so ib_marquee = true keeps meaning it scrolls |
ib_marquee_pause_on_hover | boolean | false | Opt-in: stop the scrolling while the pointer is over the block, so a long text can actually be read. The loop position is kept: nothing jumps when the pointer leaves |
Optional interactions #
| Property | Type | Default | Purpose |
|---|---|---|---|
ib_allow_drop | boolean | false | Opt-in: accepts files dropped from Windows Explorer; the full paths arrive through ue_drop_files. A disabled text (ib_enabled = false) refuses every drop |
ib_track_mouse | boolean | false | Opt-in: enables ue_mouse_enter / ue_mouse_leave |
ib_track_cycle | boolean | false | Opt-in: enables ue_cycle, raised at the end of each scrolling pass; without it, the text scrolls in silence |
ib_auto_height | boolean | false | Opt-in: the block measures its ideal height and resizes the userobject; see Shared foundation |
ib_auto_width | boolean | false | Opt-in: the userobject takes the WIDTH of its text — the longest line, without wrapping (the [br] breaks count), plus the padding and the border; a new text, a font or a padding resizes it again, and ue_auto_width tells the width settled on. A scrolling banner (ib_marquee) has no natural width and reports none |
ib_follow_end | boolean | false | Opt-in, for a log written with of_append_text: the view stays at the BOTTOM as lines arrive — unless the reader scrolled up to read an older line: he is never pulled away from it |
is_theme_style | string | "" | Visual style of the component (THEME_STYLE_* constants); empty = the application's, followed at every change |
is_theme_mode | string | "" | Light or dark variant (THEME_MODE_* constants); empty = the application's, followed at every change |
il_theme_accent | long | -1 | Accent colour of this component (-1 = the application accent, or the theme's) |
is_tooltip | string | "" | Simple tooltip shown when hovering the component |
is_super_tooltip_title | string | "" | Title of the rich tooltip (takes precedence over is_tooltip) |
is_super_tooltip_text | string | "" | Text of the rich tooltip (rich markup accepted) |
is_super_tooltip_image | string | "" | Image of the rich tooltip |
Methods #
| Method | Purpose |
|---|---|
of_reset ( ) | Resets every property to its default and clears the text. 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 |
of_refresh_parent_color ( ) | Reads again the colour of the object the block sits on. With il_back_color and ii_corner_radius, the rounded corners show that colour, read when those two properties are set: call it after changing the BackColor of your window, or after moving the block to another parent. Returns 0 once sent, -2 when the component is not created |
of_scroll_to_end ( ) | Scrolls to the bottom of the text. For a log, whose newest line sits at the end: without it that line drops below the fold as soon as the text outgrows the visible height. Returns 0 once sent, -2 when the component is not created |
of_append_text (string as_markup) | Adds ONE line at the end of the text, for a log: only that line travels to the component and only that line is drawn — rewriting is_text at every line sent and drew the whole log again. as_markup takes the same markup as is_text; read back, is_text holds every line, joined by [br]. With ib_follow_end the view stays at the bottom. Returns 0 once sent, -2 when the component is not created |
Events #
| Event | Raised when |
|---|---|
ue_clicked ( ) | Left click on the block — not raised on an [action] or [hyperlink] area (no duplicates), on the header of a [foldarea] (folding raises nothing), nor after a text selection |
ue_hyperlink (string as_url) | A [hyperlink=url] zone was clicked. The browser opens on its own: the event reaches you as well, to log the click or do more with it |
ue_action (string as_key) | An [action=id] area has been clicked: it is up to you to hook your code in. The area is reachable with the keyboard too: Tab to it, then Enter or Space |
ue_drop_files (string as_files[]) | Files have been dropped from Windows: full paths, one entry per file. Requires ib_allow_drop = true |
ue_drag_enter ( ) | A file drag enters the component (ib_allow_drop) |
ue_drag_leave ( ) | The file drag leaves the component |
ue_auto_height (long al_height) | The block has computed its ideal height — requires ib_auto_height = true |
ue_auto_width (long al_width) | The block has taken a new width, in PowerBuilder units — requires ib_auto_width = true |
ue_rclicked ( ) | Right click on the block |
ue_double_clicked ( ) | Double click on the block, like the native PowerBuilder StaticText. The single clicks that precede it are raised too, in the same order. Not raised on an [action] or [hyperlink] zone, which have their own channel |
ue_text_overflow (boolean ab_truncated) | The text stopped fitting the box — or fits again. Raised only on change, never as a flood: a wrapped block counts as cut when it is clipped at the bottom, a single-line one when it is cut on the side. Handle it to widen a column, offer a see more button, or simply switch ib_ellipsis_tooltip on |
ue_mouse_enter ( ) | The mouse enters — requires ib_track_mouse = true |
ue_mouse_leave ( ) | The mouse leaves — requires ib_track_mouse = true |
ue_cycle ( ) | Scrolling mode only: the text has just finished a full pass (an animation INSIDE the text never counts as a pass) — requires ib_track_cycle = true |
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) |
Examples #
A section header #
Solid background, centered white text and a height fitted to the content: the block reads like a real title bar.
// Freeze the drawing while everything is set
uo_header.of_set_redraw(/*on*/ false)
// The title, centred
uo_header.is_text = "[b]Sales dashboard"
uo_header.is_align = uo_header.ALIGN_CENTER
// Solid background and readable white text
uo_header.il_back_color = RGB(/*red*/ 60, /*green*/ 110, /*blue*/ 190)
uo_header.il_text_color = RGB(/*red*/ 255, /*green*/ 255, /*blue*/ 255)
uo_header.ii_padding = 14
// The block hugs its content : it reads like a title bar
uo_header.ib_auto_height = true
// Everything is drawn at once
uo_header.of_set_redraw(/*on*/ true)
// ue_auto_height event of uo_header
of_reposition_below_header(al_height) // moves the content below the header
Rich text with a link and an action #
// A link to a web page, and an action your application handles (ue_action)
uo_text.is_text = "Your license expires on [b]12/31[/b]. " &
+ "[hyperlink=https://pbtoolboxai.net]Learn more[/hyperlink] " &
+ "or [action=renew]renew it now[/action]."
// ue_action event of uo_text : (string as_key)
choose case as_key
case "renew" ; of_open_renewal()
end choose
ue_hyperlink is meant for URLs (the browser opens on its own); [action=id] is the right choice when the click has to stay inside your application. The [invisibleaction=id] variant raises the same ue_action without looking like a link.
A collapsible block #
// Two foldable sections : the second one starts folded
uo_recap.is_text = "[b]Order 2026-0148[/b][br]" &
+ "[foldarea:[b]Delivery[/b]]Shipped on 12/07, within 48 hours.[/foldarea]" &
+ "[foldarea-closed:[i]Legal notice[/i]]Returns accepted within 14 days.[/foldarea]"
// The block shrinks when a section is folded
uo_recap.ib_auto_height = true
A [foldarea:Title] adds a clickable header above its content: the reader folds the section with a click, and the marker turns from − into +. [foldarea-closed:Title] produces the same block, folded from the start. Blocks nest, and folding raises no event: it is a reading matter, not a coding one. When ib_auto_height is on, the height is reported again on every fold. The title is markup: [foldarea:[b][accent]Order 2026-0148[/accent][/b]] makes its own bold and accent-colored.
A scrolling banner #
// The message of the banner
uo_banner.is_text = "[b]Notice[/b] -- the service will be closed on Friday the 12th."
// Scrolling mode, news-ticker style
uo_banner.ib_marquee = true
uo_banner.ii_marquee_speed = 90 // pixels per second
uo_banner.is_marquee_direction = uo_banner.MARQUEE_START
The scrolling loops with no dead time. To stop it, set ib_marquee back to false: the text returns to its normal layout.
Once ib_track_cycle = true is set, the ue_cycle event is raised on every full pass of the text — handy for rotating several messages:
// In ue_cycle of the banner : move on to the next message
ii_message = Mod(ii_message, UpperBound(is_messages)) + 1
uo_banner.is_text = is_messages[ii_message]
A file drop zone #
// Accept files dragged from Windows Explorer
uo_zone.ib_allow_drop = true
// What the zone shows, centred
uo_zone.is_text = "[size=32][accent][b]Drop your files here[/b][/accent][/size][br][br]" &
+ "Drag one or more files from Windows Explorer."
uo_zone.is_align = uo_zone.ALIGN_CENTER
uo_zone.is_valign = uo_zone.VALIGN_CENTER
// ue_drop_files event of uo_zone : (string as_files[])
integer li
// Each dropped file, one after the other
for li = 1 to UpperBound(as_files)
of_import(as_files[li]) // as_files[li] = FULL path of the file
next
// ue_drag_enter event of uo_zone : highlight the target while hovering
uo_zone.il_border_color = RGB(/*red*/ 21, /*green*/ 101, /*blue*/ 192)
uo_zone.ii_border_width = 2
The paths you receive are full paths: you can pass them straight to FileOpen or to your own import routine.
A label that behaves like a button #
// A text that behaves like a link button
uo_link.is_text = "Select all"
uo_link.il_text_color = RGB(/*red*/ 21, /*green*/ 101, /*blue*/ 192)
uo_link.ii_padding = 8
uo_link.ii_corner_radius = 6
uo_link.ib_hover_effect = true // reacts to hover like a button
// ue_clicked event of uo_link
of_select_all()
A log written line by line #
Each call sends only the line added; ib_follow_end keeps the last one in view as long as the reader does not scroll up.
// Once, when the window opens
uo_log.ib_follow_end = true
uo_log.is_text = "[b]Import[/b]"
// For every row imported : one line, sent alone
uo_log.of_append_text(/*markup*/ "Row " + String(ll_row) + " [color=#2e7d32]imported[/color]")
A label as wide as its text #
// A status chip : background, rounded corners, and the width of its text
uo_status.is_text = "[b]Status :[/b] connected"
uo_status.il_back_color = RGB(/*red*/ 232, /*green*/ 245, /*blue*/ 233)
uo_status.ii_corner_radius = 12
uo_status.ib_auto_width = true
Best practices #
- Text without markup costs nothing extra: feel free to replace your PowerBuilder
statictextcontrols systematically, even for plain text. - Prefer
is_align = uo.ALIGN_STARTover"left": your screen will still be correct if the application switches to right-to-left writing. ib_selectablestays off by default, like a label. Turn it on only where copying makes sense (case number, technical error message).- For a header, combine
il_back_color+ii_padding+ib_auto_height: the block sizes itself when the text changes length. - Only turn
ib_track_mouseon if you really scriptue_mouse_enter/ue_mouse_leave. - Call
of_reset()before reusing a block for different content: otherwise a previous background, border or scrolling mode stays in place.
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.
| Members | Role | Detailed in |
|---|---|---|
of_reset | Put the component back to zero | 3.6 Resetting a component: of_reset() |
of_register_shortcut · of_clear_shortcuts | The component's keyboard chords | 3.5 Keyboard shortcuts |
of_is_created · of_is_ready · of_get_last_error | Whether it was born, whether it is ready, what failed | 3.7 Diagnostics |
of_save_as_png · of_save_as_jpg | Export the rendering as an image | 3.8 Exporting the rendering as an image |
of_set_redraw | Group changes into a single repaint | 3.10 Best practices |
of_preload_icons | Icons shown with no delay | Instant display: of_icon |
of_set_translation | Translate one of the component's labels | 5.2 Adapting a label: of_set_translation |
of_focus_webview | Give the component the focus | 6.4 Keyboard and focus |
of_print · of_print_to_pdf | Print, or write a PDF | 6.9 Printing |
of_set_property · of_get_property · of_component_name | Driving a property by its name | 3.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.