windows_win/ui/
msg_box.rs1use crate::sys::{HWND, MessageBoxW};
4use crate::utils::Result;
5
6use std::os::windows::ffi::OsStrExt;
7use std::ffi;
8use std::ptr;
9use std::os::raw::{c_int, c_uint};
10
11use crate::utils;
12
13pub mod flags {
15 pub use crate::sys::{
16 MB_ABORTRETRYIGNORE,
18 MB_CANCELTRYCONTINUE,
19 MB_HELP,
20 MB_OK,
21 MB_OKCANCEL,
22 MB_RETRYCANCEL,
23 MB_YESNO,
24 MB_YESNOCANCEL,
25 MB_ICONEXCLAMATION,
27 MB_ICONWARNING,
28 MB_ICONINFORMATION,
29 MB_ICONASTERISK,
30 MB_ICONQUESTION,
31 MB_ICONSTOP,
32 MB_ICONERROR,
33 MB_ICONHAND,
34 MB_APPLMODAL,
36 MB_SYSTEMMODAL,
37 MB_TASKMODAL,
38 };
39}
40
41#[derive(Debug, PartialEq, Eq)]
42pub enum MsgBoxResult {
44 Abort,
46 Cancel,
48 Continue,
50 Ignore,
52 No,
54 Ok,
56 Retry,
58 TryAgain,
60 Yes,
62 Ext(c_int),
64}
65
66impl From<c_int> for MsgBoxResult {
67 fn from(value: c_int) -> MsgBoxResult {
68 match value {
69 1 => MsgBoxResult::Ok,
70 2 => MsgBoxResult::Cancel,
71 3 => MsgBoxResult::Abort,
72 4 => MsgBoxResult::Retry,
73 5 => MsgBoxResult::Ignore,
74 6 => MsgBoxResult::Yes,
75 7 => MsgBoxResult::No,
76 10 => MsgBoxResult::TryAgain,
77 11 => MsgBoxResult::Continue,
78 value => MsgBoxResult::Ext(value),
79 }
80 }
81}
82
83pub struct MessageBox {
89 parent: HWND,
90 text: Vec<u16>,
91 caption: Option<Vec<u16>>,
92 flags: c_uint,
93}
94
95impl MessageBox {
96 pub fn new(text: &ffi::OsStr) -> Self {
100 let mut text: Vec<u16> = text.encode_wide().collect();
101 text.push(0);
102
103 Self {
104 parent: ptr::null_mut(),
105 text,
106 caption: None,
107 flags: flags::MB_OK,
108 }
109 }
110
111 #[inline]
112 pub fn info<T: AsRef<ffi::OsStr>>(text: T) -> Self {
114 let mut res = Self::new(text.as_ref());
115 res.flags |= flags::MB_ICONINFORMATION;
116 res
117 }
118
119 #[inline]
120 pub fn error<T: AsRef<ffi::OsStr>>(text: T) -> Self {
122 let mut res = Self::new(text.as_ref());
123 res.flags |= flags::MB_ICONERROR;
124 res
125 }
126
127 pub fn parent(&mut self, parent: HWND) -> &mut Self {
129 self.parent = parent;
130 self
131 }
132
133 pub fn set_flags(&mut self, flags: c_uint) -> &mut Self {
135 self.flags = flags;
136 self
137 }
138
139 pub fn flags(&mut self, flags: c_uint) -> &mut Self {
141 self.flags |= flags;
142 self
143 }
144
145 pub fn text<T: AsRef<ffi::OsStr>>(&mut self, text: T) -> &mut Self {
147 let text = text.as_ref();
148
149 self.text.truncate(0);
150 for ch in text.encode_wide() {
151 self.text.push(ch);
152 }
153 self.text.push(0);
154
155 self
156 }
157
158 pub fn title<T: AsRef<ffi::OsStr>>(&mut self, text: T) -> &mut Self {
160 let title = text.as_ref();
161
162 self.caption = match self.caption.take() {
163 Some(mut caption) => {
164 caption.truncate(0);
165 for ch in title.encode_wide() {
166 caption.push(ch);
167 }
168 caption.push(0);
169 Some(caption)
170 },
171 None => {
172 let mut title: Vec<u16> = title.encode_wide().collect();
173 title.push(0);
174 Some(title)
175 },
176 };
177
178 self
179 }
180
181 pub fn show(&self) -> Result<MsgBoxResult> {
183 let caption = self.caption.as_ref().map(|caption| caption.as_ptr()).unwrap_or_else(|| ptr::null());
184
185 match unsafe { MessageBoxW(self.parent, self.text.as_ptr(), caption, self.flags) } {
186 0 => Err(utils::get_last_error()),
187 n => Ok(MsgBoxResult::from(n)),
188 }
189 }
190}