FormLib — Form Management Library
Complete functionality for creating and managing application windows in Plan9Basic. Create, show, position, style, and respond to events on forms across all six supported platforms. 105 functions.
| Category | Count | Description |
|---|---|---|
| Error Handling | 4 | form_error, form_errormsg$, form_strerror$, form_clearerror |
| Creation & Lifecycle | 5 | form# (3 overloads), form_free, form_close |
| Display | 7 | form_show, form_showmodal, form_showex#, form_hide, form_visible (get/set), form_showfullscreenicon (get/set) |
| Position & Size | 16 | left/top/width/height (get/set), bounds#, move#, size#, center# |
| Constraints | 6 | minwidth/minheight/maxwidth/maxheight (get/set), constraints# |
| Window State & Style | 14 | windowstate, maximize#, minimize#, restore#, borderstyle, formstyle, stayontop, fullscreen |
| Appearance | 6 | caption (get/set), fill (get/set), transparency (get/set) |
| Close Behavior | 5 | closeaction (get/set), allowclose (get/set), modalresult (get/set) |
| Client Area | 2 | form_clientwidth, form_clientheight |
| Padding | 3 | padding (get/set), paddings# |
| Utility | 7 | tag (get/set), active, bringtofront#, sendtoback#, setfocus#, invalidate#, handle |
| Screen Info | 4 | form_screenwidth, form_screenheight, form_screenscale, form_screenorientation |
| Events | 26 | 12 event types × set/get + clearcallbacks# |
Cross-Platform Support
| Platform | Status | Notes |
|---|---|---|
| Windows | ✅ Full Support | Win32/Win64 |
| Linux | ✅ Full Support | GTK-based |
| Android | ✅ Full Support | Mobile-optimized |
form_showmodal is only available on desktop platforms (Windows, macOS, Linux). On mobile, use form_showex# with a callback instead.Error Handling
| Code | Description |
|---|---|
| 0 | No error |
| 1 | Invalid or nil form |
| 2 | Invalid property |
| 3 | Invalid value |
| 4 | Form creation failed |
| 5 | Invalid callback function |
| Function | Signature | Description |
|---|---|---|
form_error() | form_error@ | Last error code (0–5) |
form_errormsg$() | form_errormsg$@ | Last error message as string |
form_strerror$(code) | form_strerror$@n | Description for a given error code |
form_clearerror() | form_clearerror@ | Clear the error state |
let frm# = form#("Test", 400, 300) if form_error() <> 0 then println "Error: " + form_errormsg$() endif
Numeric Values Reference
Plan9Basic does not have built-in constants. The tables below document the numeric values accepted by various functions. You can define your own named values for readability:
' Define readable names for numeric values let POS_SCREEN_CENTER = 4 let BORDER_SIZEABLE = 2 let CLOSE_FREE = 2 let STATE_MAXIMIZED = 2
Position Modes form_position#
| Value | Description |
|---|---|
| 0 | Use design-time position |
| 4 | Center on screen |
| 5 | Center on desktop |
| 6 | Center on main form |
Border Styles form_borderstyle#
| Value | Description |
|---|---|
| 0 | No border |
| 1 | Single-line border (non-resizable) |
| 2 | Standard resizable border |
| 3 | Tool window style |
| 4 | Resizable tool window |
Form Styles form_formstyle#
| Value | Description |
|---|---|
| 0 | Normal form |
| 1 | Stay on top |
| 2 | Popup window |
Close Actions form_closeaction#
| Value | Description |
|---|---|
| 0 | No action (form stays open) |
| 1 | Hide the form |
| 2 | Free/destroy the form |
| 3 | Minimize the form |
Window States form_windowstate#
| Value | Description |
|---|---|
| 0 | Normal window state |
| 1 | Minimized to taskbar |
| 2 | Maximized to fill screen |
Form Creation & Lifecycle
| Function | Signature | Description |
|---|---|---|
form#() | form#@ | Create form with defaults (640×480, centered) |
form#(caption$) | form#@$ | Create form with caption |
form#(caption$, w, h) | form#@$nn | Create form with caption and size |
form_free(frm#) | form_free@# | Destroy form and release all resources |
form_close(frm#) | form_close@# | Close form (triggers OnClose/OnCloseQuery events) |
' Default form let frm# = form#() ' Named form let frm# = form#("My Application") ' Named form with specific size let frm# = form#("My Application", 800, 600) ' Cleanup form_free(frm#)
form_free immediately destroys the form and all child controls.Form Display
| Function | Signature | Description |
|---|---|---|
form_show(frm#) | form_show@# | Show form non-modally |
form_showmodal(frm#) | form_showmodal@# | Show modally (desktop only, blocks until closed) |
form_showex#(frm#, func$) | form_showex#@#$ | Show with close callback (cross-platform) |
form_hide(frm#) | form_hide@# | Hide form |
form_visible(frm#) | form_visible@# | Get visibility (0 = hidden, 1 = visible) |
form_visible#(frm#, n) | form_visible#@#n | Set visibility (0/1) |
form_showfullscreenicon(frm#) | form_showfullscreenicon@# | Get fullscreen icon visibility (0/1) |
form_showfullscreenicon#(frm#, n) | form_showfullscreenicon#@#n | Show/hide the fullscreen icon (0/1) |
' Non-modal (program continues) form_show(frm#) ' Modal (desktop only — blocks until closed) form_showmodal(frm#) ' Cross-platform dialog with callback function OnDialogClosed(sender#, result) if result = 1 then println "OK clicked" else println "Cancelled" endif endfunction form_showex#(dlg#, "OnDialogClosed")
form_showex# is the recommended way to show dialogs on all platforms. The callback receives the form pointer and the modal result value.Position & Size
| Function | Signature | Description |
|---|---|---|
form_left(frm#) | form_left@# | Get X position |
form_left#(frm#, x) | form_left#@#n | Set X position |
form_top(frm#) | form_top@# | Get Y position |
form_top#(frm#, y) | form_top#@#n | Set Y position |
form_width(frm#) | form_width@# | Get width |
form_width#(frm#, w) | form_width#@#n | Set width |
form_height(frm#) | form_height@# | Get height |
form_height#(frm#, h) | form_height#@#n | Set height |
form_bounds#(frm#, x, y, w, h) | form_bounds#@#nnnn | Set position and size in one call |
form_move#(frm#, x, y) | form_move#@#nn | Set position only |
form_size#(frm#, w, h) | form_size#@#nn | Set size only |
form_center#(frm#) | form_center#@# | Center form on screen |
form_position(frm#) | form_position@# | Get position mode |
form_position#(frm#, n) | form_position#@#n | Set position mode (see Numeric Values) |
form_position#(frm#, 4) ' Center on screen form_bounds#(frm#, 100, 100, 800, 600) ' Exact placement form_center#(frm#) ' Re-center after resize println "Position: " + str$(form_left(frm#)) + ", " + str$(form_top(frm#)) println "Size: " + str$(form_width(frm#)) + " x " + str$(form_height(frm#))
Size Constraints
| Function | Signature | Description |
|---|---|---|
form_minwidth(frm#) | form_minwidth@# | Get minimum width |
form_minwidth#(frm#, w) | form_minwidth#@#n | Set minimum width |
form_minheight(frm#) | form_minheight@# | Get minimum height |
form_minheight#(frm#, h) | form_minheight#@#n | Set minimum height |
form_maxwidth(frm#) | form_maxwidth@# | Get maximum width |
form_maxwidth#(frm#, w) | form_maxwidth#@#n | Set maximum width |
form_maxheight(frm#) | form_maxheight@# | Get maximum height |
form_maxheight#(frm#, h) | form_maxheight#@#n | Set maximum height |
form_constraints#(frm#, minW, minH, maxW, maxH) | form_constraints#@#nnnn | Set all constraints at once |
' Prevent the form from being too small or too large form_constraints#(frm#, 400, 300, 1200, 800) ' Or set individually form_minwidth#(frm#, 320) form_minheight#(frm#, 240)
Client Area
The client area is the usable interior of the form, excluding the title bar and borders. Use these to calculate available space for laying out controls.
| Function | Signature | Description |
|---|---|---|
form_clientwidth(frm#) | form_clientwidth@# | Width of the client area in pixels |
form_clientheight(frm#) | form_clientheight@# | Height of the client area in pixels |
' Layout a control to fill the entire client area let cw = form_clientwidth(frm#) let ch = form_clientheight(frm#) println "Client area: " + str$(cw) + " x " + str$(ch)
Window State & Style
| Function | Signature | Description |
|---|---|---|
form_windowstate(frm#) | form_windowstate@# | Get state (0=normal, 1=min, 2=max) |
form_windowstate#(frm#, n) | form_windowstate#@#n | Set window state |
form_maximize#(frm#) | form_maximize#@# | Maximize window |
form_minimize#(frm#) | form_minimize#@# | Minimize to taskbar |
form_restore#(frm#) | form_restore#@# | Restore from minimized/maximized |
form_borderstyle(frm#) | form_borderstyle@# | Get border style |
form_borderstyle#(frm#, n) | form_borderstyle#@#n | Set border style (see Numeric Values) |
form_formstyle(frm#) | form_formstyle@# | Get form style (0=normal, 1=stay on top, 2=popup) |
form_formstyle#(frm#, n) | form_formstyle#@#n | Set form style |
form_stayontop(frm#) | form_stayontop@# | Get stay-on-top state (0/1) |
form_stayontop#(frm#, n) | form_stayontop#@#n | Set stay-on-top (0/1) |
form_fullscreen(frm#) | form_fullscreen@# | Get fullscreen state (0/1) |
form_fullscreen#(frm#, n) | form_fullscreen#@#n | Set fullscreen mode (0/1) |
' Create a fixed-size dialog let dlg# = form#("Settings", 400, 300) form_borderstyle#(dlg#, 1) ' Non-resizable form_position#(dlg#, 4) ' Centered ' Create a fullscreen kiosk app let kiosk# = form#("Kiosk", 800, 600) form_fullscreen#(kiosk#, 1)
Appearance
| Function | Signature | Description |
|---|---|---|
form_caption$(frm#) | form_caption$@# | Get form title |
form_caption#(frm#, s$) | form_caption#@#$ | Set form title |
form_fill$(frm#) | form_fill$@# | Get background color |
form_fill#(frm#, color$) | form_fill#@#$ | Set background color |
form_transparency(frm#) | form_transparency@# | Get transparency (0.0–1.0) |
form_transparency#(frm#, value) | form_transparency#@#n | Set transparency (0.0=opaque, 1.0=invisible) |
Color formats accepted by form_fill#:
| Format | Example | Description |
|---|---|---|
| Hex RGB | #RRGGBB | "#FF0000" = red |
| Hex ARGB | #AARRGGBB | "#80FF0000" = semi-transparent red |
| Named | color name | "red", "blue", "white", etc. |
form_caption#(frm#, "My Application v1.0") form_fill#(frm#, "#F0F0F0") ' Light gray background form_transparency#(frm#, 0.1) ' Slightly transparent
Close Behavior
| Function | Signature | Description |
|---|---|---|
form_closeaction(frm#) | form_closeaction@# | Get current close action |
form_closeaction#(frm#, n) | form_closeaction#@#n | Set close action (0=none, 1=hide, 2=free, 3=minimize) |
form_allowclose(frm#) | form_allowclose@# | Get allow-close state (0/1) |
form_allowclose#(frm#, n) | form_allowclose#@#n | Allow or prevent closing (0/1) |
form_modalresult(frm#) | form_modalresult@# | Get modal result |
form_modalresult#(frm#, n) | form_modalresult#@#n | Set modal result (used with showex#/showmodal) |
' Hide instead of destroy when user closes form_closeaction#(frm#, 1) ' Prevent accidental close form_allowclose#(frm#, 0) ' Set a result for dialog patterns form_modalresult#(frm#, 1) ' OK form_close(frm#)
Padding
| Function | Signature | Description |
|---|---|---|
form_padding(frm#) | form_padding@# | Get uniform padding |
form_padding#(frm#, n) | form_padding#@#n | Set uniform padding on all four sides |
form_paddings#(frm#, l, t, r, b) | form_paddings#@#nnnn | Set individual padding (left, top, right, bottom) |
form_padding#(frm#, 10) ' 10px on all sides form_paddings#(frm#, 20, 10, 20, 10) ' 20px left/right, 10px top/bottom
Utility Functions
| Function | Signature | Description |
|---|---|---|
form_tag(frm#) | form_tag@# | Get user-defined integer tag |
form_tag#(frm#, n) | form_tag#@#n | Set user-defined integer tag |
form_active(frm#) | form_active@# | Is the form currently active/focused? (0/1) |
form_bringtofront#(frm#) | form_bringtofront#@# | Bring form to the front of the Z-order |
form_sendtoback#(frm#) | form_sendtoback#@# | Send form behind other windows |
form_setfocus#(frm#) | form_setfocus#@# | Set focus to the form |
form_invalidate#(frm#) | form_invalidate#@# | Force form to repaint |
form_handle(frm#) | form_handle@# | Get the native OS window handle (advanced) |
form_tag is a general-purpose integer you can attach to any form. Useful for identifying forms in shared callback functions.Screen Information
| Function | Signature | Description |
|---|---|---|
form_screenwidth() | form_screenwidth@ | Screen width in pixels |
form_screenheight() | form_screenheight@ | Screen height in pixels |
form_screenscale() | form_screenscale@ | Display scale factor (1.0 = standard, 2.0 = Retina/HiDPI) |
form_screenorientation() | form_screenorientation@ | Screen orientation (0 = portrait, 1 = landscape) |
println "Screen: " + str$(form_screenwidth()) + " x " + str$(form_screenheight()) println "Scale: " + str$(form_screenscale()) println "Orientation: " + str$(form_screenorientation()) ' Size form to half the screen let frm# = form#("Half Screen") form_size#(frm#, form_screenwidth() / 2, form_screenheight() / 2) form_center#(frm#)
Events
Each event has a setter (form_onXXX#(frm#, func$)) and a getter (form_onXXX$(frm#)) to assign or read the callback name. Use form_clearcallbacks#(frm#) to disconnect all callbacks at once.
| Event Setter | Getter | Callback Signature |
|---|---|---|
form_onshow#(frm#, func$) | form_onshow$(frm#) | function name(sender#) |
form_onhide#(frm#, func$) | form_onhide$(frm#) | function name(sender#) |
form_onclose#(frm#, func$) | form_onclose$(frm#) | function name(sender#, action) |
form_onclosequery#(frm#, func$) | form_onclosequery$(frm#) | function name(sender#) → return 1 to allow, 0 to prevent |
form_onactivate#(frm#, func$) | form_onactivate$(frm#) | function name(sender#) |
form_ondeactivate#(frm#, func$) | form_ondeactivate$(frm#) | function name(sender#) |
form_onresize#(frm#, func$) | form_onresize$(frm#) | function name(sender#, width, height) |
form_onkeydown#(frm#, func$) | form_onkeydown$(frm#) | function name(sender#, key, keychar$, shift$) |
form_onkeyup#(frm#, func$) | form_onkeyup$(frm#) | function name(sender#, key, keychar$, shift$) |
form_onpaint#(frm#, func$) | form_onpaint$(frm#) | function name(sender#) |
form_onfocuschanged#(frm#, func$) | form_onfocuschanged$(frm#) | function name(sender#) |
form_clearcallbacks#(frm#) | — | Disconnect all event callbacks |
' Keyboard handler function OnKeyDown(sender#, key, keychar$, shift$) println "Key pressed: " + str$(key) + " char: " + keychar$ if key = 27 then form_close(sender#) ' ESC to close endif endfunction form_onkeydown#(frm#, "OnKeyDown")
' Close query — ask before closing function CanClose(sender#) ' Return 1 to allow, 0 to cancel println "Close requested..." return 1 endfunction form_onclosequery#(frm#, "CanClose")
' Resize handler — update layout dynamically function OnResize(sender#, w, h) form_caption#(sender#, "Size: " + str$(w) + " x " + str$(h)) endfunction form_onresize#(frm#, "OnResize")
Complete Examples
Simple Application Window
' Basic event-driven window let frm# = form#("Hello World", 400, 300) form_position#(frm#, 4) form_fill#(frm#, "#F0F0F0") form_show(frm#) ' Main loop — keeps the application running while form_visible(frm#) = 1 processmessages() end while form_free(frm#)
Event-Driven with Keyboard
function OnKeyDown(sender#, key, keychar$, shift$) if key = 27 then form_close(sender#) endif endfunction function OnClose(sender#, action) println "Goodbye!" return 2 endfunction let frm# = form#("Press ESC to close", 400, 300) form_position#(frm#, 4) form_onkeydown#(frm#, "OnKeyDown") form_onclose#(frm#, "OnClose") form_show(frm#) while form_visible(frm#) = 1 processmessages() end while
Resizable with Constraints
function OnResize(sender#, w, h) form_caption#(sender#, "Size: " + str$(w) + " x " + str$(h)) endfunction let frm# = form#("Resize Me", 600, 400) form_position#(frm#, 4) form_constraints#(frm#, 400, 300, 1200, 800) form_onresize#(frm#, "OnResize") form_show(frm#) while form_visible(frm#) = 1 processmessages() end while
Dialog with Buttons
let dlg# = Pointer#(0) function OnOK(sender#) form_modalresult#(dlg#, 1) form_close(dlg#) endfunction function OnCancel(sender#) form_modalresult#(dlg#, 2) form_close(dlg#) endfunction function OnDialogClose(sender#, result) if result = 1 then println "OK clicked" else println "Cancelled" endif endfunction dlg# = form#("Confirm", 300, 150) form_position#(dlg#, 4) let btnOK# = button#(dlg#, "OK", 50, 100, 80, 30) let btnCancel# = button#(dlg#, "Cancel", 170, 100, 80, 30) button_onclick#(btnOK#, "OnOK") button_onclick#(btnCancel#, "OnCancel") form_showex#(dlg#, "OnDialogClose")
Adaptive Layout
function OnResize(sender#, w, h) local cw, ch cw = form_clientwidth(sender#) ch = form_clientheight(sender#) ' Center a label in the client area label_move#(lbl#, cw / 2 - 50, ch / 2 - 10) endfunction let frm# = form#("Adaptive", 640, 480) let lbl# = label#(frm#, "Centered!", 0, 0) form_onresize#(frm#, "OnResize") form_position#(frm#, 4) form_show(frm#) while form_visible(frm#) = 1 processmessages() end while
Best Practices
| Practice | Why |
|---|---|
Always form_free when done | Releases memory and native OS resources |
Use form_showex# instead of form_showmodal | Works on all platforms including mobile |
Check form_error() after creation | Catches creation failures early |
Set form_position#(frm#, 4) | Centers on screen — better than guessing coordinates |
Use form_constraints# | Prevents forms from becoming too small to use |
Use a while form_visible = 1 main loop | Idiomatic way to keep an event-driven app running |
Initialize pointer variables with Pointer#(0) | Required before assigning in callbacks or conditional code |
Use form_tag to identify forms | Lets shared callbacks distinguish between multiple forms |
Quick Reference
| Function | Signature | Description |
|---|---|---|
form_error / errormsg$ / strerror$ / clearerror | various | Error handling (4) |
form#() / form#(s$) / form#(s$,n,n) | form#@, form#@$, form#@$nn | Create form (3 overloads) |
form_free / form_close | form_free@#, form_close@# | Destroy / close form |
form_show / showmodal / showex# / hide | various | Display control (4) |
form_visible / visible# | form_visible@#, form_visible#@#n | Visibility get/set |
form_left/top/width/height (get/set) | various | Position & size (8) |
form_bounds# / move# / size# / center# | various | Batch position/size (4) |
form_position / position# | form_position@#, form_position#@#n | Position mode |
form_constraints# / min/max width/height | various | Size constraints (9) |
form_clientwidth / clientheight | various | Client area (2) |
form_windowstate / maximize# / minimize# / restore# | various | Window state (5) |
form_borderstyle / formstyle / stayontop / fullscreen | various | Window style (8) |
form_caption$ / caption# / fill$ / fill# / transparency | various | Appearance (6) |
form_closeaction / allowclose / modalresult | various | Close behavior (6) |
form_padding / padding# / paddings# | various | Padding (3) |
form_tag / active / bringtofront# / sendtoback# / setfocus# / invalidate# / handle | various | Utility (8) |
form_screenwidth / screenheight / screenscale / screenorientation | various | Screen info (4) |
form_onshow/onhide/onclose/onclosequery/onactivate/ondeactivate/onresize/onkeydown/onkeyup/onpaint/onfocuschanged | various | Events (set+get) + clearcallbacks (25) |
form_showfullscreenicon (get/set) | various | Fullscreen icon (2) |
105 functions. Part of the Plan9Basic GUI library system.