Add ability to assign a menu when creating a window on Windows (#1842)

This commit is contained in:
Mads Marquart 2021-02-04 22:26:33 +01:00 committed by GitHub
parent bd99eb1347
commit b1d353180b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 27 additions and 3 deletions

View file

@ -6,6 +6,7 @@
- On Windows, fix bug causing mouse capture to not be released. - On Windows, fix bug causing mouse capture to not be released.
- On Windows, fix fullscreen not preserving minimized/maximized state. - On Windows, fix fullscreen not preserving minimized/maximized state.
- On Android, unimplemented events are marked as unhandled on the native event loop. - On Android, unimplemented events are marked as unhandled on the native event loop.
- On Windows, added `WindowBuilderExtWindows::with_menu` to set a custom menu at window creation time.
- On Android, bump `ndk` and `ndk-glue` to 0.3: use predefined constants for event `ident`. - On Android, bump `ndk` and `ndk-glue` to 0.3: use predefined constants for event `ident`.
# 0.24.0 (2020-12-09) # 0.24.0 (2020-12-09)

View file

@ -116,6 +116,7 @@ If your PR makes notable changes to Winit's features, please update this section
### Windows ### Windows
* Setting the taskbar icon * Setting the taskbar icon
* Setting the parent window * Setting the parent window
* Setting a menu bar
* `WS_EX_NOREDIRECTIONBITMAP` support * `WS_EX_NOREDIRECTIONBITMAP` support
* Theme the title bar according to Windows 10 Dark Mode setting or set a preferred theme * Theme the title bar according to Windows 10 Dark Mode setting or set a preferred theme

View file

@ -5,7 +5,7 @@ use std::path::Path;
use libc; use libc;
use winapi::shared::minwindef::WORD; use winapi::shared::minwindef::WORD;
use winapi::shared::windef::HWND; use winapi::shared::windef::{HMENU, HWND};
use crate::{ use crate::{
dpi::PhysicalSize, dpi::PhysicalSize,
@ -112,6 +112,16 @@ pub trait WindowBuilderExtWindows {
/// Sets a parent to the window to be created. /// Sets a parent to the window to be created.
fn with_parent_window(self, parent: HWND) -> WindowBuilder; fn with_parent_window(self, parent: HWND) -> WindowBuilder;
/// Sets a menu on the window to be created.
///
/// Parent and menu are mutually exclusive; a child window cannot have a menu!
///
/// The menu must have been manually created beforehand with [`winapi::um::winuser::CreateMenu`] or similar.
///
/// Note: Dark mode cannot be supported for win32 menus, it's simply not possible to change how the menus look.
/// If you use this, it is recommended that you combine it with `with_theme(Some(Theme::Light))` to avoid a jarring effect.
fn with_menu(self, menu: HMENU) -> WindowBuilder;
/// This sets `ICON_BIG`. A good ceiling here is 256x256. /// This sets `ICON_BIG`. A good ceiling here is 256x256.
fn with_taskbar_icon(self, taskbar_icon: Option<Icon>) -> WindowBuilder; fn with_taskbar_icon(self, taskbar_icon: Option<Icon>) -> WindowBuilder;
@ -137,6 +147,12 @@ impl WindowBuilderExtWindows for WindowBuilder {
self self
} }
#[inline]
fn with_menu(mut self, menu: HMENU) -> WindowBuilder {
self.platform_specific.menu = Some(menu);
self
}
#[inline] #[inline]
fn with_taskbar_icon(mut self, taskbar_icon: Option<Icon>) -> WindowBuilder { fn with_taskbar_icon(mut self, taskbar_icon: Option<Icon>) -> WindowBuilder {
self.platform_specific.taskbar_icon = taskbar_icon; self.platform_specific.taskbar_icon = taskbar_icon;

View file

@ -1,6 +1,6 @@
#![cfg(target_os = "windows")] #![cfg(target_os = "windows")]
use winapi::{self, shared::windef::HWND}; use winapi::{self, shared::windef::HMENU, shared::windef::HWND};
pub use self::{ pub use self::{
event_loop::{EventLoop, EventLoopProxy, EventLoopWindowTarget}, event_loop::{EventLoop, EventLoopProxy, EventLoopWindowTarget},
@ -18,6 +18,7 @@ use crate::window::Theme;
#[derive(Clone)] #[derive(Clone)]
pub struct PlatformSpecificWindowBuilderAttributes { pub struct PlatformSpecificWindowBuilderAttributes {
pub parent: Option<HWND>, pub parent: Option<HWND>,
pub menu: Option<HMENU>,
pub taskbar_icon: Option<Icon>, pub taskbar_icon: Option<Icon>,
pub no_redirection_bitmap: bool, pub no_redirection_bitmap: bool,
pub drag_and_drop: bool, pub drag_and_drop: bool,
@ -28,6 +29,7 @@ impl Default for PlatformSpecificWindowBuilderAttributes {
fn default() -> Self { fn default() -> Self {
Self { Self {
parent: None, parent: None,
menu: None,
taskbar_icon: None, taskbar_icon: None,
no_redirection_bitmap: false, no_redirection_bitmap: false,
drag_and_drop: true, drag_and_drop: true,

View file

@ -711,6 +711,10 @@ unsafe fn init<T: 'static>(
window_flags.set(WindowFlags::CHILD, pl_attribs.parent.is_some()); window_flags.set(WindowFlags::CHILD, pl_attribs.parent.is_some());
window_flags.set(WindowFlags::ON_TASKBAR, true); window_flags.set(WindowFlags::ON_TASKBAR, true);
if pl_attribs.parent.is_some() && pl_attribs.menu.is_some() {
warn!("Setting a menu on windows that have a parent is unsupported");
}
// creating the real window this time, by using the functions in `extra_functions` // creating the real window this time, by using the functions in `extra_functions`
let real_window = { let real_window = {
let (style, ex_style) = window_flags.to_window_styles(); let (style, ex_style) = window_flags.to_window_styles();
@ -724,7 +728,7 @@ unsafe fn init<T: 'static>(
winuser::CW_USEDEFAULT, winuser::CW_USEDEFAULT,
winuser::CW_USEDEFAULT, winuser::CW_USEDEFAULT,
pl_attribs.parent.unwrap_or(ptr::null_mut()), pl_attribs.parent.unwrap_or(ptr::null_mut()),
ptr::null_mut(), pl_attribs.menu.unwrap_or(ptr::null_mut()),
libloaderapi::GetModuleHandleW(ptr::null()), libloaderapi::GetModuleHandleW(ptr::null()),
ptr::null_mut(), ptr::null_mut(),
); );