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}