How I make DPI-aware apps

Share your advanced PureBasic knowledge/code with the community.
Dude
Addict
Addict
Posts: 1907
Joined: Mon Feb 16, 2015 2:49 pm

How I make DPI-aware apps

Post 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. :)
User avatar
VB6_to_PBx
Enthusiast
Enthusiast
Posts: 617
Joined: Mon May 09, 2011 9:36 am

Re: How I make DPI-aware apps

Post by VB6_to_PBx »

Dude ,

thank you very much for this example
 
PureBasic .... making tiny electrons do what you want !

"With every mistake we must surely be learning" - George Harrison
davido
Addict
Addict
Posts: 1890
Joined: Fri Nov 09, 2012 11:04 pm
Location: Uttoxeter, UK

Re: How I make DPI-aware apps

Post by davido »

@Dude,
Excellent!
Thank you for sharing.
DE AA EB
HanPBF
Enthusiast
Enthusiast
Posts: 563
Joined: Fri Feb 19, 2010 3:42 am

Re: How I make DPI-aware apps

Post by HanPBF »

Thanks a lot for the code!
davido
Addict
Addict
Posts: 1890
Joined: Fri Nov 09, 2012 11:04 pm
Location: Uttoxeter, UK

Re: How I make DPI-aware apps

Post by davido »

Hm... I wonder if anyone knows of similar methods for the other two OS's?
DE AA EB
Ulix
User
User
Posts: 48
Joined: Wed Jan 23, 2008 12:45 pm
Location: France, Montpellier

Re: How I make DPI-aware apps

Post 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:
User avatar
bbanelli
Enthusiast
Enthusiast
Posts: 543
Joined: Tue May 28, 2013 10:51 pm
Location: Europe
Contact:

Re: How I make DPI-aware apps

Post 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+?
"If you lie to the compiler, it will get its revenge."
Henry Spencer
https://www.pci-z.com/
User avatar
Sicro
Enthusiast
Enthusiast
Posts: 538
Joined: Wed Jun 25, 2014 5:25 pm
Location: Germany
Contact:

Re: How I make DPI-aware apps

Post 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.
Image
Why OpenSource should have a license :: PB-CodeArchiv-Rebirth :: Pleasant-Dark (syntax color scheme) :: RegEx-Engine (compiles RegExes to NFA/DFA)
Manjaro Xfce x64 (Main system) :: Windows 10 Home (VirtualBox) :: Newest PureBasic version
RASHAD
PureBasic Expert
PureBasic Expert
Posts: 4636
Joined: Sun Apr 12, 2009 6:27 am

Re: How I make DPI-aware apps

Post 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
Egypt my love
Bitblazer
Enthusiast
Enthusiast
Posts: 732
Joined: Mon Apr 10, 2017 6:17 pm
Location: Germany
Contact:

Re: How I make DPI-aware apps

Post 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
webpage - discord chat links -> purebasic GPT4All
Dude
Addict
Addict
Posts: 1907
Joined: Mon Feb 16, 2015 2:49 pm

Re: How I make DPI-aware apps

Post 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. :?
Bitblazer
Enthusiast
Enthusiast
Posts: 732
Joined: Mon Apr 10, 2017 6:17 pm
Location: Germany
Contact:

Re: How I make DPI-aware apps

Post 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.
webpage - discord chat links -> purebasic GPT4All
Dude
Addict
Addict
Posts: 1907
Joined: Mon Feb 16, 2015 2:49 pm

Re: How I make DPI-aware apps

Post 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:
User avatar
chi
Addict
Addict
Posts: 1028
Joined: Sat May 05, 2007 5:31 pm
Location: Linz, Austria

Re: How I make DPI-aware apps

Post by chi »

Same here! The built-in solution seems to enlarge some fonts a bit too much
Et cetera is my worst enemy
User avatar
chi
Addict
Addict
Posts: 1028
Joined: Sat May 05, 2007 5:31 pm
Location: Linz, Austria

Re: How I make DPI-aware apps

Post 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
Et cetera is my worst enemy
Post Reply