Skip to content
7 changes: 7 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -915,6 +915,13 @@ impl Window {
self.0.remove_menu(handle)
}

/// Enable or disable a menu item
#[cfg(target_os = "windows")]
#[inline]
pub fn enable_menu(&mut self, handle: Option<MenuHandle>, index: usize, enabled: bool) {
self.0.enable_menu(handle, index, enabled)
}

/// Get POSIX menus. Will only return menus on POSIX-like OSes like Linux or BSD
/// otherwise ```None```
#[cfg(any(target_os = "macos", target_os = "windows", target_arch = "wasm32"))]
Expand Down
76 changes: 64 additions & 12 deletions src/os/windows/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
use crate::{
check_buffer_size, error::Error, icon::Icon, key_handler::KeyHandler, rate::UpdateRate,
CursorStyle, InputCallback, Key, KeyRepeat, MenuHandle, MenuItem, MenuItemHandle, MouseButton,
MouseMode, Result, Scale, ScaleMode, WindowOptions, MENU_KEY_ALT, MENU_KEY_CTRL,
MENU_KEY_SHIFT, MENU_KEY_WIN,
MouseMode, Result, Scale, ScaleMode, WindowOptions, MENU_ID_SEPARATOR, MENU_KEY_ALT,
MENU_KEY_CTRL, MENU_KEY_SHIFT, MENU_KEY_WIN,
};
use raw_window_handle::{
DisplayHandle, HandleError, HasDisplayHandle, HasWindowHandle, RawDisplayHandle,
Expand All @@ -14,6 +14,7 @@ use std::{
ffi::{c_int, c_void, OsStr},
num::NonZeroIsize,
os::windows::ffi::OsStrExt,
ptr::null,
time::Duration,
};
use winapi::{
Expand All @@ -28,7 +29,7 @@ use winapi::{
libloaderapi, wingdi,
winuser::{
self, GET_XBUTTON_WPARAM, ICON_BIG, ICON_SMALL, IMAGE_ICON, LR_DEFAULTSIZE,
LR_LOADFROMFILE, WM_SETICON,
LR_LOADFROMFILE, MF_ENABLED, MF_GRAYED, MF_POPUP, MF_SEPARATOR, WM_SETICON,
},
},
};
Expand Down Expand Up @@ -1108,7 +1109,7 @@ impl Window {

winuser::AppendMenuW(
main_menu,
0x10,
MF_POPUP,
menu.menu_handle as basetsd::UINT_PTR,
menu.name.as_ptr(),
);
Expand Down Expand Up @@ -1146,6 +1147,38 @@ impl Window {
}
}

/// Enables or disables a menu item.
///
/// If handle is None the main menu bar is used
pub fn enable_menu(&mut self, handle: Option<MenuHandle>, position: usize, enabled: bool) {
let window = self.hwnd;
let main_menu = unsafe { winuser::GetMenu(window) };
match handle {
None => unsafe {
winuser::EnableMenuItem(
main_menu,
position as basetsd::UINT32,
winuser::MF_BYPOSITION | if enabled { MF_ENABLED } else { MF_GRAYED },
);
},
Some(menuhandle) => {
for i in 0..self.menus.len() {
if self.menus[i].menu_handle == menuhandle.0 as windef::HMENU {
unsafe {
winuser::EnableMenuItem(
menuhandle.0 as windef::HMENU,
position as basetsd::UINT32,
winuser::MF_BYPOSITION
| if enabled { MF_ENABLED } else { MF_GRAYED },
);
}
return;
}
}
}
}
}

#[inline]
pub fn is_menu_pressed(&mut self) -> Option<usize> {
if self.accel_key == INVALID_ACCEL {
Expand Down Expand Up @@ -1294,7 +1327,7 @@ impl Menu {
let menu_name = to_wstring(name);
winuser::AppendMenuW(
self.menu_handle,
0x10,
MF_POPUP,
menu.menu_handle as basetsd::UINT_PTR,
menu_name.as_ptr(),
);
Expand Down Expand Up @@ -1380,19 +1413,38 @@ impl Menu {
match vk_accel.0 {
0 => {
let item_name = to_wstring(&menu_item.label);
winuser::AppendMenuW(
self.menu_handle,
0x10,
menu_item.id as basetsd::UINT_PTR,
item_name.as_ptr(),
);
if menu_item.id == MENU_ID_SEPARATOR {
winuser::AppendMenuW(
self.menu_handle,
MF_SEPARATOR,
0 as basetsd::UINT_PTR,
null(),
);
} else {
winuser::AppendMenuW(
self.menu_handle,
MF_POPUP
| if menu_item.enabled {
MF_ENABLED
} else {
MF_GRAYED
},
menu_item.id as basetsd::UINT_PTR,
item_name.as_ptr(),
);
}
}
_ => {
let menu_name = Self::format_name(menu_item, vk_accel.1);
let w_name = to_wstring(&menu_name);
winuser::AppendMenuW(
self.menu_handle,
0x10,
MF_POPUP
| if menu_item.enabled {
MF_ENABLED
} else {
MF_GRAYED
},
menu_item.id as basetsd::UINT_PTR,
w_name.as_ptr(),
);
Expand Down
Loading