DPI and icons

240 views
Skip to first unread message

QuentinC

unread,
May 29, 2021, 4:15:03 AM5/29/21
to wx-u...@googlegroups.com
Hello,

An user of my app reported that the main frame and all the interface of
my app (all controls/widgets and their contents) appear blured under
windows 10.

In order to fix the blur effect and be able to work normally with my
app, he has to change DPI settings as explained by Microsoft here:
https://support.microsoft.com/en-us/windows/make-older-apps-or-programs-compatible-with-windows-10-783d6dd7-b439-bdb0-0490-54eea0f45938

When he changes his DPI settings, he also reports that the icon of my
app disappears.
* The frame icon is replaced by an icon representing three colored
blocks. That's probably some windows or WX default, as I don't provide
such an icon myself.
* The taskbar icon in notification zone is replaced by nothing, i.e.
blank/transparent space

The computer where he observed the problem was:
HP laptop with windows 10, Processor intel core i5 (dualcore,
hyperthreading, max frequency 2,7 GHz), 8 GB RAM, SSD+HDD, 15,6''
screen with max resolution 1920 x 1080, scaling 140%

He also tried on a older computer and he doesn't have the problem on it:
Toshiba laptop with win10, Processor intel pentium (dualcore, 2,0 GHz),
4 GB RAM, HDD only, 15,6'' screen with max resolution 1366 x 768, no scaling

Can/should I do something, and if yes, what, so that:
1. He doesn't have to change DPI settings
2. Icons don't disappear when DPI settings are set

I don't know well where the problem is in the code.

Here's how I set the frame icon, in main window's constructor:

class MainWindow: wxFrame { ... }

MainWindow::MainWindow (): wxFrame(...) {
...
SetIcon(wxIcon("logo.ico", wxBITMAP_TYPE_ICO, 32, 32));
...
}

And here where I similarely set it for the taskbar icon:

class TrayIcon: wxTaskBarIcon { ... };

void TrayIcon::Install () {
...
SetIcon(wxIcon("logo.ico", wxBITMAP_TYPE_ICO, 32, 32), wxGetApp()
.mainWindow ->GetTitle());
...
}

Of course, the named logo.ico file is indeed present in the same
directory as the executable and WXWidgets' DLLs.
That icon appears correctly when DPI settings aren't set, so it's
correctly loaded.

I also have added a resource file .rc in my project, which includes
WXWidgets resources:
#include "wx/msw/wx.rc"
Which, among others, includes an XML manifest file that I took
unmodified from WXWidgets.

What am I doing wrong ?
Do I have forgotten something ?

Thank you for your answers.

Hector

unread,
May 29, 2021, 7:43:24 AM5/29/21
to wx-users

QuentinC

unread,
May 30, 2021, 2:10:02 AM5/30/21
to wx-u...@googlegroups.com
Hello,

> Your manifest file must include DPI Awareness.

Don't WXWidgets automatically add it by default ?

Anyway, I have tried to force it by defining myself in the resource
file. I don't know if it's a good thing or not, or I'm supposed, or not
supposed to do it.
#define wxUSE_RC_MANIFEST 1
#define wxUSE_DPI_AWARE_MANIFEST 2

I see in wx.rc that there are in fact two possibilities, I can set
wxUSE_DPI_AWARE_MANIFEST to 1 or 2.

What's the difference between the two ?
It seems that the second only works for windows 10. Should I use this
one as it's the most recent ? Does it mean that my app won't work in
windows 7 ?

Is there consequences when setting DPI awareness ? Do I need to change
something in my C++ code or be careful about certain things ?

I must admit, in fact I don't understand at all what it is supposed to
change. The problem is that I certainly can't perceive what it changes
myself, as I'm blind.

Hector

unread,
May 30, 2021, 3:47:29 AM5/30/21
to wx-users
I don't know if it can be done from the resources file. Personally I'm using Visual Studio, I created my own manifest file and I ask Visual Studio to use it.

On a normal screen, having DPI awareness enabled changes nothing. But if the screen has high DPI and you didn't enable  DPI awareness, Windows will take your interface, drawn at normal DPI, and magnify it to the bigger size. As a result, everything and especially the text will look blurry (because magnification only did the best it could).

You really need to test on a high DPI screen to grasp the difference.

PB

unread,
May 30, 2021, 4:46:52 AM5/30/21
to wx-users
Hi,

regarding values used for wxUSE_DPI_AWARE_MANIFEST define: 1 means System DPI Awareness is used while 2 states that Per Monitor V2 DPI Awareness is used.The meaning of the two is explained in the Microsoft documentation: https://docs.microsoft.com/en-us/windows/win32/hidpi/high-dpi-desktop-application-development-on-windows  There is also wxWidgets HiDPI guide: https://docs.wxwidgets.org/trunk/overview_high_dpi.html

Be aware that there are still bugs when using Per Monitor V2 DPI Awareness, see https://trac.wxwidgets.org/ticket/18474

As for icons, IMO one should avoid SetIcon(). Usually, a Windows icon (.ico)  contains bitmaps at several sizes (resolutions, e.g., 16x16, 32x32...) which will allow Windows to pick the most suitably sized bitmap for a given scenario. Such icons should be loaded with wxIconBundle() and assigned to a top level window (e.g., wxFrame) with SetIcons(). This is unfortunately not possible with platform-independent wxICON() macro.

Regards,
PB

QuentinC

unread,
May 30, 2021, 12:39:57 PM5/30/21
to wx-u...@googlegroups.com
Hello,

Thank you for the links, I'll have a look at them and try to fix what
has to be fixed in my app.

AS far as I understand, fortunately, I have quite few places where I
specify directly sizes in pixels. I mostly rely entirely on sizers to
place my controls on screen.

Just a small question: does declaring DPI awareness changes something
for the values returned by
wxSystemSettings::GetMetric(wxSYS_SCREEN_X)
and
wxSystemSettings::GetMetric(wxSYS_SCREEN_Y)
?
I use them to set an initial size for the main frame so that it occupies
80% of the screen by default.


PB> As for icons, IMO one should avoid SetIcon(). Usually, a Windows
icon (.ico) contains bitmaps at several sizes (resolutions, e.g.,
16x16, 32x32...) which will allow Windows to pick the most suitably
sized bitmap for a given scenario. Such icons should be loaded with
wxIconBundle() and assigned to a top level
window (e.g., wxFrame) with SetIcons(). This is unfortunately not
possible with platform-independent wxICON() macro.

What should I use instead ?

The icon for the main frame is originally an SVG file. I converted it to
32x32 ICO using an online converter. AS far as I understand, WX can't
load an SVG directly (theree's no image loader for SVG, is there?).
Would have it been better to convert it into another format e.g. BMP or
PNG ?

Thank you for your answers.
Regards.

PB

unread,
May 30, 2021, 12:59:32 PM5/30/21
to wx-users
Hi,

On Sunday, May 30, 2021 at 6:39:57 PM UTC+2 webm...@quentinc.net wrote:
> Just a small question: does declaring DPI awareness changes something for the values returned by wxSystemSettings::GetMetric()

I believe it does.  For an unaware application, it gets fake "standard" size, for the system aware one, it gets system size and for Per Monitor V2 aware it gets the correct size depending on the monitor the window is on. That is why in recent wxWidgets versions you can pass a wxWindow pointer to GetMetric().

Not sure if this would be of any use for you, but I have wrote a utility class which allows inspecting various system settings values, of course it needs to be built as DPI aware: https://github.com/PBfordev/wxsysinfoframe


On Sunday, May 30, 2021 at 6:39:57 PM UTC+2 webm...@quentinc.net wrote:
The icon for the main frame is originally an SVG file. I converted it to
32x32 ICO using an online converter. AS far as I understand, WX can't
load an SVG directly (theree's no image loader for SVG, is there?).
Would have it been better to convert it into another format e.g. BMP or
PNG ?

As I wrote before, the Windows icon format allows storing multiple resolution bitmaps in a single file. wxWidgets itself does not allow converting SVG to bitmap at runtime. So you should convert the SVG to several bitmaps at multiple resolutions using some tool , e.g. at least 16x16, 32x32, 48x48, and 64x64 and save it as a single icon file (which your probably also embed in a resource and use for the application icon itself). This is useful not only for HiDPI but also for general situations where a different size bitmaps can be used, e.g. icon displayed in a window caption vs icon displayed in a taskbar for a running application.

Regards,
PB
Reply all
Reply to author
Forward
0 new messages