
While experimenting with the DPI-Aware feature of PureBasic, I cobbled together three examples that will display almost exactly the same on any resolution screen; if the need ever arises.

This first one compares the resolution of the executing machine against the resolution of the development machine and scales all the window, gadget, and content measurements accordingly. As it relies on a pre-initialised, invisible, maximised window to obtain the metrics of the display, it is not affected by any applied scaling or zooming. However, as Linux does not support the #PB_Window_Maximize directive well, it does not work reliably on Linux.
Code: Select all
;=========================================================
;
; for apps to maintain their original window and
; content sizings and gadget placements regardless
; of the display resolutions of the executing display
; including scaled and zoomed displays
;
; tested & working on:
; i. Windows XP to Windows 10 (PureBasic v5.0 ++)
; ii. macOS High Sierra to Sonoma (PureBasic v5.70 ++)
;
; please disable the DPI-Aware option on later
; versions of PureBasic that support the feature
;
;=========================================================
; this must be set to the resolution of the display
; that was used when designing the application
#devMachineWidth = 1920
#devMachineHeight = 1000
Global.f xScale, yScale
Macro x(width)
width * xScale
EndMacro
Macro y(height)
height * yScale
EndMacro
Procedure getDisplayMetrics()
OpenWindow(0, 0, 0, 10, 10, "",
#PB_Window_Invisible |
#PB_Window_Maximize)
Define winWidth = WindowWidth(0)
Define winHeight = WindowHeight(0)
CloseWindow(0)
xScale = (winWidth / #devMachineWidth)
yScale = (winHeight / #devMachineHeight)
aspectRatio.f = winWidth / winHeight
If aspectRatio < 1.5
yScale / aspectRatio
EndIf
EndProcedure
getDisplayMetrics()
;###### sample GUI ######
image = LoadImage(#PB_Any, #PB_Compiler_Home + "examples/sources/Data/Geebee2.bmp")
smallFont = LoadFont(#PB_Any, "Arial", y(12))
mediumFont = LoadFont(#PB_Any, "Arial", y(16))
largeFont = LoadFont(#PB_Any, "Arial", y(22))
wFlags = #PB_Window_SystemMenu | #PB_Window_ScreenCentered
OpenWindow(0, 0, 0, x(530), y(480), "Responsive Desktop Example", wFlags)
ButtonGadget(0, x(80), y(30), x(120), y(40), "Small Button")
SetGadgetFont(0, FontID(smallFont))
ButtonGadget(1, x(60), y(100), x(160), y(50), "Medium Button")
SetGadgetFont(1, FontID(mediumFont))
ButtonGadget(2, x(40), y(180), x(200), y(60), "Large Button")
SetGadgetFont(2, FontID(largeFont))
TextGadget(3, x(80), y(280), x(120), y(30), "Small Text", #PB_Text_Center)
SetGadgetFont(3, FontID(smallFont))
TextGadget(4, x(70), y(340), x(140), y(50), "Medium Text", #PB_Text_Center)
SetGadgetFont(4, FontID(mediumFont))
TextGadget(5, x(60), y(400), x(160), y(60), "Large Text", #PB_Text_Center)
SetGadgetFont(5, FontID(largeFont))
ResizeImage(image, x(100), y(100))
ImageGadget(6, x(290), y(30), x(100), y(100), ImageID(image))
ResizeImage(image, x(200), y(200))
ImageGadget(7, x(290), y(240), x(200), y(200), ImageID(image))
ProgressBarGadget(8, x(290), y(170), x(200), y(40), 0, 100)
SetGadgetState(8, 60)
While WaitWindowEvent() ! #PB_Event_CloseWindow : Wend
;########################
This second one does exactly the same thing, except that it utilises the ExamineDesktops() function to obtain the display metrics. The values returned by this function do not factor in any applied scaling or zooming, so the windows will look bigger if scaling or zooming is applied. This approach works on Windows, macOS, and Linux as well.
Code: Select all
;=========================================================
;
; for apps to maintain their original window and
; content sizings and gadget placements regardless
; of the display resolutions of the executing display
;
; tested & working on:
; i. Windows XP to Windows 10 (PureBasic v5.0 ++)
; ii. macOS High Sierra to Sonoma (PureBasic v5.70 ++)
; iii. Ubuntu Linux 18.04.2 (PureBasic 6.11)
;
; does not support scaled or zoomed displays -
; please disable the DPI-Aware option on later
; versions of PureBasic that support the feature
;
;=========================================================
; this must be set to the resolution of the display
; that was used when designing the application
#devMachineWidth = 1920
#devMachineHeight = 1000
Global.f xScale, yScale
Macro x(width)
width * xScale
EndMacro
Macro y(height)
height * yScale
EndMacro
Procedure getDisplayMetrics()
ExamineDesktops()
winWidth = DesktopWidth(0)
winHeight = DesktopHeight(0)
xScale = (winWidth / #devMachineWidth)
yScale = (winHeight / #devMachineHeight)
aspectRatio.f = winWidth / winHeight
If aspectRatio < 1.5
yScale / aspectRatio
EndIf
EndProcedure
getDisplayMetrics()
;###### sample GUI ######
image = LoadImage(#PB_Any, #PB_Compiler_Home + "examples/sources/Data/Geebee2.bmp")
smallFont = LoadFont(#PB_Any, "Arial", y(12))
mediumFont = LoadFont(#PB_Any, "Arial", y(16))
largeFont = LoadFont(#PB_Any, "Arial", y(22))
wFlags = #PB_Window_SystemMenu | #PB_Window_ScreenCentered
OpenWindow(0, 0, 0, x(530), y(480), "Responsive Desktop App Example", wFlags)
ButtonGadget(0, x(80), y(30), x(120), y(40), "Small Button")
SetGadgetFont(0, FontID(smallFont))
ButtonGadget(1, x(60), y(100), x(160), y(50), "Medium Button")
SetGadgetFont(1, FontID(mediumFont))
ButtonGadget(2, x(40), y(180), x(200), y(60), "Large Button")
SetGadgetFont(2, FontID(largeFont))
TextGadget(3, x(80), y(280), x(120), y(30), "Small Text", #PB_Text_Center)
SetGadgetFont(3, FontID(smallFont))
TextGadget(4, x(70), y(340), x(140), y(50), "Medium Text", #PB_Text_Center)
SetGadgetFont(4, FontID(mediumFont))
TextGadget(5, x(60), y(400), x(160), y(60), "Large Text", #PB_Text_Center)
SetGadgetFont(5, FontID(largeFont))
ResizeImage(image, x(100), y(100))
ImageGadget(6, x(290), y(30), x(100), y(100), ImageID(image))
ResizeImage(image, x(200), y(200))
ImageGadget(7, x(290), y(240), x(200), y(200), ImageID(image))
ProgressBarGadget(8, x(290), y(170), x(200), y(40), 0, 100)
SetGadgetState(8, 60)
While WaitWindowEvent() ! #PB_Event_CloseWindow : Wend
;########################
The final example is a duplicate of the second one, but it applies the new DesktopScaledX/Y() functions to obtain any applied scaling or zooming. This will maintain the original size of the window, gadgets, and contents even on scaled or zoomed displays. It works only on Windows with PureBasic v5.70++, and on macOS with PureBasic v6.10++, with the compiler's DPI-Aware option enabled.
Code: Select all
;=========================================================
;
; for apps to maintain their original window and
; content sizings and gadget placements regardless
; of the display resolutions of the executing display
; including scaled and zoomed displays
;
; tested & working on:
; i. Windows XP to Windows 10 (PureBasic v5.70 ++)
; ii. macOS High Sierra to Sonoma (PureBasic v6.10 ++)
;
; please enable the DPI-Aware compiler option
;
;=========================================================
CompilerIf (#PB_Compiler_OS = #PB_OS_MacOS And #PB_Compiler_Version < 610) Or
(#PB_Compiler_OS = #PB_OS_Windows And #PB_Compiler_Version < 570) Or
#PB_Compiler_OS = #PB_OS_Linux
CompilerError "Platform/Version not supported!"
CompilerEndIf
; this must be set to the resolution of the display
; that was used when designing the application
#devMachineWidth = 1920
#devMachineHeight = 1000
Global.f xScale, yScale
Macro x(width)
width * xScale
EndMacro
Macro y(height)
height * yScale
EndMacro
Procedure getDisplayMetrics()
ExamineDesktops()
winWidth = DesktopWidth(0)
winHeight = DesktopHeight(0)
aspectRatio.f = winWidth / winHeight
dtScaleX.f = DesktopScaledX(100) / 100
dtScaleY.f = DesktopScaledY(100) / 100
xScale = (winWidth / #devMachineWidth) / dtScaleX
yScale = (winHeight / #devMachineHeight) / dtScaleY
If aspectRatio < 1.5
yScale / aspectRatio
EndIf
EndProcedure
getDisplayMetrics()
;###### sample GUI ######
imgRes.s = #PB_Compiler_Home +
"examples/sources/Data/Geebee2.bmp"
image = LoadImage(#PB_Any, imgRes)
image2 = CopyImage(image, #PB_Any)
smallFont = LoadFont(#PB_Any, "Arial", y(12))
mediumFont = LoadFont(#PB_Any, "Arial", y(16))
largeFont = LoadFont(#PB_Any, "Arial", y(22))
CompilerIf #PB_Compiler_OS = #PB_OS_MacOS
ResizeImage(image, x(100), y(100))
ResizeImage(image2, x(200), y(200))
CompilerElse
ResizeImage(image, 100, 100)
ResizeImage(image2, 200, 200)
CompilerEndIf
wFlags = #PB_Window_SystemMenu | #PB_Window_ScreenCentered
OpenWindow(0, 0, 0, x(530), y(480), "Responsive Desktop App Example", wFlags)
ButtonGadget(0, x(80), y(30), x(120), y(40), "Small Button")
SetGadgetFont(0, FontID(smallFont))
ButtonGadget(1, x(60), y(100), x(160), y(50), "Medium Button")
SetGadgetFont(1, FontID(mediumFont))
ButtonGadget(2, x(40), y(180), x(200), y(60), "Large Button")
SetGadgetFont(2, FontID(largeFont))
TextGadget(3, x(80), y(280), x(120), y(30), "Small Text", #PB_Text_Center)
SetGadgetFont(3, FontID(smallFont))
TextGadget(4, x(70), y(340), x(140), y(50), "Medium Text", #PB_Text_Center)
SetGadgetFont(4, FontID(mediumFont))
TextGadget(5, x(60), y(400), x(160), y(60), "Large Text", #PB_Text_Center)
SetGadgetFont(5, FontID(largeFont))
ImageGadget(6, x(290), y(30), x(100), y(100), ImageID(image))
ImageGadget(7, x(290), y(240), x(200), y(200), ImageID(image2))
ProgressBarGadget(8, x(290), y(170), x(200), y(40), 0, 100)
SetGadgetState(8, 60)
While WaitWindowEvent() ! #PB_Event_CloseWindow : Wend
;########################
These are just conceptualised examples to demonstrate the scaling concepts, and in no way bulletproof. Hopefully, they might still provide some inherent value.