kamft_desktop 0.0.4

Kamft desktop utilities including screenshot capture and WeChat Work integration
/// Windows 命名互斥体 + 查找已有窗口,实现单例模式
/// 如果已有实例运行,激活其窗口后退出当前进程
#[cfg(target_os = "windows")]
pub fn ensure_single_instance() {
    extern "system" {
        fn CreateMutexW(
            lp_mutex_attributes: *mut std::ffi::c_void,
            b_initial_owner: i32,
            lp_name: *const u16,
        ) -> *mut std::ffi::c_void;
        fn GetLastError() -> u32;
        fn CloseHandle(h_object: *mut std::ffi::c_void) -> i32;
        fn FindWindowW(class_name: *const u16, window_name: *const u16) -> *mut std::ffi::c_void;
        fn ShowWindow(h_wnd: *mut std::ffi::c_void, n_cmd_show: i32) -> i32;
        fn SetForegroundWindow(h_wnd: *mut std::ffi::c_void) -> i32;
        fn IsIconic(h_wnd: *mut std::ffi::c_void) -> i32;
    }

    const ERROR_ALREADY_EXISTS: u32 = 183;
    const SW_RESTORE: i32 = 9;
    const SW_SHOW: i32 = 5;

    let name: Vec<u16> = "Global\\start_kamft_single_instance\0"
        .encode_utf16()
        .collect();
    unsafe {
        let handle = CreateMutexW(std::ptr::null_mut(), 1, name.as_ptr());
        if handle.is_null() {
            return;
        }
        if GetLastError() == ERROR_ALREADY_EXISTS {
            CloseHandle(handle);
            // 已有实例 → 查找窗口并激活
            let title: Vec<u16> = "招财进宝小助手\0".encode_utf16().collect();
            let hwnd = FindWindowW(std::ptr::null(), title.as_ptr());
            if !hwnd.is_null() {
                if IsIconic(hwnd) != 0 {
                    ShowWindow(hwnd, SW_RESTORE); // 最小化状态 → 恢复
                } else {
                    ShowWindow(hwnd, SW_SHOW); // 隐藏状态 → 显示
                }
                SetForegroundWindow(hwnd); // 带到前台
            }
            std::process::exit(0);
        }
        // 互斥体由当前进程持有,进程退出时自动释放
    }
}

/// 非 Windows 平台:单例检测为空操作
#[cfg(not(target_os = "windows"))]
pub fn ensure_single_instance() {
    // 非 Windows 平台暂不支持单例检测
}