winapi_easy/ui/
message_box.rs1use crate::internal::ReturnValue;
2use num_enum::{
3 FromPrimitive,
4 IntoPrimitive,
5};
6use std::io;
7use windows::core::PCWSTR;
8use windows::Win32::UI::WindowsAndMessaging::{
9 MessageBoxExW,
10 IDABORT,
11 IDCANCEL,
12 IDCONTINUE,
13 IDIGNORE,
14 IDNO,
15 IDOK,
16 IDRETRY,
17 IDTRYAGAIN,
18 IDYES,
19 MB_ABORTRETRYIGNORE,
20 MB_CANCELTRYCONTINUE,
21 MB_ICONERROR,
22 MB_ICONINFORMATION,
23 MB_ICONQUESTION,
24 MB_ICONWARNING,
25 MB_OK,
26 MB_OKCANCEL,
27 MB_RETRYCANCEL,
28 MB_YESNO,
29 MB_YESNOCANCEL,
30 MESSAGEBOX_STYLE,
31};
32
33use crate::string::ToWideString;
34use crate::ui::WindowHandle;
35
36#[derive(Copy, Clone, Default, Debug)]
37pub struct MessageBoxOptions<'a> {
38 pub message: Option<&'a str>,
39 pub caption: Option<&'a str>,
40 pub buttons: MessageBoxButtons,
41 pub icon: Option<MessageBoxIcon>,
42}
43
44#[derive(IntoPrimitive, Copy, Clone, Eq, PartialEq, Default, Debug)]
45#[repr(u32)]
46pub enum MessageBoxButtons {
47 #[default]
48 Ok = MB_OK.0,
49 OkCancel = MB_OKCANCEL.0,
50 RetryCancel = MB_RETRYCANCEL.0,
51 YesNo = MB_YESNO.0,
52 YesNoCancel = MB_YESNOCANCEL.0,
53 AbortRetryIgnore = MB_ABORTRETRYIGNORE.0,
54 CancelTryContinue = MB_CANCELTRYCONTINUE.0,
55}
56
57impl From<MessageBoxButtons> for MESSAGEBOX_STYLE {
58 fn from(value: MessageBoxButtons) -> Self {
59 MESSAGEBOX_STYLE(value.into())
60 }
61}
62
63#[derive(IntoPrimitive, Copy, Clone, Eq, PartialEq, Default, Debug)]
64#[repr(u32)]
65pub enum MessageBoxIcon {
66 #[default]
67 Information = MB_ICONINFORMATION.0,
68 QuestionMark = MB_ICONQUESTION.0,
69 Warning = MB_ICONWARNING.0,
70 Error = MB_ICONERROR.0,
71}
72
73impl From<MessageBoxIcon> for MESSAGEBOX_STYLE {
74 fn from(value: MessageBoxIcon) -> Self {
75 MESSAGEBOX_STYLE(value.into())
76 }
77}
78
79#[derive(FromPrimitive, Copy, Clone, Eq, PartialEq, Debug)]
80#[repr(i32)]
81pub enum PressedMessageBoxButton {
82 Ok = IDOK.0,
83 Cancel = IDCANCEL.0,
84 Abort = IDABORT.0,
85 Retry = IDRETRY.0,
86 Ignore = IDIGNORE.0,
87 Yes = IDYES.0,
88 No = IDNO.0,
89 TryAgain = IDTRYAGAIN.0,
90 Continue = IDCONTINUE.0,
91 #[num_enum(catch_all)]
92 Other(i32),
93}
94
95pub fn show_message_box(
96 window_handle: &WindowHandle,
97 options: MessageBoxOptions,
98) -> io::Result<PressedMessageBoxButton> {
99 let result = unsafe {
100 MessageBoxExW(
101 window_handle.raw_handle,
102 options
103 .message
104 .map(|x| PCWSTR::from_raw(x.to_wide_string().as_ptr()))
105 .as_ref(),
106 options
107 .caption
108 .map(|x| PCWSTR::from_raw(x.to_wide_string().as_ptr()))
109 .as_ref(),
110 MESSAGEBOX_STYLE::from(options.buttons)
111 | options.icon.map(MESSAGEBOX_STYLE::from).unwrap_or_default(),
112 0,
113 )
114 };
115 let _ = result.0.if_null_get_last_error()?;
116 Ok(result.0.into())
117}