GUI sample of high DPI screen using PowerShell

Viewed 233

Do you know the sample code of the GUI screen for high DPI implemented by PowerShell in the official information of Microsoft? I couldn't find it and created the sample code myself. But I don't think this is enough. I want to make smarter coding.

mysample codes

For example, one of the sample codes is here (Based on the sample code of the custom input box Creating a Custom Input Box) :

#this sample is Based on is microsoft sample thit is Creating a Custom Input Box
#URL:https://docs.microsoft.com/en-us/powershell/scripting/samples/creating-a-custom-input-box?view=powershell-7.2

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

$form = New-Object System.Windows.Forms.Form
$form.Text = 'Data Entry Form'
$form.Size = New-Object System.Drawing.Size(300,200)
$form.StartPosition = 'CenterScreen'

#For High DPI, We Set AutoScaleDimensions and AutoScaleMode
#The reason SizeF is set to 96 is that the standard Windows resolution for the display is 96.
#Maybe you shuld try that All object resets Drawing.Point And Drawing.Size
#In some cases, review the Drawing.Point and Drawing.Size of all objects, depending on the resolution of your display.
$form.AutoScaleDimensions =  New-Object System.Drawing.SizeF(96, 96)
$form.AutoScaleMode  = [System.Windows.Forms.AutoScaleMode]::Dpi

$okButton = New-Object System.Windows.Forms.Button
$okButton.Location = New-Object System.Drawing.Point(75,220)
$okButton.Size = New-Object System.Drawing.Size(75,50)
$okButton.Text = 'OK'
$okButton.DialogResult = [System.Windows.Forms.DialogResult]::OK
$form.AcceptButton = $okButton
$form.Controls.Add($okButton)

$cancelButton = New-Object System.Windows.Forms.Button
$cancelButton.Location = New-Object System.Drawing.Point(150,220)
$cancelButton.Size = New-Object System.Drawing.Size(200,50)
$cancelButton.Text = 'Cancel'
$cancelButton.DialogResult = [System.Windows.Forms.DialogResult]::Cancel
$form.CancelButton = $cancelButton
$form.Controls.Add($cancelButton)

$label = New-Object System.Windows.Forms.Label
$label.Location = New-Object System.Drawing.Point(10,20)
$label.Size = New-Object System.Drawing.Size(800,40)
$label.Text = 'Please enter the information in the space below:'
$form.Controls.Add($label)

$textBox = New-Object System.Windows.Forms.TextBox
$textBox.Location = New-Object System.Drawing.Point(10,100)
$textBox.Size = New-Object System.Drawing.Size(800,20)
#For High DPI, We Set Font Size
#In Japanese, "Yu Gothic UI" is the best font type. However, this font is for Japan only. Therefore, the default font definition is undefined.
#$Font = New-Object System.Drawing.Font("Yu Gothic UI",45,([System.Drawing.FontStyle]::Regular),[System.Drawing.GraphicsUnit]::Pixel)
$Font = New-Object System.Drawing.Font("",45,([System.Drawing.FontStyle]::Regular),[System.Drawing.GraphicsUnit]::Pixel)
$textBox.Font =  $Font 

$form.Controls.Add($textBox)

$form.Topmost = $true

$form.Add_Shown({$textBox.Select()})
$result = $form.ShowDialog()

if ($result -eq [System.Windows.Forms.DialogResult]::OK)
{
    $x = $textBox.Text
    $x
}

my custom points

  • Set AutoScaleDimensions and AutoScaleMode
#For High DPI, We Set AutoScaleDimensions and AutoScaleMode
#The reason SizeF is set to 96 is that the standard Windows resolution for the display is 96.
#Maybe you shuld try that All object resets Drawing.Point And Drawing.Size
#In some cases, review the Drawing.Point and Drawing.Size of all objects, depending on the resolution of your display.
$form.AutoScaleDimensions =  New-Object System.Drawing.SizeF(96, 96)
$form.AutoScaleMode  = [System.Windows.Forms.AutoScaleMode]::Dpi
  • Set Font Size for Some parts (ex:textbox)
#For High DPI, We Set Font Size for 
([System.Drawing.FontStyle]::Regular),[System.Drawing.GraphicsUnit]::Pixel)
$Font = New-Object System.Drawing.Font("",45,([System.Drawing.FontStyle]::Regular),
$textBox.Font =  $Font
  • Trial and error (resetting Drawing.Point and Drawing.Size for all objects)

Points to improve

I don't want to reset Drawing.Point and Drawing.Size. I want to use the same value for all display types.

Link

Regards

2 Answers

This is what I have found working in my last PowerShell GUI. At the start of your script call SetProcessDPIAware() to tell the OS that your GUI is DPI-aware and it doesn't try to scale it on its own which results in blurry text. This is a native API, so you need P/Invoke:

Add-Type -TypeDefinition @'
using System.Runtime.InteropServices;
public class ProcessDPI {
    [DllImport("user32.dll", SetLastError=true)]
    public static extern bool SetProcessDPIAware();      
}
'@
$null = [ProcessDPI]::SetProcessDPIAware()

After that enable visual styles (propably unrelated to DPI scaling, lets your GUI look more modern):

[System.Windows.Forms.Application]::EnableVisualStyles()

To have [System.Windows.Forms.AutoScaleMode]::Dpi work, call $form.SuspendLayout() immediately after creating the form and $form.ResumeLayout() when you have created and positioned all controls. This is important so that all controls will be positioned and sized with correct scaling according to DPI.

Call SuspendLayout() set $form.AutoScaleDimensions and $form.AutoScaleMode before changing form size. Maybe the order isn't important, but in my code it works this way.

Instead of setting $form.Size which is the outer form size, set $form.ClientSize so you don't need to know frame and caption size, which depends on OS version and user style settings.

$form = New-Object System.Windows.Forms.Form

# Very important to correctly size and position all controls!
$form.SuspendLayout()

$form.AutoScaleDimensions =  New-Object System.Drawing.SizeF(96, 96)
$form.AutoScaleMode  = [System.Windows.Forms.AutoScaleMode]::Dpi

$form.Text = 'Data Entry Form'
$form.ClientSize = New-Object System.Drawing.Size(300,200)
$form.StartPosition = 'CenterScreen'

$okButton = New-Object System.Windows.Forms.Button
$okButton.Location = New-Object System.Drawing.Point(75,220)
$okButton.Size = New-Object System.Drawing.Size(75,50)
$okButton.Text = 'OK'
$okButton.DialogResult = [System.Windows.Forms.DialogResult]::OK
$form.AcceptButton = $okButton
$form.Controls.Add($okButton)

$cancelButton = New-Object System.Windows.Forms.Button
$cancelButton.Location = New-Object System.Drawing.Point(150,220)
$cancelButton.Size = New-Object System.Drawing.Size(200,50)
$cancelButton.Text = 'Cancel'
$cancelButton.DialogResult = [System.Windows.Forms.DialogResult]::Cancel
$form.CancelButton = $cancelButton
$form.Controls.Add($cancelButton)

# Very important to correctly size and position all controls!
$form.ResumeLayout()

Thank you for your answer. I tryed to remake a sample code I don't need to know frame and caption size, which depends on OS version and user style settings!

Remade sample code

#this sample is Based on is microsoft sample thit is Creating a Custom Input Box
#URL:https://docs.microsoft.com/en-us/powershell/scripting/samples/creating-a-custom-input-box?view=powershell-7.2

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

#--- For High DPI, Call SetProcessDPIAware(need P/Invoke) and EnableVisualStyles ---
Add-Type -TypeDefinition @'
using System.Runtime.InteropServices;
public class ProcessDPI {
    [DllImport("user32.dll", SetLastError=true)]
    public static extern bool SetProcessDPIAware();      
}
'@
$null = [ProcessDPI]::SetProcessDPIAware()
[System.Windows.Forms.Application]::EnableVisualStyles()


$form = New-Object System.Windows.Forms.Form

#--- For High DPI, First Call SuspendLayout(),After that, Set AutoScaleDimensions, AutoScaleMode ---
# SuspendLayout() is Very important to correctly size and position all controls!
$form.SuspendLayout()
$form.AutoScaleDimensions =  New-Object System.Drawing.SizeF(96, 96)
$form.AutoScaleMode  = [System.Windows.Forms.AutoScaleMode]::Dpi

$form.Text = 'Data Entry Form'
$form.Size = New-Object System.Drawing.Size(300,200)
$form.StartPosition = 'CenterScreen'

$okButton = New-Object System.Windows.Forms.Button
$okButton.Location = New-Object System.Drawing.Point(75,120)
$okButton.Size = New-Object System.Drawing.Size(75,23)
$okButton.Text = 'OK'
$okButton.DialogResult = [System.Windows.Forms.DialogResult]::OK
$form.AcceptButton = $okButton
$form.Controls.Add($okButton)

$cancelButton = New-Object System.Windows.Forms.Button
$cancelButton.Location = New-Object System.Drawing.Point(150,120)
$cancelButton.Size = New-Object System.Drawing.Size(75,23)
$cancelButton.Text = 'Cancel'
$cancelButton.DialogResult = [System.Windows.Forms.DialogResult]::Cancel
$form.CancelButton = $cancelButton
$form.Controls.Add($cancelButton)

$label = New-Object System.Windows.Forms.Label
$label.Location = New-Object System.Drawing.Point(10,20)
$label.Size = New-Object System.Drawing.Size(280,20)
$label.Text = 'Please enter the information in the space below:'
$form.Controls.Add($label)

$textBox = New-Object System.Windows.Forms.TextBox
$textBox.Location = New-Object System.Drawing.Point(10,40)
$textBox.Size = New-Object System.Drawing.Size(260,20)
#For High DPI, Set Font Size 
#In Japanese, "Yu Gothic UI" is the best font type. However, this font is for Japan only. Therefore, the default font definition is undefined.
#$Font = New-Object System.Drawing.Font("Yu Gothic UI",45,([System.Drawing.FontStyle]::Regular),[System.Drawing.GraphicsUnit]::Pixel)
$Font = New-Object System.Drawing.Font("",45,([System.Drawing.FontStyle]::Regular),[System.Drawing.GraphicsUnit]::Pixel)
$textBox.Font =  $Font 

$form.Controls.Add($textBox)

$form.Topmost = $true

$form.Add_Shown({$textBox.Select()})

#--- For High DPI, Finally, Call ResumeLayout(),before ShowDialog() ---
# ResumeLayout() is Very important to correctly size and position all controls!
$form.ResumeLayout()

$result = $form.ShowDialog()

if ($result -eq [System.Windows.Forms.DialogResult]::OK)
{
    $x = $textBox.Text
    $x
}


However, I need to use a large font size for tuning

I'm adding code to solve the problem that the textbox is elongated. using the big font size of the textbox.

#For High DPI, Set Font Size 
#In Japanese, "Yu Gothic UI" is the best font type. However, this font is for Japan only. Therefore, the default font definition is undefined.
#$Font = New-Object System.Drawing.Font("Yu Gothic UI",45,([System.Drawing.FontStyle]::Regular),[System.Drawing.GraphicsUnit]::Pixel)
$Font = New-Object System.Drawing.Font("",45,([System.Drawing.FontStyle]::Regular),[System.Drawing.GraphicsUnit]::Pixel)

Why are text boxes elongated?

For text boxes, is tuning the font size for each object a smart way? If possible, I also want to remove the resizing process that uses the font size.

Related