You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Tauri窗口切换器:获取HICON的方法是否正确?如何输出日志?

问题

我正在使用Rust和SolidJS开发一款基于Tauri的窗口切换器,通过winapi与Windows系统交互。目前已完成以下功能:

  • 构建存储<窗口标题(string), HWND>的HashMap;
  • 将窗口标题发送至前端;
  • 点击标题可正确切换目标窗口。

我希望在窗口标题旁显示应用图标以提升识别度,为此修改代码将获取到的HICON与HWND一同存储,代码如下:

unsafe extern "system" fn enum_windows_proc(hwnd: HWND, lparam: LPARAM) -> BOOL {
    let title_length = GetWindowTextLengthW(hwnd);
    if title_length > 0 {
        let mut buffer: Vec<u16> = vec![0; (title_length + 1) as usize]; // +1 for null terminator
        GetWindowTextW(hwnd, buffer.as_mut_ptr(), buffer.len() as i32);

        if IsWindowVisible(hwnd) != 0 {
            let window_title = OsString::from_wide(&buffer).to_string_lossy().to_string();
            let title_map = &mut *(lparam as *mut HashMap<String, (HWND, HICON)>);
            let app_icon = get_app_icon(hwnd);

            if app_icon.is_some() {
                title_map.insert(window_title, (hwnd, app_icon.unwrap()));
            }
        }
    }

    1
}

fn get_app_icon(hwnd: HWND) -> Option<HICON> {
    let icon_handle: usize = unsafe { GetClassLongPtrW(hwnd, GCLP_HICON as i32) };
    if icon_handle == 0 {
        None
    } else {
        Some(icon_handle as HICON)
    }
}

请问我获取HICON的方法是否正确?另外,尝试打印icon_handle无输出,替换为字符串则正常,该如何正确输出HICON相关日志?

回答

关于HICON获取方法的正确性

你当前的方法有局限性:

  • GetClassLongPtrW(hwnd, GCLP_HICON)只能获取窗口类注册时指定的32x32大图标,如果窗口没设置类大图标、用的是16x16小图标,或者程序动态修改了窗口图标,这个调用会返回0。
  • 更可靠的做法是优先通过WM_GETICON消息获取窗口当前显示的图标,失败后再 fallback 到类图标:
use winapi::{shared::minwindef::*, um::winuser::*};

fn get_app_icon(hwnd: HWND) -> Option<HICON> {
    unsafe {
        // 先拿窗口当前的大图标
        let mut icon = SendMessageW(hwnd, WM_GETICON, ICON_BIG as WPARAM, 0);
        if icon == 0 {
            // 大图标不存在就拿小图标
            icon = SendMessageW(hwnd, WM_GETICON, ICON_SMALL as WPARAM, 0);
            if icon == 0 {
                // 再尝试类大图标
                icon = GetClassLongPtrW(hwnd, GCLP_HICON as i32) as HICON;
                if icon == 0 {
                    // 最后尝试类小图标
                    icon = GetClassLongPtrW(hwnd, GCLP_HICONSM as i32) as HICON;
                }
            }
        }
        icon.ne(&0).then_some(icon)
    }
}

关于HICON的日志输出问题

HICON本质是内存指针,Rust默认没有为它实现Display/Debug trait,直接打印会无输出。你可以把它转换成usize类型,打印其内存地址:

// 在get_app_icon中添加日志
fn get_app_icon(hwnd: HWND) -> Option<HICON> {
    unsafe {
        let icon_handle = GetClassLongPtrW(hwnd, GCLP_HICON as i32);
        // 转成usize后以十六进制打印
        println!("Icon handle: 0x{:X}", icon_handle as usize);
        if icon_handle == 0 {
            None
        } else {
            Some(icon_handle as HICON)
        }
    }
}

如果需要关联窗口信息排查问题,还可以结合窗口标题打印:

// 在enum_windows_proc中添加
println!("Window: '{}' - Icon handle: {:?}", window_title, app_icon.map(|icon| icon as usize));

内容的提问来源于stack exchange,提问作者Saverio

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 19:03:26