Kal*_*son 1 windows winapi rust rust-cargo
struct在 Rust 桌面应用程序中,总是使用某些版本的窗口,例如WNDCLASSW. WNDCLASSW定义后,可以通过成员添加类图标。下面的代码摘录演示了如何包含存储在文件中的图标。structhIconIcon.ico
...
let hicon: HICON = LoadImageW(
0 as HINSTANCE,
wide_null("Icon.ico").as_ptr(),
IMAGE_ICON, 0, 0, LR_LOADFROMFILE
) as HICON;
let hinstance = GetModuleHandleW(null_mut());
let mut wc: WNDCLASSW = std::mem::zeroed();
wc.lpfnWndProc = Some(window_proc);
wc. hInstance = hinstance;
wc.hIcon = hicon;
wc.lpszClassName = name.as_ptr();
...
Run Code Online (Sandbox Code Playgroud)
图标文件在程序执行期间加载,并且必须与该exe文件保存在同一文件夹中。如果图标文件丢失,LoadImageW()则返回NULL句柄。设置hIcon为NULL有效并导致使用标准系统图标。
虽然此方法会生成所需的图标,但图标文件是在执行期间加载的,并且必须与文件一起传递exe。这不是一个可接受的解决方案;图标应链接到exe文件并在其中传递。
如何将图标链接到 Rust Windows 应用程序并在那里使用它?
我知道这个解决方案,但它在编译过程中会生成数千行错误和警告,并且必须被视为过时的。此解决方案有效,但它仅添加Windows 中显示的exe 图标File Explorer,而类图标(在任务栏中)未更改。可以在互联网上找到exe图标的其他几个解决方案,但这不是我正在寻找的。
在 Windows 上将资源嵌入到可执行映像中的标准过程是创建一个资源文件(.rc),让资源编译器将其转换为其二进制表示形式,然后将其传递给链接器。
由于与 Cargo 中的链接器交互有点乏味,因此使用现有的板条箱来处理这个问题要容易一些。正如您所发现的,有winres(它似乎有点过时),所以我将在这里使用embed-resource。
如果您想一起玩,请从创建一个新的二进制箱开始
cargo new --bin embed_icon
Run Code Online (Sandbox Code Playgroud)
接下来,将您选择的图标复制到包的根目录中(我使用从此处下载的“rust_lang_logo.ico” )并在同一位置创建资源脚本(embed_icon.rc):
1 ICON "rust_lang_logo.ico"
Run Code Online (Sandbox Code Playgroud)
这一切所做的就是告诉资源编译器它应该寻找一个名为 的图标"rust_lang_logo.ico",并在生成其二进制输出时为其分配一个 ID 1。
当然我们还需要一个 Cargo.toml:
[package]
name = "embed_icon"
version = "0.0.0"
edition = "2021"
[dependencies.windows]
version = "0.43.0"
features = [
"Win32_Foundation",
"Win32_UI_WindowsAndMessaging",
"Win32_System_LibraryLoader",
]
[build-dependencies]
embed-resource = "1.8"
Run Code Online (Sandbox Code Playgroud)
windows这声明了我们将使用的所需功能,并将嵌入资源作为构建依赖项导入。剩下的是 src/main.rs
use windows::{
core::{Result, PCWSTR},
Win32::{
System::LibraryLoader::GetModuleHandleW,
UI::WindowsAndMessaging::{LoadImageW, IMAGE_ICON, LR_DEFAULTSIZE},
},
};
fn main() -> Result<()> {
let _icon = unsafe {
LoadImageW(
GetModuleHandleW(None)?,
PCWSTR(1 as _), // Value must match the `nameID` in the .rc script
IMAGE_ICON,
0,
0,
LR_DEFAULTSIZE,
)
}?;
Ok(())
}
Run Code Online (Sandbox Code Playgroud)
除了尝试加载我们刚刚嵌入到二进制文件中的图标之外,这并没有做太多事情。后来cargo run,我们有...
错误:错误 { 代码:HRESULT(0x80070714),消息:“指定的图像文件不包含资源部分。” }
以及文件资源管理器中如下所示的二进制文件:
最后一步是实际运行 embed-resource 并将图标链接到可执行映像中。需要构建脚本来执行此操作。要添加一个,请在 crate 的根目录中创建一个名为“build.rs”的文件,其中包含以下内容:
fn main() {
embed_resource::compile("embed_icon.rc");
}
Run Code Online (Sandbox Code Playgroud)
这巧妙地将所有内容结合在一起。现在运行可执行文件已成功,并且当在文件资源管理器中显示时,二进制文件有一个与之关联的漂亮图标:
注意:上述解决方案使用windows crate,其设计是为了方便和更好的安全性。如果您使用winapi或windows-sys crate,核心原理仍然是相同的。不过,main.rs 中的代码必须进行调整。
| 归档时间: |
|
| 查看次数: |
872 次 |
| 最近记录: |