Author | Topic: Bug in AppDesktop():CurrentSize() | |
---|---|---|
Itai Ben-Artzi | Bug in AppDesktop():CurrentSize() on Tue, 20 Oct 2015 19:15:16 -0700 I’ve setup screen resolution to 1920 x 1200. AppDesktop():CurrentSize() = {1920,1200} I’ve changed desktop font size to 150% (screen resolution kept at 1920 X 1200). AppDesktop:CurrentSize() = {1280,800} Can this bug be fixed? Is there a way to retrieve screen resolution independent of desktop font-size? Many thanks, -Itai | |
Andreas Gehrs-Pahl | Re: Bug in AppDesktop():CurrentSize() on Thu, 22 Oct 2015 01:22:34 -0400 Itai, >Iʼve setup screen resolution to 1920 x 1200. >AppDesktop():CurrentSize() = {1920,1200} >Iʼve changed desktop font size to 150% (screen resolution kept at 1920 X >1200). >AppDesktop:CurrentSize() = {1280,800} >Can this bug be fixed? This is called "DPI Virtualization" and is correct behavior, so it doesn't need to be fixed. On Windows Vista and higher, Windows APIs report a virtual resolution, based on the actual Screen Resolution and the applied scaling factor, leaving the (reported) DPI at the default of 96 DPI. That way, the entire application dialog is transparently scaled by the OS, not only the fonts. This feature allows applications that are "not DPI aware" appear the same as if the resolution was changed, even though they might look "blurry", as they are scaled by the Desktop Window Manager (DWM). In Windows Vista, the text isn't scaled correctly, but in Windows 7 and later the text is also scaled. >Is there a way to retrieve screen resolution independent of desktop >font-size? Yes, to change this behavior (for all applications), select "Control Panel" ==> "Appearance and Personalization" ==> "Display" and from that dialog the: "Set custom text size (DPI)" option on the left (this is for Windows 7, other OS versions might be slightly different). On the popup dialog, select the "Use Windows XP style DPI scaling" check box and [Apply] the settings. After Log-off or Restart, the OS will report the original resolution (of 1920 x 1200) with an adjusted DPI setting (for fonts), which will be 120 DPI (for the "Medium - 125%" setting) or 144 DPI (for the "Larger - 150%") setting, instead of the default of 96 DPI (for the "Smaller - 100%" setting). DPI virtualization is by default enabled when a scale factor of greater than 120 (125 percent) is selected. But it can be disabled (or enabled) with this check box for any scale (or DPI) setting. You can also change this for just a particular application, by selecting the Compatibility tab on the Properties dialog, and then select the box labeled "Disable display scaling on high DPI settings". Another option to disable DPI virtualization for a particular application, is to supply a manifest file for the application with the <dpiAware>true</dpiAware> setting. Additionally, you can use the SetProcessDPIAware() Windows API function to change the setting at runtime, but MS discourages doing this. To check if the above-mentioned check box has been selected, you can also read the "UseDpiScaling" value of the following Registry key: HKEY_CURRENT_USER\Software\Microsoft\Windows\DWM. If it is set to 0 (Zero) (a DWord), then the check box is selected (XP-style scaling is used). If it is set to 1, then the check box is not selected (and DPI virtualization is used). You can verify (and experiment with) this using the Windows API functions GetClientRect() and GetDeviceCaps(). Here is what I use: Function GetDeskTopSize() ************************************************************************* * Used to get the actual, current Desktop Size, as this value is not updated correctly, if the Deskop resolution is changed during program execution, and "AppDektop():CurrentSize() always reports the original settings. See also PDR 109-4244 for details. * ************************************************************************* LOCAL nHWnd := AppDesktop():GetHWnd() LOCAL nWidth := 0 LOCAL nHeight := 0 LOCAL cBuffer := U2Bin(0) + U2Bin(0) + U2Bin(nWidth) + U2Bin(nHeight) DllCall("User32.DLL", DLL_STDCALL, "GetClientRect", nHWnd, @cBuffer) nWidth := Bin2U(substr(cBuffer, 9, 4)) nHeight := Bin2U(substr(cBuffer, 13, 4)) return ({nWidth, nHeight}) Function GetWindowsFontsDPI(lWidth) LOCAL lHeight := iif(lWidth == NIL, .t., .not. lWidth) LOCAL nHeight := iif(lHeight, LOGPIXELSY, LOGPIXELSX) LOCAL nHWnd := AppDesktop():GetHWnd() LOCAL nHDC := DllCall("User32.DLL", DLL_STDCALL, "GetDC", nHWnd) LOCAL nLogPix := 96 default for Small Fonts (100%) if nHDC # 0 nLogPix := DllCall("GDI32.DLL", DLL_STDCALL, "GetDeviceCaps", nHDC, nHeight) DllCall("User32.DLL", DLL_STDCALL, "ReleaseDC", nHWnd, nHDC) endif return (nLogPix) For more information, see also this MS article on "Writing DPI-Aware Desktop and Win32 Applications": https://msdn.microsoft.com/en-us/library/windows/desktop/dn469266(v=vs.85).aspx Hope this helps, Andreas Andreas Gehrs-Pahl Absolute Software, LLC phone: (989) 723-9927 email: Andreas.GP@Charter.net web: http://www.Aerospace-History.net | |
Itai Ben-Artzi | Re: Bug in AppDesktop():CurrentSize() on Thu, 22 Oct 2015 20:37:14 -0700 Thank you! Thank you! Thank you, Andreas!!! This is valuable info well delivered. One more follow-up question: Can I set (via manifest or otherwise) the application to 96 DPI (100%) regardless of the computer settings? Many thanks, -Itai | |
Andreas Gehrs-Pahl | Re: Bug in AppDesktop():CurrentSize() on Fri, 23 Oct 2015 02:05:42 -0400 Itai, >Thank you! Thank you! Thank you, Andreas!!! >This is valuable info well delivered. You are welcome. >One more follow-up question: >Can I set (via manifest or otherwise) the application to 96 DPI (100%) >regardless of the computer settings? Yes, if you (always) enable DPI virtualization, the DWM will do the scaling of your application, and the application will think it is at 96 DPI (100%) regardless of the computer's actual settings. But this is what you didn't like, according to your original post, because the OS APIs will report a lower resolution than the one actually set, while the DWM will do the scaling for you. I haven't tried it, but using <dpiAware>false</dpiAware> in your manifest file might do exactly that -- enable DPI virtualization at any scale factor. Follow the link to the MS article about DPI-aware applications at the end of my previous post. It explains a lot of this in detail and the differences between the various OS versions. As a general note, the best option would be to actually create a DPI-aware application and to size all GUI elements and fonts according to the selected scaling factor (DPI setting) and resolution at runtime. This would result in a much better resolution (no blurriness) and no GUI rendering issues -- like the ones mentioned in the MS article. Maybe Alaska could add such a feature to their future layout manager/visual designer in Xbase++ Version 3.0, allowing for automatic, out-of-the-box, DPI-aware GUI elements and behavior. Especially since Windows 8.1 introduced dynamic DPI scaling (and the corresponding events). Andreas Andreas Gehrs-Pahl Absolute Software, LLC phone: (989) 723-9927 email: Andreas.GP@Charter.net web: http://www.Aerospace-History.net | |
Itai Ben-Artzi | Re: Bug in AppDesktop():CurrentSize() on Thu, 22 Oct 2015 23:46:39 -0700 Great! good advice. I'll simply scale the font as needed. -Itai | |
Itai Ben-Artzi | Re: Bug in AppDesktop():CurrentSize() on Thu, 22 Oct 2015 21:20:06 -0700 Andreas, Including <dpiAware>true</dpiAware> in the manifest yields run-time error. Could you please provide a sample how/where to insert this line? Many thanks, -Itai | |
Itai Ben-Artzi | Re: Bug in AppDesktop():CurrentSize() on Thu, 22 Oct 2015 22:06:09 -0700 OK, I've found it: <asmv3:application> <asmv3:windowsSettings xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings"> <dpiAware>true</dpiAware> </asmv3:windowsSettings> </asmv3:application> |