我正在用铁 rust 和Solidjs在Tauri做一个windows switch .

我正在使用winapi与Windows交互.

目前,我有:

  1. <WINDOW_TITLE(字符串)的HashMap,HWND>
  2. 我将窗口标题发送到前端
  3. 当被点击时,它会正确地切换窗口.

我想在标题旁边显示应用程序图标,这样它就更容易识别.

这是我的方法:

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张,但什么也没有显示.但是,当我try 在其位置记录任何字符串时,它会正确地记录.

推荐答案

以下是如何将HICON转换为PNG图标的base64表示形式:

use base64::{engine::general_purpose, Engine as _};
use image::RgbaImage;
use std::{mem::{self, MaybeUninit},ptr::addr_of_mut};
use windows::Win32::{Foundation::HWND, Graphics::Gdi::{DeleteObject, GetDC, GetDIBits, GetObjectW, ReleaseDC, BITMAP, BITMAPINFOHEADER, BI_RGB,DIB_RGB_COLORS, HDC}, UI::WindowsAndMessaging::{GetIconInfo, HICON}};

unsafe fn icon_to_rgba_image(icon: HICON) -> String {
    let bitmap_size = i32::try_from(mem::size_of::<BITMAP>()).unwrap();
    let biheader_size = u32::try_from(mem::size_of::<BITMAPINFOHEADER>()).unwrap();

    let mut info = MaybeUninit::uninit();
    GetIconInfo(icon, info.as_mut_ptr()).unwrap();
    let info = info.assume_init_ref();
    DeleteObject(info.hbmMask).unwrap();

    let mut bitmap: MaybeUninit<BITMAP> = MaybeUninit::uninit();
    let result = GetObjectW(
        info.hbmColor,
        bitmap_size,
        Some(bitmap.as_mut_ptr().cast()),
    );
    assert!(result == bitmap_size);
    let bitmap = bitmap.assume_init_ref();

    let width = u32::try_from(bitmap.bmWidth).unwrap();
    let height = u32::try_from(bitmap.bmHeight).unwrap();
    let w = usize::try_from(bitmap.bmWidth).unwrap();
    let h = usize::try_from(bitmap.bmHeight).unwrap();

    let buf_size = w
        .checked_mul(h)
        .and_then(|size| size.checked_mul(4))
        .unwrap();
    let mut buf: Vec<u8> = Vec::with_capacity(buf_size);

    let dc = GetDC(HWND(0));
    assert!(dc != HDC(0));

    let mut bitmap_info = BITMAPINFOHEADER {
        biSize: biheader_size,
        biWidth: bitmap.bmWidth,
        biHeight: -bitmap.bmHeight,
        biPlanes: 1,
        biBitCount: 32,
        biCompression: BI_RGB,
        biSizeImage: 0,
        biXPelsPerMeter: 0,
        biYPelsPerMeter: 0,
        biClrUsed: 0,
        biClrImportant: 0,
    };
    let result = GetDIBits(
        dc,
        info.hbmColor,
        0,
        height,
        Some(buf.as_mut_ptr().cast()),
        addr_of_mut!(bitmap_info).cast(),
        DIB_RGB_COLORS,
    );
    buf.set_len(buf.capacity());

    let result = ReleaseDC(HWND(0), dc);
    assert!(result == 1);
    DeleteObject(info.hbmColor).unwrap();

    for chunk in buf.chunks_exact_mut(4) {
        let [b, _, r, _] = chunk else { unreachable!() };
        mem::swap(b, r);
    }

    let img = RgbaImage::from_vec(width, height, buf).unwrap();

    let mut data: Vec<u8> = Vec::new();
    img.write_to(&mut Cursor::new(&mut data), image::ImageOutputFormat::Png)?;

    general_purpose::STANDARD.encode(&data);
}

=

所以Tauri是建立在TAO的基础上的,这是winit的Forking ,他们为那里的每个平台实现窗口管理.

具体来说是windows/window.rs个,所以在您的情况下,我会克隆TAO存储库并在其中添加所需的更改,然后克隆patch个依赖项以使其指向您的TAO版本.

现在,以下是与TAO implements hicon相关的类:

let class = WNDCLASSEXW {
    cbSize: mem::size_of::<WNDCLASSEXW>() as u32,
    style: CS_HREDRAW | CS_VREDRAW | CS_OWNDC,
    lpfnWndProc: Some(window_proc),
    cbClsExtra: 0,
    cbWndExtra: 0,
    hInstance: HINSTANCE(GetModuleHandleW(PCWSTR::null()).unwrap_or_default().0),
    hIcon: HICON::default(),
    hCursor: HCURSOR::default(), // must be null in order for cursor state to work properly
    hbrBackground: HBRUSH::default(),
    lpszMenuName: PCWSTR::null(),
    lpszClassName: PCWSTR::from_raw(class_name.as_ptr()),
    hIconSm: HICON::default(),
  };

哦,值得一提的是,Tauri使用的是windows箱,而不是winapi箱.它的下载量较少,但我认为微软的支持更好.从本质上讲,这与apple-sys为Mac所做的非常相似.

正如乔纳森·波特所指出的,你需要用GetIconInfo来获取他的信息:

pub struct ICONINFO {
    pub fIcon: BOOL,
    pub xHotspot: u32,
    pub yHotspot: u32,
    pub hbmMask: HBITMAP,
    pub hbmColor: HBITMAP,
}

所以回答你最初的问题,不,你不能打印hicon,因为它只是a handle:

pub type HICON = isize;

附注:这是如何在Windows上TAO check visibility的一个窗口.

附注:Same Place有~7 ways个选项来获取HWND和其他格式的Windows硬件ID.

Javascript相关问答推荐

react 路由加载程序行为

vanillajs-datepicker未设置输入值,日期单击时未触发更改事件

具有相同参数的JS类

微软Edge编辑和重新发送未显示""

如何在angular中从JSON值添加动态路由保护?

在我的html表单中的用户输入没有被传送到我的google表单中

在react JS中映射数组对象的嵌套数据

如果Arrow函数返回函数,而不是为useEffect返回NULL,则会出现错误

Reaction Native中的范围滑块

搜索功能不是在分页的每一页上进行搜索

是否可以在Photoshop CC中zoom 路径项?

如何在FastAPI中为通过file:/URL加载的本地HTML文件启用CORS?

Docent.cloneNode(TRUE)不克隆用户输入

Chrome上的印度时区名S有问题吗?

Plotly.js栏为x轴栏添加辅助文本

将以前缓存的 Select 器与querySelector()一起使用

如何调整下拉内容,使其不与其他元素重叠?

我想为我的Reaction项目在画布上加载图像/视频,图像正在工作,但视频没有

使用JAVASCRIPT-使用If和Else If多次判断条件-使用JAVASRIPT对象及其属性

如何在不获取其子元素的文本内容的情况下获取元素的文本内容?