use std::time::Duration;
use windows_sys::Win32::Foundation::HWND;
use windows_sys::Win32::UI::Shell::{
NIF_INFO, NIF_TIP, NIIF_ERROR, NIIF_INFO, NIIF_NOSOUND, NIIF_WARNING, NIM_ADD, NIM_DELETE,
NIM_MODIFY, NOTIFYICONDATAW, Shell_NotifyIconW,
};
const NOTIFICATION_ICON_ID: u32 = 100;
pub enum BalloonKind {
Info,
Warning,
Error,
}
fn fill_wide<const N: usize>(s: &str) -> [u16; N] {
let mut buf = [0u16; N];
let chars: Vec<u16> = s.encode_utf16().collect();
let len = chars.len().min(N.saturating_sub(1));
buf[..len].copy_from_slice(&chars[..len]);
buf
}
pub fn show_balloon(hwnd: HWND, title: &str, body: &str, kind: BalloonKind) {
let tip_w: [u16; 128] = fill_wide("FreeCycle");
let title_w: [u16; 64] = fill_wide(title);
let body_w: [u16; 256] = fill_wide(body);
let info_flags = match kind {
BalloonKind::Info => NIIF_INFO | NIIF_NOSOUND,
BalloonKind::Warning => NIIF_WARNING | NIIF_NOSOUND,
BalloonKind::Error => NIIF_ERROR,
};
unsafe {
let mut data: NOTIFYICONDATAW = std::mem::zeroed();
data.cbSize = std::mem::size_of::<NOTIFYICONDATAW>() as u32;
data.hWnd = hwnd;
data.uID = NOTIFICATION_ICON_ID;
data.uFlags = NIF_TIP;
data.szTip = tip_w;
Shell_NotifyIconW(NIM_ADD, &data);
data.uFlags = NIF_INFO;
data.szInfoTitle = title_w;
data.szInfo = body_w;
data.dwInfoFlags = info_flags;
Shell_NotifyIconW(NIM_MODIFY, &data);
}
let hwnd_usize = hwnd as usize;
std::thread::spawn(move || {
std::thread::sleep(Duration::from_secs(8));
unsafe {
let mut del: NOTIFYICONDATAW = std::mem::zeroed();
del.cbSize = std::mem::size_of::<NOTIFYICONDATAW>() as u32;
del.hWnd = hwnd_usize as HWND;
del.uID = NOTIFICATION_ICON_ID;
Shell_NotifyIconW(NIM_DELETE, &del);
}
});
}