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_
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();
}
性能优化建议
- 对于频繁更新的控件,考虑使用
nwg::ControlHandle
缓存控件引用 - 复杂布局使用
nwg::GridLayout
代替绝对定位 - 大量数据展示考虑使用虚拟列表控件
常见问题解决
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应用的简洁方案。它平衡了原生性能和使用便利性,特别适合需要轻量级、原生外观的中小型桌面应用开发。