Native Windows GUI: Helpers

Outside of the controls, the resources, and the layouts NWG also has some utility functions. This section will go over them.

Automatic styling

NWG use a hack to implement visual style in applications without having to use a manifest file (see this) This is a good thing because linking a manifest requires a third party library (such as rust-embed-resource)

If automatic styling is not needed, enable the feature no-styling

Message box

In a GUI application, there's no console to display error messages to the end user. In cases like this, a message box is used.
NWG wraps the winapi message box function with the message function.
use native_windows_gui as nwg;

let p = nwg::MessageParams {
    title: "Hey",
    content: "Cats are cute",
    buttons: nwg::MessageButtons::Ok,
    icons: nwg::MessageIcons::Warning
};

assert!(nwg::message(&p) == nwg::MessageChoice::Ok)
This function might be a little to verbose for most use case, that's why NWG implements three simple interfaces:
pub fn fatal_message<'a>(title: &'a str, content: &'a str) {}
pub fn error_message<'a>(title: &'a str, content: &'a str) {}
pub fn simple_message<'a>(title: &'a str, content: &'a str) {}

Cursor

NWG wraps the system cursor with the GlobalCursor object. Not to be confused with a Cursor object, a cursor resource file (*.cur).

GlobalCursor is hidden behind the cursor feature. Once enabled, it can be used to get/set the mouse position on screen, capture the cursor outside of the application, detect a dragging gesture, and set the image of the cursor globally.

Lastly, the GlobalCursor object do not need to be instanced. It must be used as it is:
use native_windows_gui as nwg;
let (x,y) = nwg::GlobalCursor::position();

Clipboard

NWG also wraps the system clipboard in order to write or read data from it. The clipboard is a way to copy arbritary data from within an application or even between two different applications.

Clipboard is hidden behind the clipboard feature.

Writing/Reading text

Because reading or writing text will probably be the most used feature, NWG includes helpers functions that handles the unsafy bits. One thing to note is that Windows clipboard functions always take a control parameter. This can be any HWND based controls (ex: Window, Button, etc).

use native_windows_gui as nwg;

fn clipboard_text(window: &nwg::Window) {
    nwg::Clipboard::set_data_text(window, "Hello!");

    let text = nwg::Clipboard::data_text(window);
    assert!(text.is_some());
    assert!(&text.unwrap() == &"Hello!");
}

Handling custom data

It's possible to pass data structure around using the low level clipboard functions. Note that those function are unsafe because there is no way to validate the data.

When using the low level functions, the clipboard must be manually opened and then closed. Also, when setting data, it's up to the developer to empty whatever content was in the clipboard. Failure to do so will result in unknown errors.
use native_windows_gui as nwg;

#[repr(C)]
#[derive(Clone, Copy)]
struct Hello {
    foo: usize,
    bar: [u16; 3]
}

fn write_custom_data(window: &nwg::Window) {
    let data = Hello {
        foo: 6529,
        bar: [0, 100, 20]
    };

    nwg::Clipboard::open(window);
    nwg::Clipboard::empty();
    unsafe {
        nwg::Clipboard::set_data(
            nwg::ClipboardFormat::Global("Hello"),
            &data as *const Hello,
            1
        );
    }

    nwg::Clipboard::close();
}
    
fn read_custom_data(window: &nwg::Window) -> Option<Hello> {
    unsafe {
        nwg::Clipboard::open(window);
        let data = nwg::Clipboard::data(nwg::ClipboardFormat::Global("Hello"));
        nwg::Clipboard::close();
        data
    }
}

fn read_custom_data_handle(window: &nwg::Window) -> Option<Hello> {
    unsafe {
        nwg::Clipboard::open(window);
        let handle = nwg::Clipboard::data_handle(nwg::ClipboardFormat::Global("Hello"));
        let data = match handle {
            Some(h) => {
                let data_ptr: *const Hello = h.cast();
                let data = *data_ptr;
                h.release();
                Some(data)
            },
            None => None
        };

        nwg::Clipboard::close();
        data
    }
}