Page 1 of 4

How I make DPI-aware apps

Posted: Sun Mar 11, 2018 2:34 am
by Dude
In response to another post I saw about cropped text in gadgets, here is how I personally code my apps to be DPI-aware. There are other techniques but they seem to have too much code... when just a simple multiplier works great. I've seen dozens of screenshots of my apps on other people's PCs and websites, and the gadgets are always perfect, so I know this works. :) I test my apps on two displays before release to the public: 1280 x 1024 resolution at 100% DPI (Small Fonts) with Aero theme and default colors; and 1024 x 768 resolution at 150% DPI (Large Fonts) with Basic theme and alternate color scheme.

In this day and age you simply CANNOT hard-code your X/Y/W/H parameters (well, unless your apps are for your own personal use). For release to the public, they must be DPI-aware to ensure correct display with no cropping. It's unprofessional if you don't, and yes, people still do use 1024 x 768 resolution with Large Fonts (I have several customers with that setup).

So, here's how I do it (it's really easy). I simply use a global variable called "dpi" which I multiply all my X,Y,W,H parameters with. As you can see from the screenshots below, it works great! 8)

Code: Select all

Global dpi.d=GetDeviceCaps_(GetDC_(0),#LOGPIXELSX)/100 ; The magic!

OpenWindow(0,200,200,180*dpi,100*dpi,"test",#PB_Window_SystemMenu)

x=10*dpi
w=155*dpi
h=20*dpi

TextGadget(1,x,10*dpi,w,h,"This is text that fills the gadget",#PB_Text_Border)

StringGadget(2,x,40*dpi,w,h,"Another small test of fitted text")

ButtonGadget(3,x,70*dpi,w,h,"And last example of exact text")

Repeat : Until WaitWindowEvent()=#PB_Event_CloseWindow
The DPI-aware results of the above code:

Image

Now, compare that to hard-coded X,Y,W,H parameters without any DPI multiplication:

Code: Select all

; No DPI multiplication for X/Y/W/H parameters. :(

OpenWindow(0,200,200,180,100,"test",#PB_Window_SystemMenu)

x=10
w=155
h=20

TextGadget(1,x,10,w,h,"This is text that fills the gadget",#PB_Text_Border)

StringGadget(2,x,40,w,h,"Another small test of fitted text")

ButtonGadget(3,x,70,w,h,"And last example of exact text")

Repeat : Until WaitWindowEvent()=#PB_Event_CloseWindow
The results without any DPI multiplication:

Image

The images speak for themselves. :)

Re: How I make DPI-aware apps

Posted: Sun Mar 11, 2018 6:40 am
by VB6_to_PBx
Dude ,

thank you very much for this example

Re: How I make DPI-aware apps

Posted: Sun Mar 11, 2018 7:43 am
by davido
@Dude,
Excellent!
Thank you for sharing.

Re: How I make DPI-aware apps

Posted: Sun Mar 11, 2018 8:09 am
by HanPBF
Thanks a lot for the code!

Re: How I make DPI-aware apps

Posted: Sun Mar 11, 2018 10:13 pm
by davido
Hm... I wonder if anyone knows of similar methods for the other two OS's?

Re: How I make DPI-aware apps

Posted: Mon Mar 12, 2018 11:37 am
by Ulix
Translation by google!

Hello everyone !

Very interesting as a code, if I understand correctly if it is to obtain the same dimension (windows and gadgets)
whatever the resolution of the screen? or / and the setting of OS!

What is the equivalent of the instruction:

Code: Select all

Global dpi.d = GetDeviceCaps_ (GetDC_ (0), # LOGPIXELSX) / 100; The magic!
for other OS (Linux and Mac)?
The idea: Make it a multi-platform feature! :lol:

Can we use the dpi to size the fonts?

I will follow this post with interest

Ulix :wink:

Re: How I make DPI-aware apps

Posted: Mon Mar 12, 2018 3:06 pm
by bbanelli
Hi Dude,

I think there's more to it. Process Explorer states application as DPI unaware, primarily because you didn't use SetProcessDpiAwareness().

Image

Furthermore, this might not work properly on Windows 8.1+ where you can pick different DPI's in multimonitor environment. Since documentation for GetDeviceCaps() (which seems to be rather antique function) states the following:
LOGPIXELSX
Number of pixels per logical inch along the screen width. In a system with multiple display monitors, this value is the same for all monitors.
Perhaps it would be more prudent to use GetDpiForMonitor() function on W8.1+?

Re: How I make DPI-aware apps

Posted: Mon Mar 12, 2018 6:35 pm
by Sicro
German forum thread (translated to english per google translate): Resource generator for manifests

Code: PureBasic-CodeArchive-Rebirth / PB-IDE-Tools / ResourceGeneratorForManifests

I don't know how well the manifest helps, but it has helped on the game named in the forum thread.

Re: How I make DPI-aware apps

Posted: Mon Mar 12, 2018 7:33 pm
by RASHAD
Hi Dude
It is not that easy mate :)
There are
1- Unaware
2- System aware (Thanks to Sicro) for his fantastic solution
3- Per-Monitor aware as (Explorer.exe) and that need to add a key to the registry corresponded to your application

And it maybe more difficult than that :P

Re: How I make DPI-aware apps

Posted: Mon Mar 12, 2018 8:38 pm
by Bitblazer
Dude wrote:In this day and age you simply CANNOT hard-code your X/Y/W/H parameters (well, unless your apps are for your own personal use). For release to the public, they must be DPI-aware to ensure correct display with no cropping. It's unprofessional if you don't, and yes, people still do use 1024 x 768 resolution with Large Fonts (I have several customers with that setup).

So, here's how I do it (it's really easy). I simply use a global variable called "dpi" which I multiply all my X,Y,W,H parameters with. As you can see from the screenshots below, it works great! 8)

Code: Select all

Global dpi.d=GetDeviceCaps_(GetDC_(0),#LOGPIXELSX)/100 ; The magic!

OpenWindow(0,200,200,180*dpi,100*dpi,"test",#PB_Window_SystemMenu)

x=10*dpi
w=155*dpi
h=20*dpi

TextGadget(1,x,10*dpi,w,h,"This is text that fills the gadget",#PB_Text_Border)

StringGadget(2,x,40*dpi,w,h,"Another small test of fitted text")

ButtonGadget(3,x,70*dpi,w,h,"And last example of exact text")

Repeat : Until WaitWindowEvent()=#PB_Event_CloseWindow
The DPI-aware results of the above code:

Image

Now, compare that to hard-coded X,Y,W,H parameters without any DPI multiplication:

Code: Select all

; No DPI multiplication for X/Y/W/H parameters. :(

OpenWindow(0,200,200,180,100,"test",#PB_Window_SystemMenu)

x=10
w=155
h=20

TextGadget(1,x,10,w,h,"This is text that fills the gadget",#PB_Text_Border)

StringGadget(2,x,40,w,h,"Another small test of fitted text")

ButtonGadget(3,x,70,w,h,"And last example of exact text")

Repeat : Until WaitWindowEvent()=#PB_Event_CloseWindow
The results without any DPI multiplication:

Image

The images speak for themselves. :)
You may even have multiple monitor setups with different aspect ratios. Some people use 6 Monitors in a 3 x 2 setup to simulate one giant resolution, others use a graphic card with a huge virtual resolution and use desktop tools like 360desktop to switch between workplaces on them, others use 2 monitors where one has a 4:3 aspect ratio to display a 3d viewport for example while working with their tools on a second monitor with 16:9 or 16:10 ratio and some even use monitors that display one or multiple A4 pages for desktop publishing for example. And to make the situation worse, some tools allow to seemlessly move windows between monitors of different aspect ratios by simply dragging and moving the window header.

So i would definately suggest to use a procedure call/macro and NOT a single fixed aspect ratio that's calculated during the start of an app. I suggest using something like DPI_X(X) and DPI_Y(Y) at least. Its not a perfect solution yet, but that way you can better adapt to a special case later. Look into manifests and resources about making windows aware about your applications "DPI awareness".

monitors
are
crazy
nowadays

multi monitor setups are common among gamers or desktop publishing people

Re: How I make DPI-aware apps

Posted: Mon Mar 12, 2018 10:17 pm
by Dude
Hmm, okay, so there may technically be more to it. But it's still better than simply hard-coding the X/Y/W/H, which is the PureBasic default that can't be relied on at all.

As I said in bold in my first post, seeing my product "in the wild" across many websites (reviews, etc) has not shown evidence of any issues. Oh well. Take it or leave it. :?

Re: How I make DPI-aware apps

Posted: Tue Mar 13, 2018 12:24 am
by Bitblazer
Dude wrote:Hmm, okay, so there may technically be more to it. But it's still better than simply hard-coding the X/Y/W/H, which is the PureBasic default that can't be relied on at all.

As I said in bold in my first post, seeing my product "in the wild" across many websites (reviews, etc) has not shown evidence of any issues. Oh well. Take it or leave it. :?
Your tip is very useful and covers probably 98% of the customer setups. Without it, its rather unrealistic nowadays due to the very different monitor resolutions. I just wanted to mention the insane special configurations that i witnessed so far since making my own apps "dpi aware" a few years ago. I still don't have a final solution which covers all special cases in a clean way. Calling a function instead of using a static dpi calculation makes it possible to refresh the window on demand (user key ALT-Plus or ALT-Minus or window movement across different DPI areas) and that has turned out to be quite convenient, that's all :)

DPI awareness is a requirement nowadays for nearly all kinds of software IMHO.

Re: How I make DPI-aware apps

Posted: Thu May 31, 2018 1:38 pm
by Dude
Okay, now that PureBasic v5.70 Beta 1 is out, with DPI awareness built-in, I don't understand why my code in my first post doesn't make my window be DPI aware? Maybe I'm not understanding what DPI awareness is? I thought it was to make your apps look the same no matter what system font size is in use, resolution, etc?

So when I enable DPI awareness in v5.70 and run my code (from the first post), it looks like this (wrong):

Image

But if I use my multiplication trick instead, with DPI awareness off, my code looks like this (correct):

Image

Am I doing something wrong with v5.70's DPI awareness? :shock:

Re: How I make DPI-aware apps

Posted: Thu May 31, 2018 2:50 pm
by chi
Same here! The built-in solution seems to enlarge some fonts a bit too much

Re: How I make DPI-aware apps

Posted: Wed Jan 16, 2019 5:23 pm
by chi
Nothing changed in the final release of PB 5.70 (unfortunately). The text with built-in DPI awareness is still too big :cry:

Top window without DPI awareness, bottom window with built-in DPI awareness (both 150%). Though MS is stretching the text of the top window, which makes it blurry, it still fits perfectly into the enlarged gadgets. With built-in DPI the text of the bottom window is crisp again, but doesn't fit anymore.
That's a problem I have with many of my UI's and is in fact a no-go for the built-in DPI awareness...

@Fred: Are you aware of this problem and is it going to be fixed sometime in the near future OR are there no plans of addressing this problem? I kinda need to know, thank you :oops:

Image