native_windows_gui2/win32/
message_box.rs

1use super::base_helper::to_utf16;
2use crate::controls::ControlHandle;
3use std::ptr;
4use winapi::shared::windef::HWND;
5
6/**
7    Enum of message box buttons (to use with `MessageParams` )
8*/
9#[derive(Clone, PartialEq, Debug)]
10pub enum MessageButtons {
11    AbortTryIgnore,
12    CancelTryContinue,
13    Ok,
14    OkCancel,
15    RetryCancel,
16    YesNo,
17    YesNoCancel,
18}
19
20/**
21    Enum of message box icons (to use with `MessageParams` )
22*/
23#[derive(Clone, PartialEq, Debug)]
24pub enum MessageIcons {
25    Warning,
26    Info,
27    Question,
28    Error,
29    None,
30}
31
32/**
33    Return value of `message`. Define the button that the user clicked. If the user
34    cancelled the message box by clicking on X button of the window, `MessageChoice::Cancel` is returned.
35*/
36#[derive(Clone, PartialEq, Debug)]
37pub enum MessageChoice {
38    Abort,
39    Cancel,
40    Continue,
41    Ignore,
42    No,
43    Ok,
44    Retry,
45    TryAgain,
46    Yes,
47}
48
49/**
50    A structure that defines how a messagebox should look and behave.
51
52    Members:
53    * `title`: The title of the message box
54    * `content`: The message of the message box
55    * `buttons`: The button of the message box
56    * `icons`: The message box icon
57*/
58#[derive(Clone, PartialEq, Debug)]
59pub struct MessageParams<'a> {
60    pub title: &'a str,
61    pub content: &'a str,
62    pub buttons: MessageButtons,
63    pub icons: MessageIcons,
64}
65
66/// Inner function used by the message box function
67fn inner_message(parent: HWND, params: &MessageParams) -> MessageChoice {
68    use winapi::um::winuser::{
69        MB_ABORTRETRYIGNORE, MB_CANCELTRYCONTINUE, MB_ICONEXCLAMATION, MB_ICONINFORMATION,
70        MB_ICONQUESTION, MB_ICONSTOP, MB_OK, MB_OKCANCEL, MB_RETRYCANCEL, MB_YESNO, MB_YESNOCANCEL,
71    };
72
73    use winapi::um::winuser::MessageBoxW;
74    use winapi::um::winuser::{
75        IDABORT, IDCANCEL, IDCONTINUE, IDIGNORE, IDNO, IDOK, IDRETRY, IDTRYAGAIN, IDYES,
76    };
77
78    let text = to_utf16(params.content);
79    let title = to_utf16(params.title);
80
81    let buttons = match params.buttons {
82        MessageButtons::AbortTryIgnore => MB_ABORTRETRYIGNORE,
83        MessageButtons::CancelTryContinue => MB_CANCELTRYCONTINUE,
84        MessageButtons::Ok => MB_OK,
85        MessageButtons::OkCancel => MB_OKCANCEL,
86        MessageButtons::RetryCancel => MB_RETRYCANCEL,
87        MessageButtons::YesNo => MB_YESNO,
88        MessageButtons::YesNoCancel => MB_YESNOCANCEL,
89    };
90
91    let icons = match params.icons {
92        MessageIcons::Error => MB_ICONSTOP,
93        MessageIcons::Info => MB_ICONINFORMATION,
94        MessageIcons::None => 0,
95        MessageIcons::Question => MB_ICONQUESTION,
96        MessageIcons::Warning => MB_ICONEXCLAMATION,
97    };
98
99    let answer = unsafe { MessageBoxW(parent, text.as_ptr(), title.as_ptr(), buttons | icons) };
100    match answer {
101        IDABORT => MessageChoice::Abort,
102        IDCANCEL => MessageChoice::Cancel,
103        IDCONTINUE => MessageChoice::Continue,
104        IDIGNORE => MessageChoice::Ignore,
105        IDNO => MessageChoice::No,
106        IDOK => MessageChoice::Ok,
107        IDRETRY => MessageChoice::Retry,
108        IDTRYAGAIN => MessageChoice::TryAgain,
109        IDYES => MessageChoice::Yes,
110        _ => MessageChoice::Cancel,
111    }
112}
113
114/**
115    Create an application wide message box.
116    It is recommended to use `modal_message` because it locks the window that creates the message box.
117    This method may be deprecated in the future
118
119    Parameters:
120    * params: A `MessageParams` structure that defines how the message box should look
121
122    ```rust
123    use native_windows_gui2 as nwg;
124    fn test_message() {
125        let p = nwg::MessageParams {
126            title: "Hey",
127            content: "Cats are cute",
128            buttons: nwg::MessageButtons::Ok,
129            icons: nwg::MessageIcons::Warning
130        };
131
132        assert!(nwg::message(&p) == nwg::MessageChoice::Ok)
133    }
134    ```
135*/
136pub fn message<'a>(params: &MessageParams) -> MessageChoice {
137    inner_message(ptr::null_mut(), params)
138}
139
140/**
141    Create a message box for a selected window. The window will be locked until the user close the message box.
142
143    This functions panics if a non window control is used as parent (ex: a menu)
144
145    Parameters:
146    * parent: The reference to a window-like control
147    * params: A `MessageParams` structure that defines how the message box should look
148
149    ```rust
150    use native_windows_gui2 as nwg;
151    fn test_message(parent: &nwg::Window) {
152        let p = nwg::MessageParams {
153            title: "Hey",
154            content: "Cats are cute",
155            buttons: nwg::MessageButtons::Ok,
156            icons: nwg::MessageIcons::Warning
157        };
158
159        assert!(nwg::modal_message(parent, &p) == nwg::MessageChoice::Ok)
160    }
161    ```
162*/
163pub fn modal_message<'a, P: Into<ControlHandle>>(
164    parent: P,
165    params: &MessageParams,
166) -> MessageChoice {
167    let control_handle = parent.into();
168    let hwnd = control_handle.hwnd().expect("expected window like control");
169    inner_message(hwnd, params)
170}
171
172/**
173    Display a message box and then panic. The message box has for style `MessageButtons::Ok` and `MessageIcons::Error` .
174    It is recommended to use `modal_fatal_message` because it locks the window that creates the message box.
175    This method may be deprecated in the future
176
177    Parameters:
178    * title: The message box title
179    * content: The message box message
180*/
181pub fn fatal_message<'a>(title: &'a str, content: &'a str) -> ! {
182    error_message(title, content);
183    panic!("{} - {}", title, content);
184}
185
186/**
187    Display a message box and then panic. The message box has for style `MessageButtons::Ok` and `MessageIcons::Error` .
188
189    This functions panics if a non window control is used as parent (ex: a menu)
190
191    Parameters:
192    * parent: Parent window to lock for the duration of the message box
193    * title: The message box title
194    * content: The message box message
195*/
196pub fn modal_fatal_message<'a, P: Into<ControlHandle>>(
197    parent: P,
198    title: &'a str,
199    content: &'a str,
200) -> ! {
201    modal_error_message(parent, title, content);
202    panic!("{} - {}", title, content);
203}
204
205/**
206    Display a simple error message box. The message box has for style `MessageButtons::Ok` and `MessageIcons::Error`.
207    It is recommended to use `modal_error_message` because it locks the window that creates the message box.
208    This method may be deprecated in the future
209
210    Parameters:
211    * title: The message box title
212    * content: The message box message
213*/
214pub fn error_message<'a>(title: &'a str, content: &'a str) -> MessageChoice {
215    let params = MessageParams {
216        title,
217        content,
218        buttons: MessageButtons::Ok,
219        icons: MessageIcons::Error,
220    };
221
222    message(&params)
223}
224
225/**
226    Display a simple error message box. The message box has for style `MessageButtons::Ok` and `MessageIcons::Error`.
227
228    This functions panics if a non window control is used as parent (ex: a menu)
229
230    Parameters:
231    * parent: Parent window to lock for the duration of the message box
232    * title: The message box title
233    * content: The message box message
234*/
235pub fn modal_error_message<'a, P: Into<ControlHandle>>(
236    parent: P,
237    title: &'a str,
238    content: &'a str,
239) -> MessageChoice {
240    let params = MessageParams {
241        title,
242        content,
243        buttons: MessageButtons::Ok,
244        icons: MessageIcons::Error,
245    };
246
247    modal_message(parent, &params)
248}
249
250/**
251    Display a simple message box. The message box has for style `MessageButtons::Ok` and `MessageIcons::Info`.
252    It is recommended to use `modal_info_message` because it locks the window that creates the message box.
253    This method may be deprecated in the future
254
255    Parameters:
256    * title: The message box title
257    * content: The message box message
258*/
259pub fn simple_message<'a>(title: &'a str, content: &'a str) -> MessageChoice {
260    let params = MessageParams {
261        title,
262        content,
263        buttons: MessageButtons::Ok,
264        icons: MessageIcons::Info,
265    };
266
267    message(&params)
268}
269
270/**
271    Display a simple message box. The message box has for style `MessageButtons::Ok` and `MessageIcons::Info`.
272
273    This functions panics if a non window control is used as parent (ex: a menu)
274
275    Parameters:
276    * parent: Parent window to lock for the duration of the message box
277    * title: The message box title
278    * content: The message box message
279*/
280pub fn modal_info_message<'a, P: Into<ControlHandle>>(
281    parent: P,
282    title: &'a str,
283    content: &'a str,
284) -> MessageChoice {
285    let params = MessageParams {
286        title,
287        content,
288        buttons: MessageButtons::Ok,
289        icons: MessageIcons::Info,
290    };
291
292    modal_message(parent, &params)
293}