Native Windows GUI: Low level events
Winapi implements a bazillion of events and applications are free to define their own. There's no way for NWG to
catch
wrap them all. As a solution, NWG lets you use
bind_raw_event_handler
to hook the system event queue without parsing the parameters.
Using raw events handlers
fn log_resize(window: &Window) {
use winapi::um::winuser::WM_SIZE;
use winapi::shared::minwindef::{HIWORD, LOWORD};
const MY_UNIQUE_RAW_HANDLER_ID: usize = 45776;
bind_raw_event_handler(&window.handle, MY_UNIQUE_RAW_HANDLER_ID, |_hwnd, msg, _w, l| {
match msg {
WM_SIZE => {
println!("w: {}, h: {}", LOWORD(l as u32), HIWORD(l as u32));
},
_ => {}
}
None
});
}
Raw event handlers work in similar way as default events handers. It works by adding a callback to a window control. This callback then gets called
everytime the control receives an event.
The parameters:
handle
is the handle of a window control
id
is an id identifying the handler. Without a different id, binding the same handler a second time on the same control will replace the first handler!
f
is the callback that will be called.
The return value:
RawEventHandler
works the same way as the normal
event handler. This object is an opaque handle over the event hook
and ignoring this value means that the callback and all its data will be leaked.
The callback:
The callback takes 4 arguments:
HWND, MSG, WPARAM, and LPARAM
which are the same value passed to the window procedures.
This guide assumes you already know how to use them.
The callback also lets you pass a value back to the OS. If
None
is returned, the internal handler will use
DefSubclassProc
and
execute the next event handler on the control. If a
Some
value is returned, this value will be returned by the internal handler and the following
handlers
will not be called.
Events handlers are always executed from last added to first added. Ie, user hooks will be executed before any NWG hooks.
Freeing raw handlers
To free a raw event handler call:
nwg::unbind_raw_event_handler(&handler)
Calling unbind twice or trying to unbind an handler after destroying its parent will cause the function to panic.
Checking if a raw handler is bound
If you are not sure if a raw event handler is bound and you don't want your application to panic, use the
nwg::has_raw_handler(&handle, handler_id)
method.
Example:
let handler = bind_raw_event_handler(&handle, 9001, move |_hwnd, _msg, _w, _l| {
None
});
assert!(has_raw_handler(&handle, 9001) == true);