From 0ae81ad8b22dd2622e302254ce434d14880087a3 Mon Sep 17 00:00:00 2001 From: Pavel Kuzmin Date: Mon, 28 Jul 2025 18:50:09 +0500 Subject: [PATCH] Fix: Windows submenu icons support (#308) --- .changes/refactor-simplify-internal-id-usage.md | 5 +++++ examples/tao.rs | 7 +++++-- examples/windows-common-controls-v6/src/main.rs | 3 +++ examples/winit.rs | 7 +++++-- examples/wry.rs | 7 +++++-- src/platform_impl/windows/mod.rs | 8 ++++++-- 6 files changed, 29 insertions(+), 8 deletions(-) create mode 100644 .changes/refactor-simplify-internal-id-usage.md diff --git a/.changes/refactor-simplify-internal-id-usage.md b/.changes/refactor-simplify-internal-id-usage.md new file mode 100644 index 0000000..05b07ec --- /dev/null +++ b/.changes/refactor-simplify-internal-id-usage.md @@ -0,0 +1,5 @@ +--- +"muda": patch +--- + +On Windows, fix icon of `Submenu` not visible when added to a root `Menu` diff --git a/examples/tao.rs b/examples/tao.rs index afa95f6..93de5ed 100644 --- a/examples/tao.rs +++ b/examples/tao.rs @@ -78,10 +78,15 @@ fn main() { ]); } + let path = concat!(env!("CARGO_MANIFEST_DIR"), "/examples/icon.png"); + let icon = load_icon(std::path::Path::new(path)); + let file_m = Submenu::new("&File", true); let edit_m = Submenu::new("&Edit", true); let window_m = Submenu::new("&Window", true); + window_m.set_icon(Some(icon.clone())); + menu_bar.append_items(&[&file_m, &edit_m, &window_m]); let custom_i_1 = MenuItem::with_id( @@ -91,8 +96,6 @@ fn main() { Some(Accelerator::new(Some(Modifiers::ALT), Code::KeyC)), ); - let path = concat!(env!("CARGO_MANIFEST_DIR"), "/examples/icon.png"); - let icon = load_icon(std::path::Path::new(path)); let image_item = IconMenuItem::with_id( "image-custom-1", "Image custom 1", diff --git a/examples/windows-common-controls-v6/src/main.rs b/examples/windows-common-controls-v6/src/main.rs index 2111460..8bf1fc2 100644 --- a/examples/windows-common-controls-v6/src/main.rs +++ b/examples/windows-common-controls-v6/src/main.rs @@ -77,6 +77,9 @@ fn main() { Some(Accelerator::new(Some(Modifiers::ALT), Code::KeyC)), ); + let path = concat!(env!("CARGO_MANIFEST_DIR"), "/examples/icon.png"); + let icon = load_icon(std::path::Path::new(path)); + let image_item = IconMenuItem::new("Image Custom 1", true, Some(icon), None); let check_custom_i_1 = CheckMenuItem::new("Check Custom 1", true, true, None); diff --git a/examples/winit.rs b/examples/winit.rs index 1911bae..7f628a1 100644 --- a/examples/winit.rs +++ b/examples/winit.rs @@ -186,10 +186,15 @@ impl AppMenu { menu_bar.append(&app_menu); } + let path = concat!(env!("CARGO_MANIFEST_DIR"), "/examples/icon.png"); + let icon = load_icon(std::path::Path::new(path)); + let file_menu = Submenu::new("&File", true); let edit_menu = Submenu::new("&Edit", true); let window_menu = Submenu::new("&Window", true); + window_menu.set_icon(Some(icon.clone())); + menu_bar.append_items(&[&file_menu, &edit_menu, &window_menu]); let custom_i_1 = MenuItem::new( @@ -198,8 +203,6 @@ impl AppMenu { Some(Accelerator::new(Some(Modifiers::ALT), Code::KeyC)), ); - let path = concat!(env!("CARGO_MANIFEST_DIR"), "/examples/icon.png"); - let icon = load_icon(std::path::Path::new(path)); let image_item = IconMenuItem::new("Image Custom 1", true, Some(icon), None); let check_custom_i_1 = CheckMenuItem::new("Check Custom 1", true, true, None); diff --git a/examples/wry.rs b/examples/wry.rs index c2ed00f..1d86dc9 100644 --- a/examples/wry.rs +++ b/examples/wry.rs @@ -86,10 +86,15 @@ fn main() -> wry::Result<()> { .unwrap(); } + let path = concat!(env!("CARGO_MANIFEST_DIR"), "/examples/icon.png"); + let icon = load_icon(std::path::Path::new(path)); + let file_m = Submenu::new("&File", true); let edit_m = Submenu::new("&Edit", true); let window_m = Submenu::new("&Window", true); + window_m.set_icon(Some(icon.clone())); + menu_bar .append_items(&[&file_m, &edit_m, &window_m]) .unwrap(); @@ -100,8 +105,6 @@ fn main() -> wry::Result<()> { Some(Accelerator::new(Some(Modifiers::ALT), Code::KeyC)), ); - let path = concat!(env!("CARGO_MANIFEST_DIR"), "/examples/icon.png"); - let icon = load_icon(std::path::Path::new(path)); let image_item = IconMenuItem::new( "Image custom 1", true, diff --git a/src/platform_impl/windows/mod.rs b/src/platform_impl/windows/mod.rs index 4e08100..9f73626 100644 --- a/src/platform_impl/windows/mod.rs +++ b/src/platform_impl/windows/mod.rs @@ -235,17 +235,19 @@ impl Menu { let child_ = child.borrow(); let item_type = child_.item_type(); + // Set icons for both regular menu items and submenus if matches!(item_type, MenuItemType::Icon | MenuItemType::Submenu) { let hbitmap = child_ .icon .as_ref() .map(|i| unsafe { i.inner.to_hbitmap() }) .unwrap_or(std::ptr::null_mut()); + let info = create_icon_item_info(hbitmap); unsafe { - SetMenuItemInfoW(self.hmenu, child_.internal_id, FALSE, &info); - SetMenuItemInfoW(self.hpopupmenu, child_.internal_id, FALSE, &info); + SetMenuItemInfoW(self.hmenu, child_.internal_id(), FALSE, &info); + SetMenuItemInfoW(self.hpopupmenu, child_.internal_id(), FALSE, &info); }; } } @@ -795,7 +797,9 @@ impl MenuChild { let hbitmap = icon .map(|i| unsafe { i.inner.to_hbitmap() }) .unwrap_or(std::ptr::null_mut()); + let info = create_icon_item_info(hbitmap); + for (parent, menu_bars) in &self.parents_hemnu { unsafe { SetMenuItemInfoW(*parent, self.internal_id(), FALSE, &info) };