I'm working on a PowerShell script that uses forms and panels that are docked. I was able to create the form and panels just fine, but I'm having issues getting a listbox to resize during runtime using $inputbox.Bottom = $form.Height - 215 to control the size, but I recieve the error
'Bottom' is a read-only property.
Simply using Fill in the panel will not work because I have buttons above and below the listbox. Here is a sample of my code:
[void] [System.Reflection.Assembly]::LoadWithPartialName(“System.Windows.Forms”)
[void] [System.Reflection.Assembly]::LoadWithPartialName(“System.Drawing”)
$form.ResizeEnd
$form = New-Object System.Windows.Forms.Form
$form.Size = New-Object System.Drawing.Size(1040,459)
$form.KeyPreview = $true
$form.StartPosition = ‘centerscreen’
$form.BackColor = 'MidnightBlue'
$form.Add_KeyDown({if($_.KeyCode -eq "Escape"){$form.Close()}})
$form.Text = "Dialog Box 2.0"
$form.Icon = [system.drawing.icon]::ExtractAssociatedIcon($PSHOME + "\powershell_ise.exe")
$buttonPanel3 = New-Object Windows.Forms.Panel
$buttonPanel3.Size = New-Object Drawing.Size #(290,70)
$buttonPanel3.Dock = "left"
$buttonPanel3.BackColor = 'Blue'
$inputbox = New-Object System.Windows.Forms.ListBox
$inputbox.BorderStyle = 'NONE'
$inputbox.Font = New-Object System.Drawing.Font(“segoe UI”,9)
$inputbox.SelectionMode = "MultiExtended"
$inputbox.Left = 10
$inputbox.Top = 105
$inputbox.Width = 200
$inputbox.Bottom = $form.Height -215
$inputbox.Height = $form.Height -215
$buttonPanel3.Controls.Add($inputbox)
$form.Controls.Add($buttonPanel3)
$form.ShowDialog()
If someone could give some sample code of a listbox that resizes (mainly concerned with vertical expansion) when you resize the form that would be excellent.
I ended up completely rearranging my form and using the fill method, but I wanted to put in a tidbit about form resizing since that was the true issue here.
The resize handler for the form would be $form.Add_Resize({}). Inside the brackets I could modify the height and width properties as desired. In this case, I only wanted the height property, so the code would be like:
[void] [System.Reflection.Assembly]::LoadWithPartialName(“System.Windows.Forms”)
[void] [System.Reflection.Assembly]::LoadWithPartialName(“System.Drawing”)
$form.ResizeEnd
$form = New-Object System.Windows.Forms.Form
$form.Size = New-Object System.Drawing.Size(1040,459)
$form.KeyPreview = $true
$form.StartPosition = ‘centerscreen’
$form.BackColor = 'MidnightBlue'
$form.Add_KeyDown({if($_.KeyCode -eq "Escape"){$form.Close()}})
$form.Text = "Dialog Box 2.0"
$form.Icon = [system.drawing.icon]::ExtractAssociatedIcon($PSHOME + "\powershell_ise.exe")
$form.Add_Resize({
$inputbox.Height = $form.Height -215
})
$buttonPanel3 = New-Object Windows.Forms.Panel
$buttonPanel3.Size = New-Object Drawing.Size #(290,70)
$buttonPanel3.Dock = "left"
$buttonPanel3.BackColor = 'Blue'
$inputbox = New-Object System.Windows.Forms.ListBox
$inputbox.BorderStyle = 'NONE'
$inputbox.Font = New-Object System.Drawing.Font(“segoe UI”,9)
$inputbox.SelectionMode = "MultiExtended"
$inputbox.Left = 10
$inputbox.Top = 105
$inputbox.Width = 200
$inputbox.Height = $form.Height -215
$buttonPanel3.Controls.Add($inputbox)
$form.Controls.Add($buttonPanel3)
$form.ShowDialog()
Related
This question already has answers here:
WPF if statement based on radio button checked or not
(3 answers)
Closed 1 year ago.
I have the following code:
$var_executeButton.Add_Click( {
if ($var_radioButton.Checked) {
..do stuff
}
})
however, the code inside the if block never run, even if radio button is checked.
Code outside of the if works just fine.
Can you please tell me why?
Continuing from my comment. There ways to take action on form elements at the time they are acted on or checked later. As an example here is a simple WinForm, that discovers all radio button controls on a form and takes the same action when any one of them is clicked.
Add-Type -AssemblyName System.Windows.Forms
[System.Windows.Forms.Application]::EnableVisualStyles()
$objForm = New-Object System.Windows.Forms.Form
$objForm.Text = "Test"
$objForm.Size = New-Object System.Drawing.Size(400, 200)
$objForm.StartPosition = "CenterScreen"
$RadioButton1 = New-Object System.Windows.Forms.RadioButton
$RadioButton1.Location = New-Object System.Drawing.Size(10, 10)
$RadioButton1.Size = New-Object System.Drawing.Size(100, 20)
$RadioButton1.Checked = $false
$RadioButton1.text = "Button1"
$objForm.controls.Add($RadioButton1)
$RadioButton2 = New-Object System.Windows.Forms.RadioButton
$RadioButton2.Location = New-Object System.Drawing.Size(10, 50)
$RadioButton2.Size = New-Object System.Drawing.Size(100, 20)
$RadioButton2.Checked = $false
$RadioButton2.text = "Button2"
$objForm.controls.Add($RadioButton2)
$OKButton = New-Object System.Windows.Forms.Button
$OKButton.Location = New-Object System.Drawing.Size(10, 120)
$OKButton.Size = New-Object System.Drawing.Size(150, 30)
$OKButton.Text = "OK"
$OKButton.Enabled = $false
$OKButton.DialogResult = [System.Windows.Forms.DialogResult]::OK
$objForm.Controls.Add($OKButton)
$objForm.AcceptButton = $OKButton
$objForm.TopMost = $True
$objForm.Controls |
Where-Object { $PSItem -is [System.Windows.Forms.RadioButton] } |
ForEach-Object {
$PSItem.Add_Click(
{
If (-Not $OKButton.Enabled)
{$OKButton.Enabled = $True}
})
}
$Form = $objForm.ShowDialog()
To see if a radio button is checked, you can use either .Checked,
# Example - check radio button state on OK click.
function Test-RadioButtonCheck
{
Param
(
$title,
$a1,
$a2,
$a3
)
$form = New-Object System.Windows.Forms.Form
$form.Size = '300,250'
$form.Text = $title
$form.StartPosition = [System.Windows.Forms.FormStartPosition]::CenterScreen
$label1 = New-Object System.Windows.Forms.Label
$label1.Location = '15,15'
$label1.Width = 100
$label1.Text = 'Enter some text'
$form.Controls.Add($label1)
$textBox1 = New-Object System.Windows.Forms.TextBox
$textBox1.Location = '115,15'
$textBox1.width = 150
$textBox1.Name = 'input'
$form.Controls.Add($textBox1)
$radio1 = New-Object System.Windows.Forms.RadioButton
$radio1.Location = '25,40'
$radio1.Text = 'Check me if you want the save'
$radio1.Width = 200
$form.Controls.Add($radio1)
$button = New-Object System.Windows.Forms.Button
$button.Location = '70,70'
$button.Text = 'Ok'
$button.DialogResult = 'Ok'
$form.Controls.Add($button)
if($form.ShowDialog() -eq 'Ok')
{
if($textBox1.Text)
{
if($radio1.Checked){$form}
else{[void][System.Windows.Forms.MessageBox]::Show('You didn''t check the radio button','Error')}
}
else{[void][System.Windows.Forms.MessageBox]::Show('You didn''t enter any text','Error')}
}
}
if($frm = Test-RadioButtonCheck 'Test form')
{Write-Host "You entered $($frm.Controls['input'].Text)" -ForegroundColor Green}
.IsChecked as per mklement0's link, or looping to find them:
Where {$PSItem -is [system.windows.controls.radiobutton] -and $PSItem.IsChecked} |
Select Name
... or using [System.Windows.Controls.RadioButton]::CheckedEvent as per this WPF example:
[xml]$xaml = #"
<Window
xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml"
x:Name = "Window" Title = "Initial Window" WindowStartupLocation = "CenterScreen"
SizeToContent = "WidthAndHeight" ShowInTaskbar = "True" Background = "lightgray">
<StackPanel x:Name = 'StackPanel'>
<RadioButton x:Name = "Item1" Content = 'Item1'/>
<RadioButton x:Name = "Item2" Content = 'Item2'/>
<RadioButton x:Name = "Item3" Content = 'Item3'/>
<Separator/>
<TextBox x:Name = 'textbox'/>
</StackPanel>
</Window>
"#
$reader = (New-Object System.Xml.XmlNodeReader $xaml)
$Window = [Windows.Markup.XamlReader]::Load( $reader )
$xaml.SelectNodes("//*[#*[contains(translate(name(.),'n','N'),'Name')]]") |
ForEach {Set-Variable -Name ($PSItem.Name) -Value $Window.FindName($PSItem.Name) -Scope Script}
#Bubble up event handler
[System.Windows.RoutedEventHandler]$Script:CheckedEventHandler =
{$TextBox.Text = $PSItem.source.name}
$StackPanel.AddHandler([System.Windows.Controls.RadioButton]::
CheckedEvent, $CheckedEventHandler)
$Window.Showdialog() | Out-Null
If you want dig at the explanations of the WPF and radio button options, then see this blog post regarding the samples shown:
https://learn-powershell.net/2014/08/10/powershell-and-wpf-radio-button
If the aforementioned is not what you are doing, then as per my comment, you are not showing what the use case really is.
I'm trying to implement a PowerShell form whereby there is a faded overlay over the background desktop.
The only way I could think implementing this was to use two forms - one to show a full screen overlay (background form), and the other being the actual (main) form. However, when i click off (or deactivate) the main form, I want everything to close. However it no longer closes and I can't figure it why? I get the feeling that when I click off the main form, the click event is trying to click the background form (and can't due to the main form having focus) and the 'deactivate' event no longer works?
Any help appreciated:
[void][System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
[void][System.Reflection.Assembly]::LoadWithPartialName("System.Drawing")
[System.Windows.Forms.Application]::EnableVisualStyles()
$windowsGreyTrans = [System.Drawing.Color]::FromArgb(20,43,43,43)
$windowsGreyOff = [System.Drawing.Color]::FromArgb(43,43,43)
$windowsGreyOn = [System.Drawing.Color]::FromArgb(60,60,60)
$bgform = New-Object System.Windows.Forms.Form
$bgform.WindowState = 'Maximized'
$bgform.ShowInTaskbar = $false
$bgform.MaximizeBox = $false
$bgform.Opacity = 0.5
$bgform.ControlBox = $false
$bgform.FormBorderStyle = [System.Windows.Forms.FormBorderStyle]::none
[void]$bgform.show()
$form = New-Object System.Windows.Forms.Form
$form.Size = New-Object System.Drawing.Size(200, 40)
$Form.StartPosition = "CenterScreen"
$form.ShowInTaskbar = $false
$form.Name ="Power"
$form.MaximizeBox = $false
$form.ControlBox = $false
$form.FormBorderStyle = [System.Windows.Forms.FormBorderStyle]::none
$shutdownBtn = New-Object System.Windows.Forms.Button
$shutdownBtn.Location = New-Object System.Drawing.Point(0, 0)
$shutdownBtn.Size = New-Object System.Drawing.Size(200, 40)
$shutdownBtn.Text = "Shut down"
$shutdownBtn.FlatStyle = "Flat"
$shutdownBtn.UseVisualStyleBackColor = $True
$shutdownBtn.BackColor = $windowsGreyOff
$shutdownBtn.FlatAppearance.BorderSize = 0
$shutdownBtn.ForeColor = "White"
$shutdownBtn.Font = "Segoe UI,10pt"
#$shutdownBtn.Cursor = [System.Windows.Forms.Cursors]::Hand
$shutdownBtn.Add_Click({
try {
}
catch{
}
})
$shutdownBtn.Add_MouseEnter({
$this.BackColor = $windowsGreyOn
})
$shutdownBtn.Add_MouseLeave({
$this.BackColor = $windowsGreyOff
})
$form.Controls.Add($shutdownBtn)
$form.Add_Deactivate({
$this.Close()
$bgform.close()
})
$form.Add_Shown({
$this.Activate()
})
[void]$form.showdialog()
I propose you a better solution, use a tablelayoutpanel for center your button and intercept click event.
Try this :
[void][System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
[void][System.Reflection.Assembly]::LoadWithPartialName("System.Drawing")
[System.Windows.Forms.Application]::EnableVisualStyles()
$windowsGreyTrans = [System.Drawing.Color]::FromArgb(20,43,43,43)
$windowsGreyOff = [System.Drawing.Color]::FromArgb(43,43,43)
$windowsGreyOn = [System.Drawing.Color]::FromArgb(60,60,60)
#create form
$form = New-Object System.Windows.Forms.Form
$form.SuspendLayout()
$form.WindowState = [System.Windows.Forms.FormWindowState]::Maximized
$form.ShowInTaskbar = $false
$form.MaximizeBox = $false
$form.Opacity = 0.5
$form.ControlBox = $false
$form.FormBorderStyle = [System.Windows.Forms.FormBorderStyle]::none
#create Tablelayout panel on this form
$TableLayoutPanel = New-Object System.Windows.Forms.TableLayoutPanel
$TableLayoutPanel.SuspendLayout()
$TableLayoutPanel.ColumnCount=1
$TableLayoutPanel.RowCount=1
$TableLayoutPanel.Dock=[System.Windows.Forms.DockStyle]::Fill
$form.Controls.Add($TableLayoutPanel)
#create button on this tablelayoutpanel
$shutdownBtn = New-Object System.Windows.Forms.Button
$shutdownBtn.Size = New-Object System.Drawing.Size(200, 40)
$shutdownBtn.Text = "Shut down"
$shutdownBtn.FlatStyle = "Flat"
$shutdownBtn.UseVisualStyleBackColor = $True
$shutdownBtn.BackColor = $windowsGreyOff
$shutdownBtn.FlatAppearance.BorderSize = 0
$shutdownBtn.ForeColor =[System.Drawing.Color]::White
$shutdownBtn.Font = "Segoe UI,10pt"
$shutdownBtn.Anchor=[System.Windows.Forms.AnchorStyles]::None
$TableLayoutPanel.Controls.Add($shutdownBtn)
#Layout
$TableLayoutPanel.ResumeLayout($false)
$form.ResumeLayout($false)
$shutdownBtn.Add_Click({
try {
}
catch{
}
})
#change color to tablelayot on first show
$form.Add_Shown({
$TableLayoutPanel.BackColor =$windowsGreyTrans
})
$TableLayoutPanel.Add_Click({
$form.close()
})
$shutdownBtn.Add_MouseEnter({
$this.BackColor = $windowsGreyOn
})
$shutdownBtn.Add_MouseLeave({
$this.BackColor = $windowsGreyOff
})
[void]$form.ShowDialog()
$form.Dispose()
I'm trying to make a form in PowerShell that gets locked to a fixed position on the desktop.
Because whenever I press the "Show Desktop" button on the bottom right corner on Win 8.1, the form disappears until I open a different window and close it.
I just want it there like it's a widget, here's a part of the code i'm using:
Add-Type -AssemblyName System.Windows.Forms
Add-Type -Assembly System.Drawing
$Image = [System.Drawing.Image]::Fromfile("Panel.png")
$Form = New-Object system.Windows.Forms.Form
$Form.BackgroundImage = $Image
$Form.BackgroundImageLayout = "None"
$Form.Text = "Reboot Server"
$Form.Width = 517
$Form.Height = 134
$Form.ControlBox = $False
$Form.StartPosition = 'Manual'
$Form.Location = "1390, 300"
$Form.FormBorderStyle = 'None'
$Form.BackColor = "#000000"
$Form.MaximizeBox = $False
$Form.MinimizeBox = $False
$Form.Icon = "icon.ico"
$Form.Image = [System.Drawing.Image]::Fromfile("Panel.png")
$Form.ShowInTaskbar = $False
$Font = New-Object System.Drawing.Font("Tahoma",10, [System.Drawing.FontStyle]::Bold)
$Form.Font = $Font
$Label = New-Object System.Windows.Forms.Label
$Label.Text = ""
$Label.AutoSize = $True
$Form.Controls.Add($Label)
' Button 1 - Reboot Server'
$Button1 = new-object System.Windows.Forms.Button
$Button1.Location = new-object System.Drawing.Size(234,51)
$Button1.Size = new-object System.Drawing.Size(77,55)
$Button1.AutoSize = $True
$Button1.Add_Click({start-process "Reboot.lnk"})
$Button1.FlatStyle = [System.Windows.Forms.FlatStyle]::Flat
$Button1.FlatAppearance.BorderSize=0
$Button1.BackColor = "Transparent"
$Button1.ForeColor = "Transparent"
$Button1.FlatAppearance.MouseDownBackColor = "Transparent"
$Button1.FlatAppearance.MouseOverBackColor = "Transparent"
$Button1.FlatAppearance.BorderColor = "#252525"
$Form.Controls.Add($Button1)
'----------------------------------------
$Form.ShowDialog() | Out-Null
Exit 0
For gadget style positions try to use a little snippet that I have made:
$Poistion = 'RightBottom'
$Coordinates = switch ($Poistion)
{
'LeftTop' { 0, 0 }
'LeftBottom' { 0, $([System.Windows.Forms.Screen]::PrimaryScreen.WorkingArea.Bottom - $Form.Height) }
'RightTop' { $([System.Windows.Forms.Screen]::PrimaryScreen.WorkingArea.Width - $Form.Width), 0 }
'RightBottom' { $([System.Windows.Forms.Screen]::PrimaryScreen.WorkingArea.Width - $Form.Width), $([System.Windows.Forms.Screen]::PrimaryScreen.WorkingArea.Bottom - $Form.Height) }
}
$Form.Location = New-Object System.Drawing.Point($Coordinates)
To keep your form up at the time when you activate "Show Desktop" set TopMost property to $True and MinimizeBox property to $False. Like so:
$Form.TopMost = $True
$Form.MinimizeBox = $False
When you click on Show Desktop or use its hotkey (Win+D) windows tries to send Minimize All command to running applications. After minimizing all the windows that can be minimized, it then takes the desktop and "raises" it to the top of the window stack so that no other windows cover it.
You could also try to use sizing events. Like so:
$Form_Resize={
$Form.WindowState = 'Normal'
}
$Form.add_Resize($Form_Resize)
I have a borderless winform (WPF is not an option) that I am trying to make draggable from an object that is serving as a custom sidebar. I have searched around and found some things that allow me to drag the sidebar within the form, but I need to be able to move $Form with the sidebar. Any thoughts? It seems like I will need to use Add-Type with some C# here.
Ok, since we don't have the code to your form, here's a demo for you. It is just a not-pretty borderless form that uses a label to demonstrate the various events needed to drag the entire form around. (in your case this would be the sidebar)
Add-Type -AssemblyName System.Windows.Forms
# set up some globals for dragging
$global:dragging = $false
$global:mouseDragX = 0
$global:mouseDragY = 0
#Form
$form = New-Object System.Windows.Forms.Form
$form.FormBorderStyle = "None"
$form.Font = New-Object System.Drawing.Font("Microsoft Sans Serif", 9.0, [System.Drawing.FontStyle]::Regular, [System.Drawing.GraphicsUnit]::Point)
$form.MinimumSize = New-Object System.Drawing.Size(456, 547)
$form.AutoScaleDimensions = New-Object System.Drawing.SizeF(7.0, 15.0)
$form.AutoScaleMode = [System.Windows.Forms.AutoScaleMode]::Font
$form.ClientSize = New-Object System.Drawing.Size(440, 509)
$form.ShowIcon = $false
$form.StartPosition = "CenterScreen"
$form.TopMost = $true
#lblDrag (this is the object used for dragging the form)
$lblDrag = New-Object System.Windows.Forms.Label
$lblDrag.Name = "lblDrag"
$lblDrag.BackColor = [System.Drawing.Color]::LightYellow
$lblDrag.Location = New-Object System.Drawing.Point(172, 226)
$lblDrag.Size = New-Object System.Drawing.Size(117, 27)
$lblDrag.Anchor = "Top","Right"
$lblDrag.BorderStyle = "FixedSingle"
$lblDrag.Text = "Drag form.."
$lblDrag.TextAlign = [System.Drawing.ContentAlignment]::MiddleCenter
# set the 'dragging' flag and capture the current mouse position
$lblDrag.Add_MouseDown( { $global:dragging = $true
$global:mouseDragX = [System.Windows.Forms.Cursor]::Position.X - $form.Left
$global:mouseDragY = [System.Windows.Forms.Cursor]::Position.Y -$form.Top
})
# move the form while the mouse is depressed (i.e. $global:dragging -eq $true)
$lblDrag.Add_MouseMove( { if($global:dragging) {
$screen = [System.Windows.Forms.Screen]::PrimaryScreen.WorkingArea
$currentX = [System.Windows.Forms.Cursor]::Position.X
$currentY = [System.Windows.Forms.Cursor]::Position.Y
[int]$newX = [Math]::Min($currentX - $global:mouseDragX, $screen.Right - $form.Width)
[int]$newY = [Math]::Min($currentY - $global:mouseDragY, $screen.Bottom - $form.Height)
$form.Location = New-Object System.Drawing.Point($newX, $newY)
}})
# stop dragging the form
$lblDrag.Add_MouseUp( { $global:dragging = $false })
# add a button so you will be able to close the form
$btnClose = New-Object System.Windows.Forms.Button
$btnClose.Name = "btnClose"
$btnClose.Anchor = "Top","Right"
$btnClose.Location = New-Object System.Drawing.Point(172, 454)
$btnClose.Size = New-Object System.Drawing.Size(117, 27)
$btnClose.Text = "&Close"
$btnClose.UseVisualStyleBackColor = $true
$btnClose.UseMnemonic = $true
$btnClose.DialogResult = [System.Windows.Forms.DialogResult]::OK
# add controls to the form
$form.Controls.Add($btnClose)
$form.Controls.Add($lblDrag)
$form.AcceptButton = $btnClose
# show the form and play around with the dragging label
$form.ShowDialog()
# when done, dispose of the form
$form.Dispose()
I am trying to show a DateTimePicker in a WinForms form in PowerShell. When the form appears, the date can be changed, but hitting the dropdown button doesn't show the calendar. It seems like something is happening, it's just not visible.
What stupid thing am I missing here?
$form = New-Object Windows.Forms.Form
$form.Size = New-Object Drawing.Size #(400, 400)
$form.StartPosition = "CenterScreen"
$form.Text = "When do you want the snapshot to be taken?"
$form.Font = New-Object Drawing.Font("Microsoft Sans Serif",12)
$form.FormBorderStyle = [Windows.Forms.FormBorderStyle]::Fixed3D
$panel = New-Object Windows.Forms.FlowLayoutPanel
$panel.Height = 400
$panel.Width = 400
$panel.AutoScroll = $true
$panel.FlowDirection = [Windows.Forms.FlowDirection]::TopDown
$panel.WrapContents = $false
$titleText = New-Object Windows.Forms.Label
$titleText.AutoSize = $true
$titleText.Text = "When do you want the snapshot to be taken?"
$panel.Controls.Add($titleText)
$datePicker = New-Object Windows.Forms.DateTimePicker
$datePicker.ShowUpDown = $false
$datePicker.MinDate = $now
$datePicker.MaxDate = $now.AddMonths(3); #arbitrary
$datePicker.MaxSelectionCount = 1
$datePicker.Width = 350
$datePicker.Enabled = $false
$panel.Controls.Add($datePicker)
$form.Controls.Add($panel)
$drc = $form.ShowDialog()
Your code seems to work fine on my computer. I copy-pasted your code and added Add-Type to top:
Add-Type -AssemblyName System.Windows.Forms
And changed the $datePicker.Enabled:
$datePicker.Enabled = $true
When run, I can change the date/time and also the dropdown is working as expected: