Getting Windows scaling factor using declares

Hello,
I’m using an older version of Xojo, and don’t want to move up to the latest version just yet.
I need to get the scaling factor of Windows.
I’ve used the method at http://blog.xojo.com/2013/11/18/writing_high-dpi_aware_windows_apps/ , thus:

[code]Declare Function GetDC Lib “user32” (hWnd As Ptr) As Ptr
Declare Function GetDeviceCaps Lib “gdi32” _
(hdc As Ptr, nIndex As Integer) As Integer
Declare Sub ReleaseDC Lib “user32” (hWnd As Ptr, hdc As Ptr)

Const LOGPIXELSX = 88
Const LOGPIXELSY = 90

Dim hdc As Ptr = GetDC(Nil)
Dim dpiX As Integer = GetDeviceCaps(hdc, LOGPIXELSX)
Dim dpiY As Integer = GetDeviceCaps(hdc, LOGPIXELSY) ReleaseDC(Nil, hdc)

Dim scaleFactorX As Double = dpiX / 96
Dim scaleFactorY As Double = dpiY / 96[/code]

but it’s not working - it’s telling me that the scale factors are both 1.

I’m currently running a Retina Mac with a non-retina screen attached to it, with Parallels running on it. I’ve tried on both screens, and I’ve tried it with both screens being the primary screen, in case it only reports the scaling factor of the primary screen.

Can anyone tell me how to get the scaling factor, either using declares, or MBS plugins?

(The reason I need this is that the printing software we use will print at 100/, so on HiDPI displays, it’s printing at half size.)

Thanks!

What version of Windows?

In 8.1 or later you can use this convoluted technique, where you set the process DPI awareness then use GetDpiForMonitor as per https://msdn.microsoft.com/en-us/library/windows/desktop/dn280510(v=vs.85).aspx

I’m unsure of the version of Windows; I guess it could be anything which supports HiDPI (so including Win7, sadly…)

What I don’t understand is why the above code - copied from the Xojo website - doesn’t report any scaling.

I’m pretty sure that unless your app is HighDPIAware, the OS always lies to you and says the scale factor is “1.0”.

They mention this on the page under Enabling DPI-aware mode

They who? Xojo or Microsoft?
Could you post a link to this page?
Thank you :slight_smile:

hi hamish, when i set the text size to medium on windows 8 from small, i get 1.25 when i try the code you post on the top. when on the small text size, i get 1 for the scale value.

[quote=261674:@Tim Parnell]They who? Xojo or Microsoft?
Could you post a link to this page?
Thank you :)[/quote]
Tim, the link I’m referring to is in the very first post of the thread.

If I am not mistaken, you cannot get the scaling factor with older versions because it requires an HiDPI aware app, as declared in the manifest. Otherwise the system will simply report the current screen resolution.

You may want to use a helper created in 2016R1 in HiDPI mode that will give you the scale.

Oh, ok, thanks.
So, is there no way at all to get the scaling factor without making the app HiDPI aware?
Don’t suppose @Christian Schmitz has anything?

You didnt mention it in your original post, but did you call the following code on startup?

Declare Function SetProcessDPIAware Lib "user32" () As Boolean If Not SetProcessDPIAware Then MsgBox "Error enabling DPI aware mode." End If

I didn’t, no, but I (mistakenly, it seems) thought that that required the latest version of the IDE.

You may want to have a look here : https://technet.microsoft.com/en-us/library/dn528846.aspx

The scaling is also available in the registry. See How DPI Scaling works in Windows 8.1 - gHacks Tech News

At any rate the app will remain unable to manage HiDPI.

Ummm, he just wont have access to the latest xojo framework which has HiDPI built in, but he should be able to manage HiDPI himself using native windows calls as per the link he posted to the 2013 article? Or am I missing something?

OK; now tried setting that in the Open event of my app. But that makes all the UI half the size it should be. All I want is to determine the scale factor of the screen; I don’t want to make the app itself HiDPI aware. I don’t want to use a helper app either.
Tried reading HKEY_CURRENT_USER\Control Panel\Desktop’s LogPixels key, but there isn’t one.

What I meant is that the app itself will continue believing what the scale shows it, ie lower resolution.

What is nice in 2016R1 is that all that is taken care of. Hence my suggestion above to create a small helper in 2016R1 just to tell the scale, while he can keep his older version for the app.

I just played around with SetProcessDpiAwareness, once the DLLs are loaded in for the app, they have their DPI set for life so DPI awareness cant be turned off, which is a shame.

It’ll be in HKEY_CURRENT_USER\Control Panel\Desktop\PerMonitorSettings\DEL409375DD16FB_01_07DF_66^0F17F725A250061E11BAAA27972F16D9\DpiValue

0 = 100%
1 = 125%
2 = 150%
etc

where that big string will be the ID of the monitor you’re changing. Have a look around in there, change a dpi setting on the monitor and refresh the value.

OK, things are getting more confusing.

  1. I don’t have a PerMonitorSettings subfolder as you describe if I look in RegEdit.
  2. If I use RegEdit, then the key is at HKEY_CURRENT_USER\Control Panel\Desktop and called LogPixels
  3. If I use the below code, LogPixels is missing.
    Very confused!

H

[code]
// get a registry key
Dim reg As New RegistryItem(“HKEY_CURRENT_USER\Control Panel\Desktop”)

Dim lines() As String

// now we look on all values on this key
For i As Integer = 0 To reg.KeyCount- 1
Dim name As String = reg.Name(i)
Dim value As Variant = reg.Value(i)
lines.Append(name + " -> " + value)
Next

// and display them
MsgBox(Join(lines, EndOfLine))[/code]

Its there, I highly suggest you use system.debuglog for things like this rather than msgbox.

There’s some string formatting that is doesnt like in the middle of those registry entries and it drops half of the text.

Click this icon at the bottom of the xojo window to see the output:

[code] // get a registry key
Dim reg As New RegistryItem(“HKEY_CURRENT_USER\Control Panel\Desktop”)

Dim lines() As String

// now we look on all values on this key
For i As Integer = 0 To reg.KeyCount- 1
Dim name As String = reg.Name(i)
Dim value As Variant = reg.Value(i)
system.debuglog(name + " -> " + str(value))
Next[/code]

That string (HKEY_CURRENT_USER\Control Panel\Desktop\LogPixels) should be fine for computers with a single monitor or with combined monitors. If it doesnt, it will update on the key that I posted above.

Ah! Kudos.