winapi_easy/ui/
message_box.rs

1use 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}