Custom modules
Using custom modules is the most powerful way to create custom controls. It is also pretty unsafe.
Every control in the standard control library is implemented using this method.
For a concrete example, see the
custom example or the api of the
nwg::custom
module.
In order to create new control using the low level module, good knowledge of the Windows API is required.
Also, in order to make process easier, the usage of
winapi-rs
is highly recommended.
Those custom control are defined by defining 2 structures, a
template and a
control and then by
implementing the
ControlT
and the
Control
trait to these structures.
Once this is done, the template and the control can be used like any other controls. Ex: using
pack_control
.
The template role is to create the low level object (ex:
HWND
), wrap in in a Boxed Control and return the result.
The template also returns what kind of events the control will support. If a user try to bind a callback to an unsupported event,
an error will be raised.
Because NWG event are handled on the UI,
the only way for a custom control created this way to system handle events is
to do it directly in the WINPROC function.
Because custom events are not yet implemented, it is impossible to create events for those controls.
Still, basics events such as
Event::KeyUp
can be hooked to by the template. To allow the UI to see every message
received by the window, allow the
Event::Raw
event in the template.
Here is a list of event that NWG can listen to for any HWND based control:
Destroyed, KeyDown, KeyUp, Char, Closed, MouseUp, MouseDown, Moved, Resized, Paint, Raw
/**
Structures implementing this trait can be used by a Ui to build a Control
*/
pub trait ControlT<ID: Clone+Hash> {
/**
Should return the TypeId of the generated control. For example a `WindowT` struct returns the TypeId of a `Window` struct.
*/
fn type_id(&self) -> TypeId;
/**
Should instance the control and return it as a Box<Control>. If an error is raised, it will be returned by `ui.commit`.
*/
fn build(&self, ui: &Ui<ID>) -> Result<Box<Control>, Error>;
/**
Should return the events supported by the control.
*/
fn events(&self) -> Vec<Event> { Vec::new() }
}
The role of a control is to wrap a low level handle (such as a
HWND
). The trait requires a
free
to free the resources during the build phase of the template and a
handle
to return the underlying handle of the control.
/**
Structures implementing this trait are controls that can be stored in a Ui
*/
pub trait Control {
/**
Should return the underlying handle to the object
*/
fn handle(&self) -> AnyHandle;
/**
Should return the type of the control. For custom controls, the return value should be `Undefined` (the default).
*/
fn control_type(&self) -> ControlType { ControlType::Undefined }
/**
If specified, should free any ressource allocated in the template `build` function. This includes functions like `DestroyWindow`.
*/
fn free(&mut self) {}
}