How to handle Windows UI scaling?

Just starting out? Need help? Post your questions and find answers here.
mrw
User
User
Posts: 76
Joined: Wed Dec 31, 2014 1:01 pm

How to handle Windows UI scaling?

Post by mrw »

Hi,
I just discovered a problem when a Windows user has enlarged the UI, and I create a window with the same size as the desktop.

Example:
I use a laptop(Win 8.1) with a native resolution 2880 x 1620. To me this makes windows, text, startmenu and so on too small to be comfortable.
So if I open up Display in the Control Panel I can enlarge the UI using a slider or a percentage.
This does what is expected, enlarge text and menues and so on.

If I then, using PureBasic, create a normal window with size 640x480, the window is larger than without scaling.

Then I create a borderless window(fullscreen window) with width and height using DesktopWidth() and DesktopHeight(). Those functions return the screens resolution which is 2880x1620. This makes the windows much larger than the screen, when using UI scaling. And if I draw too much to the right or down it´s off the screen.

How can we handle this the best way? Are there commands such as DesktopWidth() that can handle scaling? Or any other way we can read the scaling and adjust accordingly?

I think this problem will be more and more common when monitors and displays uses higher and higher resolutions.

Thanks
//Andreas..
User avatar
NicknameFJ
User
User
Posts: 90
Joined: Tue Mar 17, 2009 6:36 pm
Location: Germany

Re: How to handle Windows UI scaling?

Post by NicknameFJ »

Never done it, but what you are searching for is called DPI Awareness.

Search for DPI Aware here in the Forum. I`ve seen it just a few weeks ago.

Greetings

NicknameFJ

PS: http://www.purebasic.fr/english/viewtop ... re#p462177 see the post of Danilo
PS: Sorry for my weird english, but english is not my native language.



Image
mrw
User
User
Posts: 76
Joined: Wed Dec 31, 2014 1:01 pm

Re: How to handle Windows UI scaling?

Post by mrw »

Thanks for your reply,

I looked at that thread and my first thought is that there should be a much easier way to handle this. Atleast in PureBasic where this kind of UI scaling probably exist in Linux and Mac too?
Danilos code is windows only, but perhaps this is the only way to go? Currently anyway?

I´ve tested a couple of commercial applications and games to see how they handle this.
Games seems to override this and ignore it completely. So games that uses a "start-app" are extremely small and text are scaled so they look very bugged. But since most games uses fullscreen this might not be a problem.
But most Windows-applications like Photoshop, Firefox are all aware and when I switch them to fullscreen view(which is just a borderless window and not a real full screen..). They fill up the screen nicely.

I guess I should check Danilos code and try to create my own DesktopWidth() and DesktopHeight() functions that are DPI aware and return the resolution scaled.
Also a function to completely override this and let my windows be very small if I create them with a small resolution.

Unless someone comes up with a better idea?
ozzie
Enthusiast
Enthusiast
Posts: 443
Joined: Sun Apr 06, 2008 12:54 pm
Location: Brisbane, Qld, Australia
Contact:

Re: How to handle Windows UI scaling?

Post by ozzie »

I use the procedures and macros included in the Forum posting DPI Aware Application. It's a bit of a pain having to use parameters like ScaleDPIy(23) instead of just 23 when creating gadgets, etc, but you soon get used to it.
User avatar
Thunder93
Addict
Addict
Posts: 1788
Joined: Tue Mar 21, 2006 12:31 am
Location: Canada

Re: How to handle Windows UI scaling?

Post by Thunder93 »

You could simplify the procedure with usage of Macros and Procedures.

For OpenWindow()

Code: Select all

Procedure _OpenWindow(WindowID.l, x.l, y.l, Width.l, Height.l, Text$, Flags.l)
  ProcedureReturn OpenWindow(WindowID.l, x.l, y.l, Width.l, Height.l, Text$, Flags.l)
EndProcedure

Macro OpenWindow(WindowID, x, y, Width, Height, Text, Flags)
    _OpenWindow(WindowID, ScaleDPIx(x), ScaleDPIy(y), ScaleDPIx(Width), ScaleDPIy(Height), Text, Flags)
EndMacro
Now simply using numbers without ScaleDPIy(..) and ScaleDPIx(...) usage.

Code: Select all

OpenWindow(0, 100, 200, #WindowWidth, #WindowHeight, "PureBasic - Gadget Demonstration", #PB_Window_MinimizeGadget)
I actually believe it to be worth-while to make importable file that includes such changes for all the PB gadgets, or the ones you will be using in your code. :wink:

ozzie wrote:I use the procedures and macros included in the Forum posting DPI Aware Application. It's a bit of a pain having to use parameters like ScaleDPIy(23) instead of just 23 when creating gadgets, etc, but you soon get used to it.
ʽʽSuccess is almost totally dependent upon drive and persistence. The extra energy required to make another effort or try another approach is the secret of winning.ʾʾ --Dennis Waitley
User avatar
fsw
Addict
Addict
Posts: 1603
Joined: Tue Apr 29, 2003 9:18 pm
Location: North by Northwest

Re: How to handle Windows UI scaling?

Post by fsw »

ozzie wrote:I use the procedures and macros included in the Forum posting DPI Aware Application. It's a bit of a pain having to use parameters like ScaleDPIy(23) instead of just 23 when creating gadgets, etc, but you soon get used to it.
This is the way to go and there are 4 ways to implement it:
1) Write ScaleDPIy(x) all the time it's needed
2) Use Macro's as already shown above
3) Create a UI include file as library to take care of #1
4) PureBasic implements #PB_AutoScaleDPI for OpenWindow

Had a similar problem here but for cross platform reasons not DPI scaling.
(example: an app designed in Linux would have cut-off text in gadgets on MacOS, etc.)

In my case I went for #3 because in this include file more things than proper UI scaling are taken care of.
(like proper menu arrangement on different OS etc.)

The bottom line is that for an optimal UI more things need to be taken care:
1) DPI scaling (no matter which OS)
2) Cross platform UI differences with standard fonts
3) Different fonts (no matter which OS)

fsw

I am to provide the public with beneficial shocks.
Alfred Hitshock
mrw
User
User
Posts: 76
Joined: Wed Dec 31, 2014 1:01 pm

Re: How to handle Windows UI scaling?

Post by mrw »

Thanks for all your excellent explanations!

The best solution would obviously be to implement this natively in PureBasic, as you list as #4.
And hopefully they will be, to get this sorted across all OSes. But in the meantime I assume we have to make these workaround ourselves.

I´ll look at all the examples and see how I can implement them best in my projects.

Thanks again.
//Andreas..
ozzie
Enthusiast
Enthusiast
Posts: 443
Joined: Sun Apr 06, 2008 12:54 pm
Location: Brisbane, Qld, Australia
Contact:

Re: How to handle Windows UI scaling?

Post by ozzie »

wrt to using the macros ScaleDPIx and ScaleDPIy, you could reduce the amount of work and the line lengths by using shorter macro names. I note that Danilo's code uses dpiX and dpiY. Even dx and dy would be sufficient macros names.
User avatar
Thunder93
Addict
Addict
Posts: 1788
Joined: Tue Mar 21, 2006 12:31 am
Location: Canada

Re: How to handle Windows UI scaling?

Post by Thunder93 »

Just more of the example I'm in reference too. You could separate this stuff and place it into a separate file to be used as a header include file. :wink:


DPI_Scaling.pbi

Code: Select all

;;;;; DPI-Aware Application ;;;;;
; Posted by Rescator on Sat Jan 02, 2010  -  http://forums.purebasic.com/english/viewtopic.php?f=12&t=40507
; Platforms: Windows Only

;Placed in the Public Domain by Roger Hågensen.
#PB_Compiler_Exe=#True ;This does not exist (yet?)

;http://msdn.microsoft.com/en-us/library/dd464660%28VS.85%29.aspx
Global.f _ScaleDPI_X_ = 1.0, _ScaleDPI_Y_ = 1.0, Font$, FontSize.b = 9
#DefaultDPIX = 96.0  ;Different platforms might have different default DPI, Windows is 96 DPI.
#DefaultDPIY = 96.0
Procedure InitScaleDPI() ;Windows 5.0 or higher needed for minimum functionality of this procedure.
  Protected.i dc, lpx, lpy, IsUser32DLL, *SetProcessDPIAware, *IsProcessDPIAware, DPIAware.l = #False , ncm.NONCLIENTMETRICS, Font
  
  ;This part is Windows 6.x+ only (Vista etc.) and must be done before we use devcaps.
  ;http://msdn.microsoft.com/en-us/library/dd464660%28VS.85%29.aspx#declaring_dpi_awareness
  ;You really should use the DPI aware manifest instead of SetProcessDPIAware() when possible.
  ;On Windows 2000 and XP the manifest has no effect and set dpi aware is not available,
  ;however Devicecaps still returns usefull info that can be used.
  ;Note! If the dpi aware manifest is missing on Vista and Win7 then the OS will lie on devicecaps and will autoscale the entire app window.
  CompilerIf #PB_Compiler_Exe ;Only use this in exes, as DLLs inherit DPI from the calling process.
                              ;If the exe or the calling exe in case of this being a DLLs is allready dpi aware (like through a manifest),
                              ;then we skip using the the set dpi aware function, a DLLs should never use the set function, but it should check if the process id dpi aware
                              ;and apply the proper modifiers where appropriate obviously.
    
    IsUser32DLL = OpenLibrary(#PB_Any, "user32.dll")
    If IsUser32DLL
      *IsProcessDPIAware = GetFunction(IsUser32DLL, "IsProcessDPIAware")
      If *IsProcessDPIAware
        DPIAware = CallFunctionFast(*IsProcessDPIAware)
      EndIf
      If Not DPIAware
        *SetProcessDPIAware = GetFunction(IsUser32DLL, "SetProcessDPIAware")
        If *SetProcessDPIAware
          CallFunctionFast(*SetProcessDPIAware)
        EndIf
      EndIf
    EndIf
  CompilerEndIf
  dc = GetDC_(#Null)
  If dc
    lpx = GetDeviceCaps_(dc, #LOGPIXELSX)
    lpy = GetDeviceCaps_(dc, #LOGPIXELSY)
    If lpx>0
      _ScaleDPI_X_ = lpx/#DefaultDPIX
    EndIf
    If lpy>0
      _ScaleDPI_Y_ = lpy/#DefaultDPIY
    EndIf
    ReleaseDC_(#Null, dc)
  EndIf
  
    ;Get the system font for message boxes etc.
    ;We default to a size of 9, which is also the Vista and Win7 default size.
    ;The OS will automatically (Vista and Win7 at least) scale the font per the current user's DPI setting.
    ncm\cbSize = SizeOf(NONCLIENTMETRICS)
    If SystemParametersInfo_(#SPI_GETNONCLIENTMETRICS, SizeOf(NONCLIENTMETRICS), ncm, #Null)
      Font$ = PeekS(@ncm\lfMessageFont\lfFaceName)
      If OSVersion() < #PB_OS_Windows_Vista : FontSIze = 8 : EndIf
      Font = LoadFont(#PB_Any, Font$, FontSIze, #PB_Font_HighQuality)
      If Font
        SetGadgetFont(#PB_Default, FontID(Font))
      EndIf
    EndIf
EndProcedure : InitScaleDPI()
Macro Dx(x) : (x)*_ScaleDPI_X_ : EndMacro
Macro Dy(y) : (y)*_ScaleDPI_Y_ : EndMacro

Macro pDx(x) : Int((x)/_ScaleDPI_X_) : EndMacro
Macro pDy(y) : Int((y)/_ScaleDPI_Y_) : EndMacro
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


;-> Procedures for Macros associates 
Procedure _OpenWindow(WindowID.l, x.l, y.l, Width.l, Height.l, Title$, Flags.l)
  ProcedureReturn OpenWindow(WindowID, x, y, Width, Height, Title$, Flags)
EndProcedure

Procedure _StringGadget(GadgetID.l, x.l, y.l, Width.l, Height.l, Text$, Flags.l)
  ProcedureReturn StringGadget(GadgetID, x, y, Width, Height, Text$, Flags)
EndProcedure

Procedure _ButtonGadget(GadgetID.l, x.l, y.l, Width.l, Height.l, Text$, Flags.l)
  ProcedureReturn ButtonGadget(GadgetID, x, y, Width, Height, Text$, Flags)
EndProcedure

Procedure _FrameGadget(GadgetID.l, x.l, y.l, Width.l, Height.l, Text$, Flags.l)
  ProcedureReturn FrameGadget(GadgetID, x, y, Width, Height, Text$, Flags)
EndProcedure

Procedure _PanelGadget(GadgetID.l, x.l, y.l, Width.l, Height.l)
  ProcedureReturn PanelGadget(GadgetID, x, y, Width, Height)
EndProcedure

Procedure _TrackBarGadget(GadgetID.l, x.l, y.l, Width.l, Height.l, Minimum, Maximum, Flags)
  ProcedureReturn TrackBarGadget(GadgetID, x, y, Width, Height, Minimum, Maximum, Flags)
EndProcedure

Procedure _CheckBoxGadget(GadgetID.l, x.l, y.l, Width.l, Height.l, Text$, Flags.l)
  ProcedureReturn CheckBoxGadget(GadgetID, x, y, Width, Height, Text$, Flags)
EndProcedure

Procedure _ComboBoxGadget(GadgetID.l, x.l, y.l, Width.l, Height.l, Flags.l)
  ProcedureReturn ComboBoxGadget(GadgetID, x, y, Width, Height, Flags)
EndProcedure

Procedure _OptionGadget(GadgetID.l, x.l, y.l, Width.l, Height.l, Text$)
  ProcedureReturn OptionGadget(GadgetID, x, y, Width, Height, Text$)
EndProcedure

Procedure _TextGadget(GadgetID.l, x.l, y.l, Width.l, Height.l, Text$, Flags.l)
  ProcedureReturn TextGadget(GadgetID, x, y, Width, Height, Text$, Flags)
EndProcedure

Procedure _ListIconGadget(GadgetID.l, x.l, y.l, Width.l, Height.l, Title$, TitleWidth.l, Flags.l)
  ProcedureReturn ListIconGadget(GadgetID, x, y, Width, Height, Title$, TitleWidth, Flags)
EndProcedure

Procedure _EditorGadget(GadgetID.l, x.l, y.l, Width.l, Height.l, Flags.l)
  ProcedureReturn EditorGadget(GadgetID, x, y, Width, Height, Flags)
EndProcedure

;-> Macros for Procedures associates
Macro OpenWindow(WindowID, x, y, Width, Height, Title, Flags = #PB_Window_SystemMenu)
  _OpenWindow(WindowID, Dx(x), Dy(y), Dx(Width), Dy(Height), Title, Flags)
EndMacro

Macro StringGadget(GadgetID, x, y, Width, Height, Text, Flags = 0)
  _StringGadget(GadgetID, Dx(x), Dy(y), Dx(Width), Dy(Height), Text, Flags)
EndMacro

Macro ButtonGadget(GadgetID, x, y, Width, Height, Text, Flags = 0)
  _ButtonGadget(GadgetID, Dx(x), Dy(y), Dx(Width), Dy(Height), Text, Flags)
EndMacro

Macro FrameGadget(GadgetID, x, y, Width, Height, Text, Flags = 0)
  _FrameGadget(GadgetID, Dx(x), Dy(y), Dx(Width), Dy(Height), Text, Flags)
EndMacro

Macro PanelGadget(GadgetID, x, y, Width, Height)
  _PanelGadget(GadgetID, Dx(x), Dy(y), Dx(Width), Dy(Height))
EndMacro

Macro TrackBarGadget(GadgetID, x, y, Width, Height, Minimum, Maximum, Flags = #PB_TrackBar_Vertical)
  _TrackBarGadget(GadgetID, Dx(x), Dy(y), Dx(Width), Dy(Height), Minimum, Maximum, Flags)
EndMacro

Macro CheckBoxGadget(GadgetID, x, y, Width, Height, Text, Flags = 0)
  _CheckBoxGadget(GadgetID, Dx(x), Dy(y), Dx(Width), Dy(Height), Text, Flags)
EndMacro

Macro ComboBoxGadget(GadgetID, x, y, Width, Height, Flags = 0)
  _ComboBoxGadget(GadgetID, Dx(x), Dy(y), Dx(Width), Dy(Height), Flags)
EndMacro

Macro OptionGadget(GadgetID, x, y, Width, Height, Text)
  _OptionGadget(GadgetID, Dx(x), Dy(y), Dx(Width), Dy(Height), Text)
EndMacro

Macro TextGadget(GadgetID, x, y, Width, Height, Text, Flags = 0)
  _TextGadget(GadgetID, Dx(x), Dy(y), Dx(Width), Dy(Height), Text, Flags)
EndMacro

Macro ListIconGadget(GadgetID, x, y, Width, Height, Title, TitleWidth, Flags = 0)
  _ListIconGadget(GadgetID, Dx(x), Dy(y), Dx(Width), Dy(Height), Title, Dx(TitleWidth), Flags)
EndMacro

Macro EditorGadget(GadgetID, x, y, Width, Height, Flags)
  _EditorGadget(GadgetID, Dx(x), Dy(y), Dx(Width), Dy(Height), Flags)
EndMacro


;The Gadget example from PureBasic manual.
#WindowWidth  = 390
#WindowHeight = 350

If OpenWindow(0, 100, 200, #WindowWidth, #WindowHeight, "PureBasic - Gadget Demonstration", #PB_Window_MinimizeGadget)
  
  Top = 10
  GadgetHeight = 24
  
  FrameGadget(#PB_Any, 10, Top, 370, 290, "Player...") : Top+20
  
  StringGadget(0, 20, Top, 200, GadgetHeight, "")
  ButtonGadget(1, 223, Top,  72, GadgetHeight, "Play")
  ButtonGadget(2, 295, Top,  72, GadgetHeight, "Stop")  : Top+35
  DisableGadget(2,1)
  
  GadgetToolTip(1,"Play the current song")
  
  PanelGadget(3, 20, Top, #WindowWidth-50, #WindowHeight-Top-60)
  AddGadgetItem(3, 0, "MP3 PlayList")
  ListViewGadget(4, 6, 10, 230, 148)
  
  For k=0 To 30
    AddGadgetItem(4, -1, "Music Song n° "+Str(k))
  Next
  
  ButtonGadget(5,  250, 10, 80, GadgetHeight, "Add")
  ButtonGadget(6,  250, 38, 80, GadgetHeight, "Remove")
  ButtonGadget(7,  250, 66, 80, GadgetHeight, "Select")
  GadgetToolTip(7, "Select the current song")
  
  TrackBarGadget(17, 10, 168, 310, 25, 0, 100)
  
  AddGadgetItem(3, 1, "Options")
  Top = 10
  CheckBoxGadget(10, 10, Top, 250, GadgetHeight, "Enable low-pass filter") : Top+30
  CheckBoxGadget(11, 10, Top, 250, GadgetHeight, "Enable visual plug-in")  : Top+30
  ComboBoxGadget(12, 10, Top, 250, 21) : Top+30
  AddGadgetItem(12, -1, "FireWorks")
  AddGadgetItem(12, -1, "OpenGL spectrum")
  AddGadgetItem(12, -1, "Bump bass")
  SetGadgetState(12,0)
  DisableGadget(12,1)
  
  OptionGadget(13, 10, Top, 80, GadgetHeight, "640*480") : Top+20
  OptionGadget(14, 10, Top, 80, GadgetHeight, "800*600") : Top+20
  OptionGadget(15, 10, Top, 80, GadgetHeight, "1024*768")
  SetGadgetState(13, 1)
  
  ButtonGadget(16, 150, Top, 80, GadgetHeight, "Info")
  CloseGadgetList()
  
  TextGadget  (9, 10, #WindowHeight-30, 250, 24, "PureBasic - Gadget demonstration")
  ButtonGadget(8, #WindowWidth-100, #WindowHeight-36, 80, 24, "Quit")
  
  SetGadgetState(3, 0)
  
  Repeat
    EventID = WaitWindowEvent()
    
    If EventID = #PB_Event_Gadget
      
      Select EventGadget()
        Case 0
          If EventType() = #PB_EventType_ReturnKey
            MessageRequester("Info", "Return key pressed", 0)
            SetActiveGadget(0)
          EndIf
          
        Case 1 ; Play
          DisableGadget(2,0)  ; Enable the 'Stop' gadget
          DisableGadget(1,1)  ; Disable the 'Play' Gadget
          
        Case 2 ; Stop
          DisableGadget(1,0)  ; Enable the 'Play' gadget
          DisableGadget(2,1)  ; Disable the 'Stop' Gadget
          
        Case 4
          If EventType() = 2
            SetGadgetText(0, GetGadgetText(4)) ; Get the current item from the ListView..
          EndIf
          
        Case 5 ; Add
          AddGadgetItem(4, -1, "New Item Added...")
          
        Case 6 ; Remove
          RemoveGadgetItem(4, GetGadgetState(4)) ; Remove the current element of the ListView
          
        Case 7 ; Select
          SetGadgetText(0, GetGadgetText(4)) ; Get the current item from the ListView..
          
        Case 8 ; Quit...
          EventID = #PB_Event_CloseWindow
          
        Case 11 ; Enable PlugIn..
          DisableGadget(12, 1-GetGadgetState(11))
          
        Case 16 ;
          If GetGadgetState(13) : Result$ = GetGadgetText(13) : EndIf
          If GetGadgetState(14) : Result$ = GetGadgetText(14) : EndIf
          If GetGadgetState(15) : Result$ = GetGadgetText(15) : EndIf
          
          MessageRequester("Info", "Selected screen mode: "+Result$, 0)
          
        Case 17
          SetGadgetText(0, Str(GetGadgetState(17)))
          
      EndSelect
      
    EndIf
    
  Until EventID = #PB_Event_CloseWindow  
EndIf
End
Last edited by Thunder93 on Fri Apr 17, 2015 3:47 am, edited 4 times in total.
ʽʽSuccess is almost totally dependent upon drive and persistence. The extra energy required to make another effort or try another approach is the secret of winning.ʾʾ --Dennis Waitley
User avatar
TI-994A
Addict
Addict
Posts: 2700
Joined: Sat Feb 19, 2011 3:47 am
Location: Singapore
Contact:

Re: How to handle Windows UI scaling?

Post by TI-994A »

For a simple cross-platform solution (on Windows and OSX at least), we could borrow a page from HTML, and implement a percentage-based layout scheme. Here's a quick example to demonstrate this:

Code: Select all

;********************************************
; HTML-style percentage-based form layout
;
; Cross-platform (tested on Windows & OSX)
;
; by TI-994A - free to use, improve, share...
;
; 10th April 2015
;
;********************************************

ExamineDesktops()

;the screen size of the development machine
#devScrWidth = 1920
#devScrHeight = 1080

;the screen size of the executing machine
Global scrWidth.f = DesktopWidth(0)
Global scrHeight.f = DesktopHeight(0)

;forces aspect ratio to 16:9
If scrWidth / scrHeight < 1.7
  scrHeight = scrWidth / 1.7
EndIf

;for scaling horizontal values
Procedure.i dx(x)
  ProcedureReturn Int((((x / #devScrWidth) * 100) * scrWidth) / 100)
EndProcedure

;for scaling vertical values
Procedure.i dy(y)
  ProcedureReturn Int((((y / #devScrHeight) * 100) * scrHeight) / 100)
EndProcedure

;for scaling font sizes
Procedure fy(y)
  ProcedureReturn Int((scrHeight / #devScrHeight) * y)
EndProcedure


;===========
; demo code
;===========

CreateImage(0, dx(220), dy(220))
If StartDrawing(ImageOutput(0))
  Box(0, 0, dx(220), dy(220), $FFFFFF)
  For i = dx(100) To 1 Step -1
    Circle(dx(110), dy(110), i, Random($FFFFFF))
  Next i        
  StopDrawing()
EndIf  

LoadFont(0, "Arial", fy(14))
LoadFont(1, "Arial", fy(18))

wFlags = #PB_Window_SystemMenu | #PB_Window_ScreenCentered
OpenWindow(0, #PB_Any, #PB_Any, dx(640), dy(480), "DPI Aware Layout: Cross-Platform", wFlags)
ImageGadget(0, dx(210), dy(130), dx(220), dy(220), ImageID(0))
TextGadget(1, dx(10), dy(10), dx(270), dy(30), "top-left corner - font size: 14")
TextGadget(2, dx(240), dy(440), dx(390), dy(30), "bottom-right corner - font size: 18")

SetGadgetColor(1, #PB_Gadget_BackColor,RGB(128, 255, 255))
SetGadgetColor(2, #PB_Gadget_BackColor,RGB(128, 255, 255))
SetGadgetFont(1, FontID(0))
SetGadgetFont(2, FontID(1))

While WaitWindowEvent() ! #PB_Event_CloseWindow : Wend
Even easier if coupled with Thunder93's gadget macros. :wink:
Texas Instruments TI-99/4A Home Computer: the first home computer with a 16bit processor, crammed into an 8bit architecture. Great hardware - Poor design - Wonderful BASIC engine. And it could talk too! Please visit my YouTube Channel :D
User avatar
Thunder93
Addict
Addict
Posts: 1788
Joined: Tue Mar 21, 2006 12:31 am
Location: Canada

Re: How to handle Windows UI scaling?

Post by Thunder93 »

:lol:


Nicely done-up cross-platform solution TI-994A.

I would do a little something more with the Text Gadgets with usage of your cross-platform solution.

After the second TextGadget(), and so forth. I would use for instances;

Code: Select all

SetGadgetFont(2, FontID(1)) : ResizeGadget(2, #PB_Ignore, #PB_Ignore, #PB_Ignore, GadgetHeight(2, #PB_Gadget_RequiredSize))
Just simply leave TextGadget() height at 0 for simplicity, instead of dy(30) or whatever. Let the above example code do the proper height resizing for at least on the Text Gadgets. :wink:
ʽʽSuccess is almost totally dependent upon drive and persistence. The extra energy required to make another effort or try another approach is the secret of winning.ʾʾ --Dennis Waitley
Little John
Addict
Addict
Posts: 4777
Joined: Thu Jun 07, 2007 3:25 pm
Location: Berlin, Germany

Re: How to handle Windows UI scaling?

Post by Little John »

NicknameFJ wrote:http://www.purebasic.fr/english/viewtop ... re#p462177 see the post of Danilo
ozzie wrote:I use the procedures and macros included in the Forum posting DPI Aware Application.
I also use (a simplified version of) this code, which essentially is similar to Danilo's code mentioned above.

Both codes give us something like

Code: Select all

ScaleDPIx = GetDeviceCaps_(GetDC_(0), #LOGPIXELSX) / 96
ScaleDPIy = GetDeviceCaps_(GetDC_(0), #LOGPIXELSY) / 96
Question to the experts:
Is it really necessary to deal separately with ScaleDPIx and ScaleDPIy in this context?
Can't we safely assume that both factors are always the same?

According to my experience (with Windows XP and Windows 7), they can not be set separately anyway.
The user can only set one factor, which applies to both x and y:

Image

Dealing with only ony "ScaleDPI" factor instead of two would allow to write somewhat simpler code.
User avatar
Thunder93
Addict
Addict
Posts: 1788
Joined: Tue Mar 21, 2006 12:31 am
Location: Canada

Re: How to handle Windows UI scaling?

Post by Thunder93 »

Computer monitors have square pixels. Typically LOGPIXELSX and LOGPIXELSY metrics will be the same. However, using CRT, you can have rectangular square, like using 320x200 or 320x400 resolution on 4:3 monitor (these resolution were actually used). On LCD you can get rectangular pixels by using non-native resolution on monitor - widescreen resolution on 5:4 monitor and vice versa.

Other types of video screens, including NTSC televisions, have rectangular or non-square pixels. Also, some input devices, such as Digital Video (DV) cameras, have charged couple devices with non-square pixels. Its even common for printers to have non-square pixels.
ʽʽSuccess is almost totally dependent upon drive and persistence. The extra energy required to make another effort or try another approach is the secret of winning.ʾʾ --Dennis Waitley
User avatar
luis
Addict
Addict
Posts: 3893
Joined: Wed Aug 31, 2005 11:09 pm
Location: Italy

Re: How to handle Windows UI scaling?

Post by luis »

Little John wrote: Is it really necessary to deal separately with ScaleDPIx and ScaleDPIy in this context?
Can't we safely assume that both factors are always the same?
...
According to my experience (with Windows XP and Windows 7), they can not be set separately anyway
The screenshot from Windows it is where you can select your scaling, and it's ONE number because it does the same scaling on both X and Y.

But the two numbers you get with the API (the number of pixels per logical inch along the screen width/height) could be potentially different.
If your question is if you could just use one of them because you always saw them identical, then the answer is no even if screens (so a specific class of device contexts) tend to have square pixels (and so the same pixel density along both axis).

But the answer is no :wink:
"Have you tried turning it off and on again ?"
A little PureBasic review
Little John
Addict
Addict
Posts: 4777
Joined: Thu Jun 07, 2007 3:25 pm
Location: Berlin, Germany

Re: How to handle Windows UI scaling?

Post by Little John »

Hi,

thanks for your replies.

I personally only remembered non-square pixels from EGA, and I was under the impression that now on modern displays pixels are always quadratic. Now I know that this assumption was wrong. :-)

Thank you!
Post Reply