Native Windows GUI: Resources

Resources are non-ui components that are usually used by GUI controls. This includes images, fonts, cursors, and dialogs.

Most resource can be loaded from file, memory, or from embed resources.

This section will go over images, fonts, and cursors. The next section covers the dialog.

Images & Icons

Out of the box, winapi only supports bitmap (.bmp) and icons (.ico). Bitmap and icons are used by many controls, and some meta resouces like ImageList. Use a ImageFrame control to display icons and bitmap in a Window.

By setting the strict builder parameter to false, NWG will load a default windows resource if the source file cannot be found (instead of returning an error).
use native_windows_gui as nwg;

fn load_bitmap() -> nwg::Bitmap {
    let mut bitmap = nwg::Bitmap::default();

    nwg::Bitmap::builder()
        .source_file(Some("Hello.bmp"))
        .strict(true)
        .build(&mut bitmap);

    bitmap
}


Windows Imaging Component (WIC)

Now, because we're no longer in 3000 BC, you probably want to support more image types. Png and jpeg specifically. Thanksfully, NWG seamlessly wraps the windows imaging component. This adds the following formats: .bmp(v5, with transparency), gif, ico, jpeg, png, tiff, vnd, and dds.

To enable the WIC, just use the image-decoder feature. When this is enabled, all the above formats will be supported by Bitmap.

The image decoder feature also enables the ImageDecoder resource. Which allows you load image files manually and read the pixel data. Ability to load images from streams (ex the internet) will probably be added in the future (after the 1.0 release).

See the image decoder example

Helper functions

The builder api can be cumbersome, that's why Native Windows GUI also includes helper functions to load resources in a single line.

The helper functions all have a similar signature: Bitmap::from_*, Icon::from_*.

You can also check out the docs.rs documentation.

use native_windows_gui as nwg;

static EMBEDDED_BITMAP: &[u8] = include_bytes!("cat.jpg");

fn load_resources() -> Result<(), nwg::NwgError> {
    let bitmap1 = nwg::Bitmap::from_file("hello.png", true)?;
    let bitmap2 = nwg::Bitmap::from_bin(EMBEDDED_BITMAP)?;

    let icon1 = nwg::Icon::from_file("hey.ico", true)?;
}

fn load_image_from_embedded() -> [Bitmap; 3] {
    let embed = nwg::EmbedResource::load(None).unwrap();

    /*
        // myapp.rc

        BALL BITMAP "ball.bmp"
        HELLO IMAGE "test.png"
        NICE IMAGE "test.jpg"
    */

    [
        nwg::Bitmap::from_embed(&embed, None, Some("BALL")),
        nwg::Bitmap::from_embed(&embed, None, Some("HELLO")),
        nwg::Bitmap::from_embed(&embed, None, Some("NICE")),
    ]
} 

Fonts

Native-windows-gui supports .ttf and .otf font files. All controls that display text have a set_font and get_font method to set their font.

NWG has access to all the fonts families installed on the system. It's also possible to add new fonts temporarily using the Font::add_font / Font::remove_font or Font::add_memory_font / Font::remove_memory_font.Those methods works globally.
use native_windows_gui as nwg;

fn main() {
    nwg::Font::add_font("./MyFont.ttf");
    // Application runtime
    nwg::Font::remove_font("./MyFont.ttf");
}


Once the font families are loaded, a `Font` resource must be created. Just like the other resources, this is done using the Font builder.
use native_windows_gui as nwg;

fn build_font() -> nwg::Font {
    let mut font = nwg::Font::default();

    nwg::Font::builder()
        .size(16)
        .family("Arial")
        .weight(1000)
        .build(&mut font);

    font
}

fn set_font(button: &nwg::Button, font: &nwg::Font) {
    button.set_font(Some(font));
}


Cursors

Cursors are icons that can be used in place of the default Windows mouse cursor. Cursors can be custom, loaded from .cur files, or they can be loaded from the system default cursors (using OemCursor).

Currently cursors can only be set globally using GlobalCursor::set (behind the cursor feature). Furthermore, this method must be called everytime the cursor moves in a control because the default cursor is replaced automatically by Windows on mouse events. This behavior will probably change in the future.
use native_windows_gui as nwg;

fn set_cursor(window: &nwg::Window, cursor: nwg::Cursor) {
    nwg::full_bind_event_handler(&window.handle, move |event, event_data, handle| {
        match event {
            nwg::Event::OnMousePress(_) | nwg::Event::OnMouseMove => {
                nwg::GlobalCursor::set(&cursor)
            },
            _ => {}
        }
    });
}