Skip to content

Commit 888756d

Browse files
committed
Fix high DPI issues
1 parent 6a70fca commit 888756d

File tree

2 files changed

+45
-37
lines changed

2 files changed

+45
-37
lines changed

native-windows-gui/src/resources/image_list.rs

+11-8
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
1+
use std::ptr;
2+
13
use winapi::um::commctrl::{HIMAGELIST, ImageList_AddMasked};
24
use winapi::shared::windef::{HICON, HBITMAP};
5+
36
use crate::{Bitmap, Icon, NwgError};
4-
use std::ptr;
7+
use crate::win32::high_dpi;
58

69

710
const NOT_BOUND: &'static str = "ImageList is not yet bound to a winapi object";
@@ -12,7 +15,7 @@ Image lists are used in controls such as tabs container and tree view in order t
1215
1316
There are two kinds of image list in Winapi: masked. This is a wrapper over the masked type.
1417
15-
Image list and the method that use them in controls are behind the "image-list" feature.
18+
Image list and the method that use them in controls are behind the "image-list" feature.
1619
1720
**Builder parameters:**
1821
* `size`: The size size of the images in the image list. Default `(32, 32)`
@@ -55,7 +58,7 @@ impl ImageList {
5558
let mut size = (0, 0);
5659
unsafe { ImageList_GetIconSize(self.handle, &mut size.0, &mut size.1); }
5760

58-
size
61+
unsafe { high_dpi::physical_to_logical(size.0, size.1) }
5962
}
6063

6164
/// Sets the size of the image list. This clears all current image data.
@@ -64,7 +67,7 @@ impl ImageList {
6467

6568
if self.handle.is_null() { panic!("{}", NOT_BOUND); }
6669

67-
let (w, h) = size;
70+
let (w, h) = unsafe { high_dpi::logical_to_physical(size.0, size.1) };
6871
unsafe { ImageList_SetIconSize(self.handle, w, h); }
6972
}
7073

@@ -116,7 +119,7 @@ impl ImageList {
116119
unsafe {
117120
let mut info: ICONINFO = ::std::mem::zeroed();
118121
GetIconInfo(icon.handle as _, &mut info);
119-
122+
120123
let i = ImageList_AddMasked(self.handle, info.hbmColor, 0);
121124

122125
DeleteObject(info.hbmMask as _);
@@ -165,7 +168,7 @@ impl ImageList {
165168

166169
if self.handle.is_null() { panic!("{}", NOT_BOUND); }
167170
if bitmap.handle.is_null() { panic!("Bitmap was not initialized"); }
168-
171+
169172
unsafe { ImageList_Replace(self.handle, index, bitmap.handle as HBITMAP, ptr::null_mut()); }
170173
}
171174

@@ -236,7 +239,7 @@ impl ImageListBuilder {
236239
use winapi::um::commctrl::{ImageList_Create, ILC_COLOR32, ILC_MASK};
237240

238241
unsafe {
239-
let (w, h) = self.size;
242+
let (w, h) = high_dpi::logical_to_physical(self.size.0, self.size.1);
240243
let handle = ImageList_Create(w, h, ILC_COLOR32 | ILC_MASK, self.initial, self.grow);
241244
if handle.is_null() {
242245
return Err(NwgError::resource_create("Failed to create image list"));
@@ -245,7 +248,7 @@ impl ImageListBuilder {
245248
list.handle = handle;
246249
list.owned = true;
247250
}
248-
251+
249252
Ok(())
250253
}
251254

native-windows-gui/src/win32/resources_helper.rs

+34-29
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use winapi::ctypes::c_int;
33
use winapi::um::winnt::HANDLE;
44

55
use crate::resources::OemImage;
6+
use crate::win32::high_dpi;
67
use super::base_helper::{get_system_error, to_utf16};
78

89
#[allow(unused_imports)] use std::{ptr, mem};
@@ -25,23 +26,23 @@ pub fn is_bitmap(handle: HBITMAP) -> bool {
2526

2627
pub fn destroy_icon(icon: HANDLE) {
2728
unsafe { winapi::um::winuser::DestroyIcon(icon as _); }
28-
}
29+
}
2930

3031
pub fn destroy_cursor(cursor: HANDLE) {
3132
unsafe { winapi::um::winuser::DestroyCursor(cursor as _); }
32-
}
33+
}
3334

3435
pub fn destroy_obj(obj: HANDLE) {
3536
unsafe { winapi::um::wingdi::DeleteObject(obj as _); }
36-
}
37+
}
3738

3839
pub unsafe fn build_font(
3940
size: i32,
4041
weight: u32,
4142
style: [bool; 3],
4243
family_name: Option<&str>,
43-
) -> Result<HFONT, NwgError>
44-
{
44+
) -> Result<HFONT, NwgError>
45+
{
4546
use winapi::um::wingdi::{DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, CLEARTYPE_QUALITY, VARIABLE_PITCH};
4647
use winapi::um::wingdi::CreateFontW;
4748
let [use_italic, use_underline, use_strikeout] = style;
@@ -56,7 +57,7 @@ pub unsafe fn build_font(
5657
family_name_ptr = ptr::null();
5758
}
5859

59-
let (size, _) = super::high_dpi::logical_to_physical(size as i32, 0);
60+
let (size, _) = high_dpi::logical_to_physical(size as i32, 0);
6061

6162
let handle = CreateFontW(
6263
size as c_int, // nHeight
@@ -95,8 +96,9 @@ pub unsafe fn build_image<'a>(
9596

9697
let filepath = to_utf16(source);
9798
let (width, height) = size.unwrap_or((0,0));
99+
let (width, height) = high_dpi::logical_to_physical(width as i32, height as i32);
98100

99-
let mut handle = LoadImageW(ptr::null_mut(), filepath.as_ptr(), image_type, width as i32, height as i32, LR_LOADFROMFILE);
101+
let mut handle = LoadImageW(ptr::null_mut(), filepath.as_ptr(), image_type, width, height, LR_LOADFROMFILE);
100102
if handle.is_null() {
101103
let (code, _) = get_system_error();
102104
if code == 2 && !strict {
@@ -116,7 +118,7 @@ pub unsafe fn build_image<'a>(
116118
},
117119
_ => { unreachable!() }
118120
};
119-
121+
120122
}
121123
}
122124

@@ -138,15 +140,16 @@ pub unsafe fn build_image_decoder<'a>(
138140
use crate::ImageDecoder;
139141

140142
let decoder = ImageDecoder::new()?;
141-
143+
142144
let mut image_frame = decoder
143145
.from_filename(source)?
144146
.frame(0)?;
145147

146148
if let Some((width, height)) = size {
147-
image_frame = decoder.resize_image(&image_frame, [width, height])?;
149+
let (width, height) = high_dpi::logical_to_physical(width as i32, height as i32);
150+
image_frame = decoder.resize_image(&image_frame, [width as u32, height as u32])?;
148151
}
149-
152+
150153
let mut bitmap = image_frame.as_bitmap()?;
151154

152155
bitmap.owned = false;
@@ -163,15 +166,16 @@ pub unsafe fn build_image_decoder_from_memory<'a>(
163166
use crate::ImageDecoder;
164167

165168
let decoder = ImageDecoder::new()?;
166-
169+
167170
let mut image_frame = decoder
168171
.from_stream(src)?
169172
.frame(0)?;
170173

171174
if let Some((width, height)) = size {
172-
image_frame = decoder.resize_image(&image_frame, [width, height])?;
175+
let (width, height) = high_dpi::logical_to_physical(width as i32, height as i32);
176+
image_frame = decoder.resize_image(&image_frame, [width as u32, height as u32])?;
173177
}
174-
178+
175179
let mut bitmap = image_frame.as_bitmap()?;
176180

177181
bitmap.owned = false;
@@ -182,13 +186,14 @@ pub unsafe fn build_image_decoder_from_memory<'a>(
182186
pub unsafe fn build_oem_image(
183187
source: OemImage,
184188
size: Option<(u32, u32)>,
185-
) -> Result<HANDLE, NwgError>
189+
) -> Result<HANDLE, NwgError>
186190
{
187191
use winapi::um::winuser::{LR_DEFAULTSIZE, LR_SHARED, IMAGE_ICON, IMAGE_CURSOR, IMAGE_BITMAP};
188192
use winapi::um::winuser::LoadImageW;
189193
use winapi::shared::ntdef::LPCWSTR;
190194

191195
let (width, height) = size.unwrap_or((0,0));
196+
let (width, height) = high_dpi::logical_to_physical(width as i32, height as i32);
192197

193198
let (c_res_type, res_identifier) = match source {
194199
OemImage::Bitmap(b) => {
@@ -208,7 +213,7 @@ pub unsafe fn build_oem_image(
208213
LR_SHARED
209214
};
210215

211-
let handle = LoadImageW(ptr::null_mut(), res_identifier, c_res_type, width as i32, height as i32, flags);
216+
let handle = LoadImageW(ptr::null_mut(), res_identifier, c_res_type, width, height, flags);
212217

213218
if handle.is_null() {
214219
Err( NwgError::resource_create("Failed to create image from system resource") )
@@ -218,7 +223,7 @@ pub unsafe fn build_oem_image(
218223
}
219224

220225

221-
/**
226+
/**
222227
Create a bitmap from memory. Only supports bitmap. Enable the `image-decoder` to load more image type from memory
223228
The memory must contain the whole file (including the bitmap header).
224229
*/
@@ -256,7 +261,7 @@ pub unsafe fn bitmap_from_memory(source: &[u8]) -> Result<HANDLE, NwgError> {
256261

257262
let header = BITMAPINFOHEADER {
258263
biSize: mem::size_of::<BITMAPINFOHEADER>() as DWORD,
259-
biWidth: w as LONG, biHeight: h as LONG,
264+
biWidth: w as LONG, biHeight: h as LONG,
260265
biPlanes: 1, biBitCount: 24, biCompression: BI_RGB,
261266
biSizeImage: (w * h * 3) as u32,
262267
biXPelsPerMeter: 0, biYPelsPerMeter: 0,
@@ -278,7 +283,7 @@ pub unsafe fn bitmap_from_memory(source: &[u8]) -> Result<HANDLE, NwgError> {
278283
return Ok(bitmap as HANDLE);
279284
}
280285

281-
/**
286+
/**
282287
Create a bitmap from memory. The source can be any image type supported by the windows imaging component.
283288
The memory must contain the whole file (including the file header).
284289
*/
@@ -343,7 +348,7 @@ pub unsafe fn create_file_dialog<'a, 'b>(
343348
multiselect: bool,
344349
default_folder: Option<String>,
345350
filters: Option<String>
346-
) -> Result<*mut IFileDialog, NwgError>
351+
) -> Result<*mut IFileDialog, NwgError>
347352
{
348353
use winapi::um::shobjidl_core::{CLSID_FileSaveDialog, CLSID_FileOpenDialog};
349354
use winapi::um::shobjidl::{FOS_PICKFOLDERS, FOS_ALLOWMULTISELECT, FOS_FORCEFILESYSTEM};
@@ -366,18 +371,18 @@ pub unsafe fn create_file_dialog<'a, 'b>(
366371

367372
// Set dialog options
368373
if file_dialog.GetOptions(&mut flags) != S_OK {
369-
file_dialog.Release();
374+
file_dialog.Release();
370375
return Err(NwgError::file_dialog("Filedialog creation failed"));
371376
}
372-
377+
373378
let use_dir = if action == FileDialogAction::OpenDirectory { FOS_PICKFOLDERS } else { 0 };
374379
let multiselect = if multiselect { FOS_ALLOWMULTISELECT } else { 0 };
375380
if file_dialog.SetOptions(flags | FOS_FORCEFILESYSTEM | use_dir | multiselect) != S_OK {
376381
file_dialog.Release();
377382
return Err(NwgError::file_dialog("Filedialog creation failed"));
378383
}
379384

380-
385+
381386
// Set the default folder
382387
match &default_folder {
383388
&Some(ref f) => match file_dialog_set_default_folder(file_dialog, f) {
@@ -424,7 +429,7 @@ pub unsafe fn file_dialog_set_default_folder<'a>(dialog: &mut IFileDialog, folde
424429

425430
let shellitem = &mut *shellitem;
426431
let mut file_properties: SFGAOF = 0;
427-
432+
428433
let results = shellitem.GetAttributes(SFGAO_FOLDER, &mut file_properties);
429434

430435
if results != S_OK && results != S_FALSE {
@@ -466,7 +471,7 @@ pub unsafe fn file_dialog_set_filters<'a>(dialog: &mut IFileDialog, filters: &'a
466471

467472
let (_name, _filter) = f.split_at(end.unwrap());
468473
let (name, filter) = (to_utf16(_name), to_utf16(&_filter[1.._filter.len()-1]));
469-
474+
470475
raw_filters.push(COMDLG_FILTERSPEC{ pszName: name.as_ptr(), pszSpec: filter.as_ptr() });
471476
keep_alive.push( (name, filter) );
472477
}
@@ -483,7 +488,7 @@ pub unsafe fn file_dialog_set_filters<'a>(dialog: &mut IFileDialog, filters: &'a
483488
#[cfg(feature = "file-dialog")]
484489
pub unsafe fn filedialog_get_item(dialog: &mut IFileDialog) -> Result<OsString, NwgError> {
485490
use winapi::shared::winerror::S_OK;
486-
491+
487492
let mut _item: *mut IShellItem = ptr::null_mut();
488493

489494
if dialog.GetResult(&mut _item) != S_OK {
@@ -500,7 +505,7 @@ pub unsafe fn filedialog_get_item(dialog: &mut IFileDialog) -> Result<OsString,
500505
pub unsafe fn filedialog_get_items(dialog: &mut IFileOpenDialog) -> Result<Vec<OsString>, NwgError> {
501506
use winapi::um::shobjidl::IShellItemArray;
502507
use winapi::shared::{winerror::S_OK, minwindef::DWORD};
503-
508+
504509
let mut _item: *mut IShellItem = ptr::null_mut();
505510
let mut _items: *mut IShellItemArray = ptr::null_mut();
506511

@@ -511,7 +516,7 @@ pub unsafe fn filedialog_get_items(dialog: &mut IFileOpenDialog) -> Result<Vec<O
511516
let items = &mut *_items;
512517
let mut count: DWORD = 0;
513518
items.GetCount(&mut count);
514-
519+
515520
let mut item_names: Vec<OsString> = Vec::with_capacity(count as usize);
516521
for i in 0..count {
517522
items.GetItemAt(i, &mut _item);
@@ -560,7 +565,7 @@ pub unsafe fn file_dialog_options(dialog: &mut IFileDialog) -> Result<u32, NwgEr
560565
#[cfg(feature = "file-dialog")]
561566
pub unsafe fn toggle_dialog_flags(dialog: &mut IFileDialog, flag: u32, enabled: bool) -> Result<(), NwgError> {
562567
use winapi::shared::winerror::S_OK;
563-
568+
564569
let mut flags = file_dialog_options(dialog)?;
565570
flags = match enabled {
566571
true => flags | flag,

0 commit comments

Comments
 (0)