1

Hi everyone I am curious on how it's possible to make a winform DPI aware when creating it in PowerShell? Or at the very least, prevent it from autoscaling. I've googled it and searched and searched but I just can't seem to find an answer or an example of how to do it. The most common answer is to include it in a manifest, but this is not a viable option for PowerShell.

If anything I just want to prevent Windows from automatically rescaling my forms in DPI higher than 96 (100%). I tried AutoScaleMode = "DPI" and that unfortunately doesn't work and doesn't seem to do anything, as setting it to "None" or not including it at all is the same result.

A quick example...

Add-Type -AssemblyName 'System.Windows.Forms'
Add-Type -AssemblyName 'System.Drawing'

$Dialog = New-Object Windows.Forms.Form
$Dialog.Text = 'Main'
$Dialog.Size = New-Object Drawing.Size(200, 100)
$Dialog.AutoScaleMode = "DPI"

$Label = New-Object Windows.Forms.Label
$Label.Size = New-Object Drawing.Size(200, 16)
$Label.Location = New-Object Drawing.Size(10, 20)
$Label.Text = 'This text is to test autoscaling.'
$Dialog.Controls.Add($Label)

$Dialog.ShowDialog()

The image on the left is autoscaled and blurry. I don't want this, I want it to look like the right. If I can get that far, I'll try to figure out how I'm going to handle the scaling.

Bighead
  • 75
  • 6
  • You want it to not scale according to OS DPI scaling at all, or you want it to just not be blurry when auto scaled? – Mathias R. Jessen Sep 15 '20 at 17:47
  • Honestly I would like to know how to do both so I can experiment a bit with it. If I can get DPI scaling working correctly, then I would try that out. If not, then I can manually try to adjust all the scaling based on DPI. – Bighead Sep 15 '20 at 17:52
  • Check this GitHub (test) project: [PSPreferExternalManifest](https://github.com/dotps1/PSPreferExternalManifest). It handles the `PreferExternalManifest` registry key to load a manifest that activates/deactivates the `DpiAware` option. – Jimi Sep 15 '20 at 18:36
  • It doesn't make sense to close an older question as duplicate of a newer question. – Reza Aghaei Feb 18 '23 at 20:16

2 Answers2

1

So I did manage to find a workaround by accident. I was looking into WPF forms (which I know little about) and came across an example. Adding the bare minimum of a dummy window in WPF that never actually gets shown, somehow prevents winforms from automatically scaling.

# Load assemblies.
Add-Type -AssemblyName 'System.Windows.Forms'
Add-Type -AssemblyName 'System.Drawing'
Add-Type -AssemblyName 'PresentationFramework'

# Dummy WPF window (prevents auto scaling).
[xml]$Xaml = @"
<Window
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    x:Name="Window">
</Window>
"@
$Reader = (New-Object System.Xml.XmlNodeReader $Xaml)
$Window = [Windows.Markup.XamlReader]::Load($Reader)

# Business as usual.
$Dialog = New-Object Windows.Forms.Form
$Dialog.Text = 'Main Window'
$Dialog.Size = New-Object Drawing.Size(200, 100)

$Label = New-Object Windows.Forms.Label
$Label.Size = New-Object Drawing.Size(200, 16)
$Label.Location = New-Object Drawing.Size(10, 20)
$Label.Text = 'This text is to test autoscaling.'
$Dialog.Controls.Add($Label)

$Dialog.ShowDialog()
Bighead
  • 75
  • 6
0

Old question, but interesting. And it's possible to make the form DPI aware without a dummy WPF window. The following example uses SetProcessDPIAware to make the form DPI aware:

using assembly System.Windows.Forms
using namespace System.Windows.Forms
using namespace System.Drawing

#Enable visual styles
[Application]::EnableVisualStyles()

#Enable DPI awareness
$code = @"
    [System.Runtime.InteropServices.DllImport("user32.dll")]
    public static extern bool SetProcessDPIAware();
"@
$Win32Helpers = Add-Type -MemberDefinition $code -Name "Win32Helpers" -PassThru
$null = $Win32Helpers::SetProcessDPIAware()

$form = [Form] @{
    ClientSize = [Point]::new(300, 80);
    StartPosition = "CenterScreen";
    Text = "Test";
    AutoScaleDimensions = [SizeF]::new(6, 13);
    AutoScaleMode = [AutoScaleMode]::Font;
}
$label = [Label] @{
    Text = "Hello, world!";
    AutoSize = $true;
    Location = [Point]::new(8,8)
}
$form.Controls.Add($label)

$null = $form.ShowDialog()
$form.Dispose()

You can see the difference, with SetProcessDPIAware:

enter image description here

Without SetProcessDPIAware:

enter image description here

Reza Aghaei
  • 120,393
  • 18
  • 203
  • 398