winapi_easy/ui/
taskbar.rs

1//! Taskbar functionality.
2
3use std::io;
4
5use num_enum::IntoPrimitive;
6use windows::Win32::Foundation::HWND;
7use windows::Win32::UI::Shell::{
8    ITaskbarList3,
9    TBPF_ERROR,
10    TBPF_INDETERMINATE,
11    TBPF_NOPROGRESS,
12    TBPF_NORMAL,
13    TBPF_PAUSED,
14    TBPFLAG,
15    TaskbarList,
16};
17use windows::core::GUID;
18
19use crate::com::ComInterfaceExt;
20use crate::internal::custom_err_with_code;
21use crate::ui::window::WindowHandle;
22
23/// Taskbar progress state animation type.
24#[derive(IntoPrimitive, Copy, Clone, Eq, PartialEq, Default, Debug)]
25#[repr(i32)]
26pub enum ProgressState {
27    /// Stops displaying progress and returns the button to its normal state.
28    #[default]
29    NoProgress = TBPF_NOPROGRESS.0,
30    /// Shows a "working" animation without indicating a completion percentage.
31    Indeterminate = TBPF_INDETERMINATE.0,
32    /// Shows a progress indicator displaying the amount of work being completed.
33    Normal = TBPF_NORMAL.0,
34    /// The progress indicator turns red to show that an error has occurred. This is a determinate state.
35    /// If the progress indicator is in the indeterminate state, it switches to a red determinate display
36    /// of a generic percentage not indicative of actual progress.
37    Error = TBPF_ERROR.0,
38    /// The progress indicator turns yellow to show that progress is currently stopped. This is a determinate state.
39    /// If the progress indicator is in the indeterminate state, it switches to a yellow determinate display
40    /// of a generic percentage not indicative of actual progress.
41    Paused = TBPF_PAUSED.0,
42}
43
44impl From<ProgressState> for TBPFLAG {
45    fn from(value: ProgressState) -> Self {
46        TBPFLAG(value.into())
47    }
48}
49
50/// Taskbar functionality.
51pub struct Taskbar {
52    taskbar_list_3: ITaskbarList3,
53}
54
55impl Taskbar {
56    pub fn new() -> io::Result<Self> {
57        let result = Taskbar {
58            taskbar_list_3: ITaskbarList3::new_instance()?,
59        };
60        Ok(result)
61    }
62
63    /// Sets the progress state taskbar animation of a window.
64    ///
65    /// See also: [Microsoft docs](https://docs.microsoft.com/en-us/windows/win32/api/shobjidl_core/nf-shobjidl_core-itaskbarlist3-setprogressstate)
66    ///
67    /// # Examples
68    ///
69    /// ```no_run
70    /// use winapi_easy::ui::taskbar::{
71    ///     ProgressState,
72    ///     Taskbar,
73    /// };
74    /// use winapi_easy::ui::window::WindowHandle;
75    ///
76    /// use std::thread;
77    /// use std::time::Duration;
78    ///
79    /// let window = WindowHandle::get_console_window().expect("Cannot get console window");
80    /// let taskbar = Taskbar::new()?;
81    ///
82    /// taskbar.set_progress_state(window, ProgressState::Indeterminate)?;
83    /// thread::sleep(Duration::from_millis(3000));
84    /// taskbar.set_progress_state(window, ProgressState::NoProgress)?;
85    ///
86    /// # Result::<(), std::io::Error>::Ok(())
87    /// ```
88    pub fn set_progress_state(&self, window: WindowHandle, state: ProgressState) -> io::Result<()> {
89        let ret_val = unsafe {
90            self.taskbar_list_3
91                .SetProgressState(HWND::from(window), state.into())
92        };
93        ret_val.map_err(|err| custom_err_with_code("Error setting progress state", err.code()))
94    }
95
96    /// Sets the completion amount of the taskbar progress state animation.
97    pub fn set_progress_value(
98        &self,
99        window: WindowHandle,
100        completed: u64,
101        total: u64,
102    ) -> io::Result<()> {
103        let ret_val = unsafe {
104            self.taskbar_list_3
105                .SetProgressValue(HWND::from(window), completed, total)
106        };
107        ret_val.map_err(|err| custom_err_with_code("Error setting progress value", err.code()))
108    }
109}
110
111impl ComInterfaceExt for ITaskbarList3 {
112    const CLASS_GUID: GUID = TaskbarList;
113}