winctx/window_loop/
icon_handle.rs

1use std::io;
2
3use windows_sys::Win32::Foundation::TRUE;
4use windows_sys::Win32::UI::WindowsAndMessaging as winuser;
5use windows_sys::Win32::UI::WindowsAndMessaging::{DestroyIcon, HICON};
6
7#[derive(Clone)]
8pub(crate) struct IconHandle {
9    pub(super) hicon: HICON,
10}
11
12impl IconHandle {
13    pub(crate) fn from_buffer(buffer: &[u8], width: u32, height: u32) -> io::Result<Self> {
14        let offset = unsafe {
15            winuser::LookupIconIdFromDirectoryEx(
16                buffer.as_ptr(),
17                TRUE,
18                width as i32,
19                height as i32,
20                winuser::LR_DEFAULTCOLOR,
21            )
22        };
23
24        if offset == 0 {
25            return Err(io::Error::last_os_error());
26        }
27
28        let icon_data = &buffer[offset as usize..];
29
30        let hicon = unsafe {
31            winuser::CreateIconFromResourceEx(
32                icon_data.as_ptr(),
33                icon_data.len() as u32,
34                TRUE,
35                0x30000,
36                width as i32,
37                height as i32,
38                winuser::LR_DEFAULTCOLOR,
39            )
40        };
41
42        if hicon == 0 {
43            return Err(io::Error::last_os_error());
44        }
45
46        Ok(Self { hicon })
47    }
48}
49
50impl Drop for IconHandle {
51    fn drop(&mut self) {
52        // SAFETY: icon handle is owned by this struct.
53        unsafe {
54            DestroyIcon(self.hicon);
55        }
56    }
57}