PureBasic Survival Guide XVII - DPI 
PureBasic Survival Guide
a tutorial for using purebasic for windows 4.51

Part 0 - TOC
Part I - General
Part II - Converts
Part III - Primer I
Part IV - Primer II
Part V - Advanced
Part VI - 2D Graphics I
Part VII - 2D Graphics II
Part X - Assembly
Part XI - Debugger
Part XII - VirtualBox
Part XIII - Databases
Part XIV - Networking
Part XV - Regular Expressions
Part XVI - Application Data
Part XVII - DPI
Part XXVII - Irregular Expressions
Part XXIX - Projects
 

Part XVII - DPI
v0.05 12.04.2011

17.1 Not all Windows are created equal...

 

This page needs reconstruction. The original version of this page was created in 2011. Things have changed since then...
 

17.1 Not all Windows are created equal...
 

Oh dear, same headline, so this page is (again) about different flavours of Windows or something similar. Well, indeed! When programming for MicroSoft Windows you have to be aware of the DPI.

Testing.

I strongly sugest to install a VM, like VirtualBox or VMWare or whatever you prefer.

To develop software that works regardless of settings it might be a good idea to install one or more other flavours of Windows on several Virtual Machines. Then set one VM to a different dpi setting, enable large fonts on another, and run a third VM with different dpi settings and 'XP style DPI disabled'. If all those VM's have access to a shared drive with your test code, you then can check your code's behaviour in different environments.

The quick and dirty solution.

If you don't want to be bothered with the impact of changed DPI's or fonts, and you cannot be bothered reading these pages, I suggest you do the following:

  1. adjust the font size when loading, depending on the dpi value returned by GetDeviceCaps_(), this will fix all DPI issues when 'XP style DPI' is turned on
  2. either adjust the results from DesktopWidth() or use one of the other WinApi calls to find the (adjusted) screen size
The proper solution would be to calculate the size of every GUI element depending on the font and fontsize being used. In some cases, this may simply not be worth it.
 

17.2 Links.

Without a doubt other people can explain it better...


17.x Example screens.

Here are a few examples of PureBasic 4.51 on different Windows flavours. I've commented on each flavour below the image. I've used the following code, so you can test it yourself:

; survival guide 4_17_100 dpi
; pb 4.51b1
;
; create the checkered images
;
CreateImage(1,400,400)
StartDrawing(ImageOutput(1))
DrawingMode(#PB_2DDrawing_Default)
For x = 0 To 30
  For y = 0 To 30
    FrontColor(RGB($FF,$FF,$FF) * ((y*5+x) & %1))
    Box(x*20,y*20,x*20+19,y*20+19)
  Next y
Next x
StopDrawing()
;
CreateImage(2,200,200)
StartDrawing(ImageOutput(2))
DrawingMode(#PB_2DDrawing_Default)
For x = 0 To 30
  For y = 0 To 30
    FrontColor(RGB($FF,$00,$00) * ((y*5+x) & %1))
    Box(x*20,y*20,x*20+19,y*20+19)
  Next y
Next x
FrontColor(0)
Box(20,40,160,40)
FrontColor(RGB($FF,$FF,$FF))
DrawText(60,53,"DRAWTEXT")
StopDrawing()
;
; create the background window
;
OpenWindow(1,100,100,400,400,"BACKGROUND")
ImageGadget(1,0,0,400,400,ImageID(1))
;
; create the foreground window
;
OpenWindow(2,140,140,200,330,"TEST")
ImageGadget(2,0,0,200,200,ImageID(2))
ButtonGadget(3,10,210,180,50,"BUTTONGADGET")
Frame3DGadget(4,10,270,180,50,"FRAME3DGADGET")
TextGadget(5,20,290,80,50,"TEXT1",#PB_Text_Center)
TextGadget(6,100,290,80,50,"TEXT2",#PB_Text_Center)
LoadFont(1,"Arial",15)
SetGadgetFont(6,FontID(1))
;
ExamineDesktops()
Debug "desktopwidth() "+Str(DesktopWidth(0))
Debug "getsystemmetrics_() "+Str(GetSystemMetrics_(#SM_CXSCREEN))
Debug "getdevicecaps_() "+Str(GetDeviceCaps_(GetDC_(0), #HORZRES))
Debug "getdevicecaps_() "+Str(GetDeviceCaps_(GetDC_(0), #LOGPIXELSX))
;
Repeat
  event = WaitWindowEvent()
Until event = #PB_Event_CloseWindow


And here are some commented screens:
 

Regular WinXP using the default normal font and 96 dpi.... Yeah, I know. I'm old fashioned using the Windows 98 look, though I prefer the word 'classic' or 'classy' :-)
 

WinXP using the 'extra large font'. As you can see, only Windows GUI elements seem to be affected. As my PureBasic test program isn't checking the font size, and has no such thing as dynamic / resizing gadgets, text may become so big that it won't fit inside buttons etc. This is a common problem with the 'extra large font' setting: many programs ignore this setting, and thus don't work well when using it.
 

WinXP but using 120 dpi. Look carefully. You can see all text output (on buttons and on the image) is upscaled following the larger DPI setting (120 instead of 96). All Windows GUI elements are upscaled, but the gadgets and windows created by PureBasic are not. In this case we'll either have to downsize our font, or upscale everything else.
 

Vista (64 bits) using 96 dpi. By default the option 'XP style DPI' is turned off.
 

The same Vista, now at 120 dpi. The behaviour is the same as Windows XP. Text is upscaled by PureBasic, but none of the other (PureBasic) elements is affected. Larger DPI settings are possible in Vista and things should work like Windows 7 when going above 120 dpi or 144 dpi. However some comments on the Internet indicate there might be some inconcistencies, though I've not run into those myself. I suspect Vista's 'high DPI awareness' may not be as good as the one build into Windows 7 but I just might be wrong... as is not uncommon :-)
 

Windows 7 at 120 dpi, XP style DPI. Everything works just like Vista above.
 

Windows 7 again at 120 dpi but this time with XP style DPI turned off. As you can see the PureBasic output is upscaled by Windows. My application isn't doing anything different. A query to GetDeviceCaps_() tells my application the system is still running at 96 dpi though in fact that is not the case, as checking DesktopWidth() tells us. You could safely handle things by assuming you're on a regular 96 dpi system, with a smaller screen... Just don't rely on DesktopWidth().
 

And the final image... for now :-) Windows 7 at 144 dpi with XP style DPI turned off. More automatic upscaling, as yu can see. Again notice the difference of screen size reported by DesktopWidth() and GetSystemMetrics_().