ui.hphp
Native desktop windows with buttons, inputs, lists, sliders, menus, timers
and dialogs — a friendly HolyPHP API over a hand-written Win32 layer in the runtime.
No external dependencies: hphp build links everything into one ~315 KB exe.
Hello GUI
import "ui.hphp";
$app = new App("My App", 640, 420);
$btn = $app->button("Click me", 16, 40);
$name = $app->input("world", 16, 80);
$btn->onClick = function() use ($app, $name) {
$app->msg("Hello, " . $name->value() . "!");
};
$app->run(); // real desktop event loop
App
| Method | Returns | Meaning |
|---|---|---|
title($t) / size($w,$h) / pos($x,$y) | App | window geometry (chainable) |
run() | void | blocking event loop |
tick($ms = 15) | void | pump events once (own loop) |
alive() | bool | window still open? |
close() | void | close the window |
every($ms, $fn) | void | timer — runs $fn periodically |
onClose($fn) | void | runs when the window closes |
Widgets — created through the App
| Factory | Widget | Extras |
|---|---|---|
$app->button($text, $x, $y, $w = 120, $h = 30) | Button | $w->onClick |
$app->label($text, $x, $y, ...) | Label | — |
$app->input($text, $x, $y, ...) | Input | value() / setValue() / $w->onChange |
$app->checkbox($text, $x, $y, ...) | Checkbox | checked() / setChecked() |
$app->listBox($x, $y, $w, $h) | ListBox | add/clear/remove/selected/select/selectedText |
$app->comboBox($x, $y, $w, $h) | ComboBox | same API as ListBox |
$app->progress($x, $y, $w) | ProgressBar | set(pct) / get() |
$app->slider($x, $y, $w) | Slider | set(pos) / get() / $w->onChange(int $v) |
$app->group($text, $x, $y, $w, $h) | Group | framed container |
$app->panel($x, $y, $w, $h) | Panel | flat container |
All widgets inherit from UIObject: chainable
text(), getText(), show(), enable(),
move(), focus(), font($size, $bold), bg($rgb).
Slider events fire live
$slider = $app->slider(430, 70, 180);
$sliderLbl = $app->label("slider: 50", 430, 104);
$slider->onChange = function(int $v) use ($sliderLbl) {
$sliderLbl->text("slider: " . $v); // fires while dragging
};
Menus
$file = $app->menu("&File");
$file->item("&Open\tCtrl+O", function() use ($app) {
$f = $app->openFile("Text|*.txt|All|*.*");
if ($f != "") { $app->msg("picked " . $f); }
});
$file->separator();
$file->item("E&xit", function() use ($app) { $app->close(); });
Dialogs & system
Timers & counters
$frame = 0;
$app->every(100, function() use (&$frame, $app) { // by-ref capture!
$frame = $frame + 1;
if ($frame % 10 == 0) { $app->title("frames: " . $frame); }
});
Full tour
examples/ui_demo.hphp exercises every feature — buttons, inputs, checkbox
gating, list box, combo, progress + slider, groups, menus, timers and dialogs:
hphp build examples/ui_demo.hphp -o ui_demo.exe
./ui_demo.exe
How it works
The Win32 layer lives in the runtime (hphp_ui.c): a handle table, a window
proc that routes events to HolyPHP closures, and guarded callback invocation — an exception
inside a handler prints and keeps the app alive instead of unwinding through C. Callbacks run
on the GUI thread; long work belongs in a timer.
$w->onClick / $w->onChange are plain
closure properties — assign any closure, capture anything with use.