http://qs321.pair.com?node_id=1176356

Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

Hi Monks

I have a general question regarding Tk applications running on Windows 10 (but the same should also apply to Windows 8.1) with size scaling activated. I am experiencing that the Apps created with Tk (latest Version) are not displayed correctly, meaning the Fonts are blurred and it is Looks like there is a foggy layer on the GUI. I know that is is certanly connected with Windows, but I would like to hear your experience on this... and some Workarounds, if any.

Replies are listed 'Best First'.
Re: Tk Windows 10 Scaling
by Anonymous Monk on Nov 22, 2016 at 23:07 UTC
    windows 10 scaling blurry says Disable DPI virtualization for the application. To do this, right-click the application's shortcut and then click Properties. On the Compatibility tab, select Disable Display Scaling On High DPI Settings, and then click OK.
Re: Tk Windows 10 Scaling
by chrstphrchvz (Scribe) on Jun 23, 2019 at 01:34 UTC

    There are a few ways that an application can tell Windows to not upscale/resample it for high-DPI displays (which it does for compatibility at the expense of appearance quality). Microsoft's recommended approach is to use an application manifest, rather than setting DPI awareness programmatically.

    But for standalone scripts, setting DPI awareness programmatically seems easier—so much so that I haven't even attempted the application manifest approach :^). The simplest approach might be to invoke SetProcessDPIAware() from User32.dll, which is present in Vista and later. (Newer DPI awareness functions exist in Windows 8.1/10 which allow more specific settings, but I'm not sure Tk would take advantage of them.) That function can be invoked from XS, or from a Perl script by using a module like Win32::API:

    # Make sure to do this **before** calling MainWindow->new
    if ($^O eq 'MSWin32') {
        require Win32::API;
        # See https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-setprocessdpiaware
        my $SetProcessDPIAware = Win32::API::More->new('User32', 'BOOL SetProcessDPIAware()');
        $SetProcessDPIAware->Call() or warn 'Failed to set process DPI awareness';
    }

    This approach works in Perl/Tk, as well as any of the wrappers for modern Tcl/Tk such as Tcl::pTk (disclaimer: I maintain this). There are very likely to be caveats to this approach; for example, although the value of $widget->scaling will be correctly updated, some elements like images will not be resized, and may appear smaller than expected.

    Edit 2019-06-24: use Win32::API should instead be require Win32::API . Thanks vkon for catching this.

      Something to be aware of: very recent versions of Windows support "per-monitor DPI awareness", meaning that separate displays can use different logical pixel densities; previously, all displays would use the same logical pixel density. Perl/Tk does not support per-monitor DPI awareness on Windows, and I believe adding support for it would be difficult. Rescaling (fuzziness) will be observed for Tk programs when toplevels are moved between displays with differing logical pixel densities. One issue encountered in upstream Tcl/Tk (and which likely affects Perl/Tk) is that this rescaling is not done correctly for overrideredirect toplevels (https://core.tcl-lang.org/tk/info/a9ee44102b); it is not clear if this is due to a Tk bug or a Windows bug.