Native Windows GUI: Controls
Controls are UI elements that can be interacted with. Native windows GUI wraps over 25 different controls in a safe rust-friendly interface.
This section explains the basics of using NWG controls.
To learn how to use controls with
native-windows-derive
see
the derive section
Control builder
Controls are created using a
builder API. On each control type, the method
builder
can be
called in order to instantiate a builder object. Builder names use the following format:
[ControlName]Builder
. Ex: (
ButtonBuilder
).
Each control documentation enumerates the properties accepted by the builder.
use native_windows_gui as nwg;
fn build_button(button: &mut nwg::Button, window: &nwg::Window, font: &nwg::Font) {
nwg::Button::builder()
.text("Hello")
.flags(nwg::ButtonFlags::VISIBLE | nwg::ButtonFlags::CHECK)
.font(Some(font))
.parent(window)
.build(button);
}
Control methods
NWG wraps almost every controls functionalities behind object methods. Fonctionnalities usually come in get/set pair.
The syntax used is
[property]()
for getters and
set_[property](value)
for setters. Example:
fn test(button: &Button) {
button.visible();
button.set_visible(true);
}
Methods of NWG never takes a mutable borrow. This is because most methods maps directy to a single winapi call.
And because the application data will almost certaintly be behind a
Rc
, having to put each control behind a refcell would be HELL.
Every NWG controls implements the
Default
trait. A control created from this is marked as
uninitialized.
Calling the methods of an uninitialized control will cause a
panic.
Window / Container controls
Most controls in NWG cannot hold children. Those that can are called "container controls". This includes
Window,
Tab Container,
and
Tab. TabContainer should only contains tab controls.
Container controls can also use
layouts. More on that in
the layout section
The window control is be the base of any GUI application. It represents a top level system window. Every NWG application will have a window.
This also includes system tray applications. In this case, the window should be a
MessageWindow
, an invisible window that only dispatch messages.
Window controls are highly customizable. System decorated window (aka normal window), popup window, and transparent window can be created by selecting the right
WindowFlags
.
nwg::Window::builder()
.flags(nwg::WindowFlags::WINDOW | nwg::WindowFlags::VISIBLE)
.size((300, 115))
.position((300, 300))
.title("Basic example")
.build(&mut data.window)?;
Controls hierarchy
All non-window control require a parent. If no parent is defined when building a new control, the build function will return a
NwgError::ControlCreationError
.
Control events
Controls can raise
Events
when interacted with. The events that can be raised by a control are
in the their documentation.
All controls have specific events (ex:
OnButtonClick
) and generic events that are shared (ex:
OnPaint
).
More on this in the next section
Implementation
To keep compile time low, most controls are feature-gated.
Every control is implemented as a wrapper over a low level window handle. As such,
most* of them only take the size of a pointer.
Some built-in controls lacks critical feature on their own. To fix this, nwg extends those controls with
raw events handlers.
Also, controls that support custom collections (ex: ListBox and ComboBox) also uses Rust collections internally to store the rust data.
Freeing
Controls implement
Drop
and are freed when they go out of scope.