mirror of
https://github.com/rust-windowing/winit.git
synced 2026-09-01 06:10:07 -04:00
Windows: add IconExtWindows::from_resource_name (#4137)
This commit is contained in:
@@ -39,3 +39,7 @@ The migration guide could reference other migration examples in the current
|
|||||||
changelog entry.
|
changelog entry.
|
||||||
|
|
||||||
## Unreleased
|
## Unreleased
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- On Windows, add `IconExtWindows::from_resource_name`.
|
||||||
|
|||||||
@@ -660,6 +660,17 @@ impl DeviceIdExtWindows for DeviceId {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Additional methods on `Icon` that are specific to Windows.
|
/// Additional methods on `Icon` that are specific to Windows.
|
||||||
|
///
|
||||||
|
/// Windows icons can be created from files, or from the [`embedded resources`](https://learn.microsoft.com/en-us/windows/win32/menurc/about-resource-files).
|
||||||
|
///
|
||||||
|
/// The `ICON` resource definition statement use the following syntax:
|
||||||
|
/// ```rc
|
||||||
|
/// nameID ICON filename
|
||||||
|
/// ```
|
||||||
|
/// `nameID` is a unique name or a 16-bit unsigned integer value identifying the resource,
|
||||||
|
/// `filename` is the name of the file that contains the resource.
|
||||||
|
///
|
||||||
|
/// More information about the `ICON` resource can be found at [`Microsoft Learn`](https://learn.microsoft.com/en-us/windows/win32/menurc/icon-resource) portal.
|
||||||
pub trait IconExtWindows: Sized {
|
pub trait IconExtWindows: Sized {
|
||||||
/// Create an icon from a file path.
|
/// Create an icon from a file path.
|
||||||
///
|
///
|
||||||
@@ -671,7 +682,12 @@ pub trait IconExtWindows: Sized {
|
|||||||
fn from_path<P: AsRef<Path>>(path: P, size: Option<PhysicalSize<u32>>)
|
fn from_path<P: AsRef<Path>>(path: P, size: Option<PhysicalSize<u32>>)
|
||||||
-> Result<Self, BadIcon>;
|
-> Result<Self, BadIcon>;
|
||||||
|
|
||||||
/// Create an icon from a resource embedded in this executable or library.
|
/// Create an icon from a resource embedded in this executable or library by its ordinal id.
|
||||||
|
///
|
||||||
|
/// The valid `ordinal` values range from 1 to [`u16::MAX`] (inclusive). The value `0` is an
|
||||||
|
/// invalid ordinal id, but it can be used with [`from_resource_name`] as `"0"`.
|
||||||
|
///
|
||||||
|
/// [`from_resource_name`]: IconExtWindows::from_resource_name
|
||||||
///
|
///
|
||||||
/// Specify `size` to load a specific icon size from the file, or `None` to load the default
|
/// Specify `size` to load a specific icon size from the file, or `None` to load the default
|
||||||
/// icon size from the file.
|
/// icon size from the file.
|
||||||
@@ -679,6 +695,55 @@ pub trait IconExtWindows: Sized {
|
|||||||
/// In cases where the specified size does not exist in the file, Windows may perform scaling
|
/// In cases where the specified size does not exist in the file, Windows may perform scaling
|
||||||
/// to get an icon of the desired size.
|
/// to get an icon of the desired size.
|
||||||
fn from_resource(ordinal: u16, size: Option<PhysicalSize<u32>>) -> Result<Self, BadIcon>;
|
fn from_resource(ordinal: u16, size: Option<PhysicalSize<u32>>) -> Result<Self, BadIcon>;
|
||||||
|
|
||||||
|
/// Create an icon from a resource embedded in this executable or library by its name.
|
||||||
|
///
|
||||||
|
/// Specify `size` to load a specific icon size from the file, or `None` to load the default
|
||||||
|
/// icon size from the file.
|
||||||
|
///
|
||||||
|
/// In cases where the specified size does not exist in the file, Windows may perform scaling
|
||||||
|
/// to get an icon of the desired size.
|
||||||
|
///
|
||||||
|
/// # Notes
|
||||||
|
///
|
||||||
|
/// Consider the following resource definition statements:
|
||||||
|
/// ```rc
|
||||||
|
/// app ICON "app.ico"
|
||||||
|
/// 1 ICON "a.ico"
|
||||||
|
/// 0027 ICON "custom.ico"
|
||||||
|
/// 0 ICON "alt.ico"
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// Due to some internal implementation details of the resource embedding/loading process on
|
||||||
|
/// Windows platform, strings that can be interpreted as 16-bit unsigned integers (`"1"`,
|
||||||
|
/// `"002"`, etc.) cannot be used as valid resource names, and instead should be passed into
|
||||||
|
/// [`from_resource`]:
|
||||||
|
///
|
||||||
|
/// [`from_resource`]: IconExtWindows::from_resource
|
||||||
|
///
|
||||||
|
/// ```rust,no_run
|
||||||
|
/// use winit::platform::windows::IconExtWindows;
|
||||||
|
/// use winit::window::Icon;
|
||||||
|
///
|
||||||
|
/// assert!(Icon::from_resource_name("app", None).is_ok());
|
||||||
|
/// assert!(Icon::from_resource(1, None).is_ok());
|
||||||
|
/// assert!(Icon::from_resource(27, None).is_ok());
|
||||||
|
/// assert!(Icon::from_resource_name("27", None).is_err());
|
||||||
|
/// assert!(Icon::from_resource_name("0027", None).is_err());
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// While `0` cannot be used as an ordinal id (see [`from_resource`]), it can be used as a
|
||||||
|
/// name:
|
||||||
|
///
|
||||||
|
/// [`from_resource`]: IconExtWindows::from_resource
|
||||||
|
///
|
||||||
|
/// ```rust,no_run
|
||||||
|
/// # use winit::platform::windows::IconExtWindows;
|
||||||
|
/// # use winit::window::Icon;
|
||||||
|
/// assert!(Icon::from_resource_name("0", None).is_ok());
|
||||||
|
/// assert!(Icon::from_resource(0, None).is_err());
|
||||||
|
/// ```
|
||||||
|
fn from_resource_name(name: &str, size: Option<PhysicalSize<u32>>) -> Result<Self, BadIcon>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl IconExtWindows for Icon {
|
impl IconExtWindows for Icon {
|
||||||
@@ -694,4 +759,9 @@ impl IconExtWindows for Icon {
|
|||||||
let win_icon = crate::platform_impl::WinIcon::from_resource(ordinal, size)?;
|
let win_icon = crate::platform_impl::WinIcon::from_resource(ordinal, size)?;
|
||||||
Ok(Icon { inner: win_icon })
|
Ok(Icon { inner: win_icon })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn from_resource_name(name: &str, size: Option<PhysicalSize<u32>>) -> Result<Self, BadIcon> {
|
||||||
|
let win_icon = crate::platform_impl::WinIcon::from_resource_name(name, size)?;
|
||||||
|
Ok(Icon { inner: win_icon })
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -109,13 +109,28 @@ impl WinIcon {
|
|||||||
pub fn from_resource(
|
pub fn from_resource(
|
||||||
resource_id: u16,
|
resource_id: u16,
|
||||||
size: Option<PhysicalSize<u32>>,
|
size: Option<PhysicalSize<u32>>,
|
||||||
|
) -> Result<Self, BadIcon> {
|
||||||
|
Self::from_resource_ptr(resource_id as PCWSTR, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn from_resource_name(
|
||||||
|
resource_name: &str,
|
||||||
|
size: Option<PhysicalSize<u32>>,
|
||||||
|
) -> Result<Self, BadIcon> {
|
||||||
|
let wide_name = util::encode_wide(resource_name);
|
||||||
|
Self::from_resource_ptr(wide_name.as_ptr(), size)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn from_resource_ptr(
|
||||||
|
resource: PCWSTR,
|
||||||
|
size: Option<PhysicalSize<u32>>,
|
||||||
) -> Result<Self, BadIcon> {
|
) -> Result<Self, BadIcon> {
|
||||||
// width / height of 0 along with LR_DEFAULTSIZE tells windows to load the default icon size
|
// width / height of 0 along with LR_DEFAULTSIZE tells windows to load the default icon size
|
||||||
let (width, height) = size.map(Into::into).unwrap_or((0, 0));
|
let (width, height) = size.map(Into::into).unwrap_or((0, 0));
|
||||||
let handle = unsafe {
|
let handle = unsafe {
|
||||||
LoadImageW(
|
LoadImageW(
|
||||||
util::get_instance_handle(),
|
util::get_instance_handle(),
|
||||||
resource_id as PCWSTR,
|
resource,
|
||||||
IMAGE_ICON,
|
IMAGE_ICON,
|
||||||
width,
|
width,
|
||||||
height,
|
height,
|
||||||
|
|||||||
Reference in New Issue
Block a user