use native apis for getters on windows

This commit is contained in:
amrbashir 2022-05-06 19:37:49 +02:00
parent 832e4964e7
commit 2ccd400497
No known key found for this signature in database
GPG key ID: BBD7A47A2003FF33
3 changed files with 67 additions and 30 deletions

View file

@ -13,7 +13,8 @@ features = [
"Win32_UI_WindowsAndMessaging", "Win32_UI_WindowsAndMessaging",
"Win32_Foundation", "Win32_Foundation",
"Win32_Graphics_Gdi", "Win32_Graphics_Gdi",
"Win32_UI_Shell" "Win32_UI_Shell",
"Win32_Globalization"
] ]
[target.'cfg(target_os = "linux")'.dependencies] [target.'cfg(target_os = "linux")'.dependencies]

View file

@ -1,13 +1,14 @@
#![cfg(target_os = "windows")] #![cfg(target_os = "windows")]
use crate::util::{encode_wide, Counter, LOWORD}; use crate::util::{encode_wide, wchar_ptr_to_string, Counter, LOWORD};
use windows_sys::Win32::{ use windows_sys::Win32::{
Foundation::{HWND, LPARAM, LRESULT, WPARAM}, Foundation::{HWND, LPARAM, LRESULT, WPARAM},
UI::{ UI::{
Shell::{DefSubclassProc, SetWindowSubclass}, Shell::{DefSubclassProc, SetWindowSubclass},
WindowsAndMessaging::{ WindowsAndMessaging::{
AppendMenuW, CreateMenu, EnableMenuItem, SetMenu, SetMenuItemInfoW, MENUITEMINFOW, AppendMenuW, CreateMenu, EnableMenuItem, GetMenuItemInfoW, SetMenu, SetMenuItemInfoW,
MF_DISABLED, MF_ENABLED, MF_GRAYED, MF_POPUP, MIIM_STRING, WM_COMMAND, MENUITEMINFOW, MFS_DISABLED, MF_DISABLED, MF_ENABLED, MF_GRAYED, MF_POPUP, MIIM_STATE,
MIIM_STRING, WM_COMMAND,
}, },
}, },
}; };
@ -36,8 +37,6 @@ impl Menu {
) )
}; };
Submenu { Submenu {
label: label.as_ref().to_string(),
enabled,
hmenu, hmenu,
parent_hmenu: self.0, parent_hmenu: self.0,
} }
@ -53,34 +52,49 @@ impl Menu {
#[derive(Clone)] #[derive(Clone)]
pub struct Submenu { pub struct Submenu {
label: String,
enabled: bool,
hmenu: isize, hmenu: isize,
parent_hmenu: isize, parent_hmenu: isize,
} }
impl Submenu { impl Submenu {
pub fn label(&self) -> String { pub fn label(&self) -> String {
self.label.clone() let mut label = Vec::<u16>::new();
}
pub fn set_label(&mut self, label: impl AsRef<str>) {
self.label = label.as_ref().to_string();
let mut info: MENUITEMINFOW = unsafe { std::mem::zeroed() }; let mut info: MENUITEMINFOW = unsafe { std::mem::zeroed() };
info.cbSize = std::mem::size_of::<MENUITEMINFOW>() as _; info.cbSize = std::mem::size_of::<MENUITEMINFOW>() as _;
info.fMask = MIIM_STRING; info.fMask = MIIM_STRING;
info.dwTypeData = encode_wide(&self.label).as_mut_ptr(); info.dwTypeData = label.as_mut_ptr();
unsafe { GetMenuItemInfoW(self.parent_hmenu, self.hmenu as _, false.into(), &mut info) };
info.cch += 1;
info.dwTypeData = Vec::with_capacity(info.cch as usize).as_mut_ptr();
unsafe { GetMenuItemInfoW(self.parent_hmenu, self.hmenu as _, false.into(), &mut info) };
wchar_ptr_to_string(info.dwTypeData)
}
pub fn set_label(&mut self, label: impl AsRef<str>) {
let mut info: MENUITEMINFOW = unsafe { std::mem::zeroed() };
info.cbSize = std::mem::size_of::<MENUITEMINFOW>() as _;
info.fMask = MIIM_STRING;
info.dwTypeData = encode_wide(label.as_ref()).as_mut_ptr();
unsafe { SetMenuItemInfoW(self.parent_hmenu, self.hmenu as u32, false.into(), &info) }; unsafe { SetMenuItemInfoW(self.parent_hmenu, self.hmenu as u32, false.into(), &info) };
} }
pub fn enabled(&self) -> bool { pub fn enabled(&self) -> bool {
self.enabled let mut info: MENUITEMINFOW = unsafe { std::mem::zeroed() };
info.cbSize = std::mem::size_of::<MENUITEMINFOW>() as _;
info.fMask = MIIM_STATE;
unsafe { GetMenuItemInfoW(self.parent_hmenu, self.hmenu as _, false.into(), &mut info) };
(info.fState & MFS_DISABLED) == 0
} }
pub fn set_enabled(&mut self, enabled: bool) { pub fn set_enabled(&mut self, enabled: bool) {
self.enabled = enabled;
unsafe { unsafe {
EnableMenuItem( EnableMenuItem(
self.parent_hmenu, self.parent_hmenu,
@ -105,8 +119,6 @@ impl Submenu {
) )
}; };
Submenu { Submenu {
label: label.as_ref().to_string(),
enabled,
hmenu, hmenu,
parent_hmenu: self.hmenu, parent_hmenu: self.hmenu,
} }
@ -127,8 +139,6 @@ impl Submenu {
) )
}; };
TextMenuItem { TextMenuItem {
label: label.as_ref().to_string(),
enabled,
id, id,
parent_hmenu: self.hmenu, parent_hmenu: self.hmenu,
} }
@ -137,34 +147,53 @@ impl Submenu {
#[derive(Clone)] #[derive(Clone)]
pub struct TextMenuItem { pub struct TextMenuItem {
label: String,
enabled: bool,
id: u64, id: u64,
parent_hmenu: isize, parent_hmenu: isize,
} }
impl TextMenuItem { impl TextMenuItem {
pub fn label(&self) -> String { pub fn label(&self) -> String {
self.label.clone() let mut label = Vec::<u16>::new();
}
pub fn set_label(&mut self, label: impl AsRef<str>) {
self.label = label.as_ref().to_string();
let mut info: MENUITEMINFOW = unsafe { std::mem::zeroed() }; let mut info: MENUITEMINFOW = unsafe { std::mem::zeroed() };
info.cbSize = std::mem::size_of::<MENUITEMINFOW>() as _; info.cbSize = std::mem::size_of::<MENUITEMINFOW>() as _;
info.fMask = MIIM_STRING; info.fMask = MIIM_STRING;
info.dwTypeData = encode_wide(&self.label).as_mut_ptr(); info.dwTypeData = label.as_mut_ptr();
unsafe { GetMenuItemInfoW(self.parent_hmenu, self.id as _, false.into(), &mut info) };
info.cch += 1;
info.dwTypeData = Vec::with_capacity(info.cch as usize).as_mut_ptr();
unsafe { GetMenuItemInfoW(self.parent_hmenu, self.id as _, false.into(), &mut info) };
wchar_ptr_to_string(info.dwTypeData)
.split("\t")
.next()
.unwrap_or_default()
.to_string()
}
pub fn set_label(&mut self, label: impl AsRef<str>) {
let mut info: MENUITEMINFOW = unsafe { std::mem::zeroed() };
info.cbSize = std::mem::size_of::<MENUITEMINFOW>() as _;
info.fMask = MIIM_STRING;
info.dwTypeData = encode_wide(label.as_ref()).as_mut_ptr();
unsafe { SetMenuItemInfoW(self.parent_hmenu, self.id as u32, false.into(), &info) }; unsafe { SetMenuItemInfoW(self.parent_hmenu, self.id as u32, false.into(), &info) };
} }
pub fn enabled(&self) -> bool { pub fn enabled(&self) -> bool {
self.enabled let mut info: MENUITEMINFOW = unsafe { std::mem::zeroed() };
info.cbSize = std::mem::size_of::<MENUITEMINFOW>() as _;
info.fMask = MIIM_STATE;
unsafe { GetMenuItemInfoW(self.parent_hmenu, self.id as _, false.into(), &mut info) };
(info.fState & MFS_DISABLED) == 0
} }
pub fn set_enabled(&mut self, enabled: bool) { pub fn set_enabled(&mut self, enabled: bool) {
self.enabled = enabled;
unsafe { unsafe {
EnableMenuItem( EnableMenuItem(
self.parent_hmenu, self.parent_hmenu,

View file

@ -29,3 +29,10 @@ pub fn encode_wide(string: impl AsRef<std::ffi::OsStr>) -> Vec<u16> {
pub fn LOWORD(dword: u32) -> u16 { pub fn LOWORD(dword: u32) -> u16 {
(dword & 0xFFFF) as u16 (dword & 0xFFFF) as u16
} }
#[cfg(target_os = "windows")]
pub fn wchar_ptr_to_string(wchar: windows_sys::core::PWSTR) -> String {
let len = unsafe { windows_sys::Win32::Globalization::lstrlenW(wchar) } as usize;
let wchar_slice = unsafe { std::slice::from_raw_parts(wchar, len) };
String::from_utf16_lossy(wchar_slice)
}