Rust原生Windows GUI开发库native-windows-gui的使用,轻量级跨平台桌面应用开发解决方案

Rust原生Windows GUI开发库native-windows-gui的使用,轻量级跨平台桌面应用开发解决方案

简介

Native Windows GUI (NWG) 是一个用于在Windows桌面开发原生GUI应用程序的Rust库。它是对WINAPI的轻量级封装,提供了简单、安全且符合Rust风格的接口。

NWG保持简单性,这意味着更小的编译时间、更少的资源使用,以及更少的文档查阅时间,让开发者可以将更多时间用于应用程序开发。

安装

在项目的Cargo.toml中添加:

[dependencies]
native-windows-gui = "1.0.12"
native-windows-derive = "1.0.3"  # 可选。仅在需要派生宏时使用

然后在main.rs或lib.rs中:

extern crate native_windows_gui as nwg;
extern crate native_windows_derive as nwd;  // 可选。仅在需要派生宏时使用

特性支持

  • 几乎所有的WINAPI控件库
  • 菜单和菜单栏
  • 图像和字体资源支持(BMP, ICO, CUR, PNG, GIF, JPG, TIFF, DDS)
  • 本地化支持
  • 工具提示
  • 系统托盘通知
  • 光标处理
  • 完整的剪贴板封装
  • 部分模板支持
  • 动态控件支持
  • 多线程应用程序支持
  • 简单布局配置(FlexboxLayout, GridLayout)
  • 拖放功能
  • 常见对话框(文件对话框、字体对话框、颜色对话框)
  • 可用于外部渲染API的画布
  • 高DPI支持
  • 辅助功能支持
  • 低级系统消息捕获
  • 支持从Linux交叉编译到Windows

性能

在发布模式下,basic示例在磁盘上大小为163kb,内存占用为900kb,启动时间即时。

代码示例

使用native-windows-derive

#![windows_subsystem = "windows"]
/*!
   一个非常简单的应用程序,在消息框中显示您的名字。
   与`basic_d`不同,此示例使用布局来定位窗口中的控件
*/

extern crate native_windows_gui as nwg;
extern crate native_windows_derive as nwd;

use nwd::NwgUi;
use nwg::NativeUi;

#[derive(Default, NwgUi)]
pub struct BasicApp {
    #[nwg_control(size: (300, 115), position: (300, 300), title: "Basic example", flags: "WINDOW|VISIBLE")]
    #[nwg_events( OnWindowClose: [BasicApp::say_goodbye] )]
    window: nwg::Window,

    #[nwg_layout(parent: window, spacing: 1)]
    grid: nwg::GridLayout,

    #[nwg_control(text: "Heisenberg", focus: true)]
    #[nwg_layout_item(layout: grid, row: 0, col: 0)]
    name_edit: nwg::TextInput,

    #[nwg_

1 回复

Rust原生Windows GUI开发库native-windows-gui使用指南

简介

native-windows-gui是一个轻量级的Rust GUI库,专注于为Windows平台提供原生界面开发体验。它封装了Windows API,允许开发者创建原生的Windows桌面应用程序,同时保持了Rust的安全性和性能优势。

主要特点

  • 轻量级,无额外依赖
  • 原生Windows外观和体验
  • 跨平台潜力(虽然名称是Windows,但设计考虑了跨平台)
  • 线程安全的GUI操作
  • 简单易用的API设计

基本使用方法

添加依赖

首先在Cargo.toml中添加依赖:

[dependencies]
native-windows-gui = "1.0"
native-windows-derive = "1.0"

创建简单窗口

use native_windows_gui as nwg;

fn basic_window() {
    nwg::init().expect("Failed to init Native Windows GUI");
    nwg::Window::builder()
        .title("Hello World")
        .size((300, 200))
        .build(&Default::default())
        .expect("Failed to build window");
    
    nwg::dispatch_thread_events();
}

带控件的窗口示例

use native_windows_gui as nwg;
use native_windows_derive::NwgUi;

#[derive(Default, NwgUi)]
pub struct BasicApp {
    #[nwg_control(size: (300, 200), position: (300, 300), title: "Basic example")]
    #[nwg_events( OnWindowClose: [BasicApp::say_goodbye] )]
    window: nwg::Window,

    #[nwg_control(text: "Hello", size: (280, 40), position: (10, 10))]
    #[nwg_events( OnButtonClick: [BasicApp::say_hello] )]
    hello_button: nwg::Button,
}

impl BasicApp {
    fn say_hello(&self) {
        nwg::simple_message("Hello", "Hello Rust GUI World!");
    }
    
    fn say_goodbye(&self) {
        nwg::stop_thread_dispatch();
    }
}

fn main() {
    let app = BasicApp::build_ui(Default::default()).expect("Failed to build UI");
    nwg::dispatch_thread_events();
}

高级功能

菜单栏创建

use native_windows_gui as nwg;

fn build_menu(window: &nwg::Window) {
    let mut menu = nwg::Menu::new();
    let mut file_menu = nwg::Menu::new();
    
    nwg::Menu::builder()
        .parent(&menu)
        .text("File")
        .popup(&file_menu)
        .build()
        .unwrap();
    
    nwg::MenuItem::builder()
        .parent(&file_menu)
        .text("Exit")
        .build()
        .unwrap();
    
    window.set_menu(Some(menu));
}

使用资源文件

use native_windows_gui as nwg;

fn load_ui from_rc() {
    nwg::init().expect("Failed to init Native Windows GUI");
    
    let resources = nwg::Resources::from_file("resources.rc")
        .expect("Failed to load resources");
    
    let mut window = Default::default();
    nwg::Window::builder()
        .resource_id("MAIN_WINDOW")
        .build(&mut window)
        .expect("Failed to build window from resource");
    
    nwg::dispatch_thread_events();
}

完整示例代码

下面是一个结合了窗口、按钮、菜单和事件处理的完整示例:

use native_windows_gui as nwg;
use native_windows_derive::NwgUi;

#[derive(Default, NwgUi)]
pub struct App {
    // 主窗口定义
    #[nwg_control(size: (400, 300), position: (300, 300), title: "我的应用")]
    #[nwg_events( OnWindowClose: [App::exit] )]
    window: nwg::Window,

    // 按钮控件
    #[nwg_control(text: "点击我", size: (120, 40), position: (140, 50))]
    #[nwg_events( OnButtonClick: [App::show_message] )]
    button: nwg::Button,

    // 文本框
    #[nwg_control(text: "在这里输入", size: (300, 25), position: (50, 120))]
    text_input: nwg::TextInput,

    // 菜单栏
    #[nwg_control(parent: window)]
    #[nwg_events( OnMenuItemSelected: [App::menu_handler] )]
    menu: nwg::Menu,

    // 文件菜单
    #[nwg_control(parent: menu, text: "文件")]
    #[nwg_events( OnMenuItemSelected: [App::menu_handler] )]
    file_menu: nwg::Menu,

    // 文件菜单项
    #[nwg_control(parent: file_menu, text: "退出")]
    #[nwg_events( OnMenuItemSelected: [App::exit] )]
    exit_item: nwg::MenuItem,

    // 帮助菜单项
    #[nwg_control(parent: file_menu, text: "关于")]
    #[nwg_events( OnMenuItemSelected: [App::about] )]
    about_item: nwg::MenuItem,
}

impl App {
    fn show_message(&self) {
        let text = self.text_input.text();
        nwg::simple_message("消息", &format!("你输入了: {}", text));
    }

    fn about(&self) {
        nwg::simple_message("关于", "这是一个使用native-windows-gui创建的Rust GUI应用");
    }

    fn exit(&self) {
        nwg::stop_thread_dispatch();
    }

    fn menu_handler(&self, item: &nwg::MenuItem) {
        match item.text().as_str() {
            "退出" => self.exit(),
            "关于" => self.about(),
            _ => {}
        }
    }
}

fn main() {
    // 初始化GUI系统
    nwg::init().expect("Failed to init Native Windows GUI");
    
    // 构建UI
    let _app = App::build_ui(Default::default()).expect("Failed to build UI");
    
    // 启动消息循环
    nwg::dispatch_thread_events();
}

性能优化建议

  1. 对于频繁更新的控件,考虑使用nwg::ControlHandle缓存控件引用
  2. 复杂布局使用nwg::GridLayout代替绝对定位
  3. 大量数据展示考虑使用虚拟列表控件

常见问题解决

Q: 为什么我的窗口不显示? A: 确保调用了nwg::dispatch_thread_events()来启动消息循环

Q: 如何响应窗口关闭事件? A: 使用OnWindowClose事件绑定处理函数,并在其中调用nwg::stop_thread_dispatch()

Q: 控件如何跨线程更新? A: 使用nwg::bind_raw_event_handler注册跨线程事件处理器

总结

native-windows-gui为Rust开发者提供了在Windows平台上构建原生GUI应用的简洁方案。它平衡了原生性能和使用便利性,特别适合需要轻量级、原生外观的中小型桌面应用开发。

回到顶部