0

I've created this little script running in tray. I've noticed that contex menu text is not placed completely to the left. After a little investigation I found out that it is because there is a space left for .checked state indicator. I found out that it can be removed by .showcheckedmargin property of ContextMenuStrip but have no idea how to implement that. Please advise.

add-type -AssemblyName 'System.Windows.Forms'
Add-Type -AssemblyName 'System.Drawing'
Add-Type -AssemblyName 'PresentationFramework'


$2 = "BASE64 CODE"

$bitmap = New-Object System.Windows.Media.Imaging.BitmapImage
$bitmap.BeginInit()
$bitmap.StreamSource = [System.IO.MemoryStream][System.Convert]::FromBase64String($2)
$bitmap.EndInit()
$bitmap.Freeze()

$image = [System.Drawing.Bitmap][System.Drawing.Image]::FromStream($bitmap.StreamSource)

$icon = [System.Drawing.Icon]::FromHandle($image.GetHicon())

$app = New-Object System.Windows.Forms.NotifyIcon
$app.Text = ""
$app.Icon = $icon
$app.Visible = $true

$Zenek = New-Object System.Windows.Forms.MenuItem
$Zenek.Text = "Zenek"

$NetExt = New-Object System.Windows.Forms.MenuItem
$NetExt.Text = "NetExt"

$Busy = New-Object System.Windows.Forms.MenuItem
$Busy.Text = "BUSY"

$Time = New-Object System.Windows.Forms.MenuItem
$Time.Text = "Time"

$Exit = New-object System.Windows.Forms.MenuItem
$Exit.Text = "Exit"

$context = New-Object System.Windows.Forms.ContextMenu

$app.ContextMenu = $context
$app.ContextMenu.MenuItems.AddRange(@($Zenek, $NetExt, $Busy, $Time, $Exit))

$keepAwakeScript = {
    while (1) {
      $wsh = New-Object -ComObject WScript.Shell
      $wsh.SendKeys('+{F15}')
      Start-Sleep -seconds 59
    }
}


Start-Job -ScriptBlock $keepAwakeScript -Name "keepAwake"|out-null

$Zenek.Add_Click({Set-Clipboard -Value "SOME TEXT"})

$NetExt.Add_Click({Set-Clipboard -Value "SOME OTHER TEXT"})

$Busy.Add_Click({
$running = Get-Job|?{$_.Name -like 'KAPS'}

$icon = new-object System.Drawing.Icon("MY PRIVATE LOCATION\red.ico")
$app.Icon = $icon
if($running -eq $null){
Start-Job -Name KAPS -ScriptBlock{
while ($true){
$shell = New-Object -ComObject WScript.Shell
$shell.SendKeys('{CAPSLOCK}')
Start-Sleep 1
}
}
}else{
Stop-Job KAPS
Remove-Job KAPS
$icon = [System.Drawing.Icon]::FromHandle($image.GetHicon())
$app.Icon = $icon
}
})

$Time.Add_Click({



$main = New-Object System.Windows.Forms.Form
$main.ClientSize = '200,200'
$main.MinimizeBox = $false
$main.MaximizeBox = $false

$label = New-Object System.Windows.Forms.Label
$label.Size = '190,30'
$label.Location = '10,10'
$label.Text = 'Ile minut?'
$font = New-Object System.Drawing.Font("Arial", 23)
$label.Font = $font

$textbox = New-Object System.Windows.Forms.TextBox
$textbox.Size = '50,100'
$textbox.Location = '10,70'

$button = New-Object System.Windows.Forms.Button
$button.Size = '50,50'
$button.Location = '10,120'
$button.Text = 'GO'
$button.Add_Click({
$timer.Start()
$textbox.Visible =$false
$button.Visible = $false
$label.Visible = $false
$script:1 = New-TimeSpan -minutes ([int]$textbox.Text)
$label2.Visible = $true
$label2.Text = $1.ToString("mm\:ss")
})

$timer = New-Object System.Windows.Forms.Timer
$timer.Enabled = $false
$timer.Interval = '1000'
$second = New-TimeSpan -Seconds 1
$timer.Add_Tick({

$script:1 = $1.Subtract($second)

$label2.Text = $1.ToString("mm\:ss")
if($script:1.TotalSeconds -le 0){$timer.Stop(); $timer.Dispose(); [System.Windows.Forms.Application]::SetSuspendState("Hibernate", $true, $false); $main.Close(); $main.Dispose()}


})

$label2 = New-Object System.Windows.Forms.Label
$label2.Size = '190,30'
$label2.Location = '10,10'
$label2.Text = $1
$font = New-Object System.Drawing.Font("Arial", 23)
$label2.Font = $font 
$label2.Visible = $false

$main.Controls.Add($textbox)
$main.Controls.Add($button)
$main.Controls.Add($label)
$main.Controls.Add($label2)
$main.ShowDialog()

})

$Exit.Add_Click({
    $app.Visible = $false
    Stop-Job -Name "keepAwake"
    $appContext.ExitThread()
    Stop-Process -Id $PID
})

$appContext = New-Object System.Windows.Forms.ApplicationContext
[void][System.Windows.Forms.Application]::Run($appContext)
rawmatter
  • 19
  • 3
Nawad-sama
  • 151
  • 2
  • 12
  • How about `$context.showcheckedmargin = $false` ? – Scepticalist Jan 16 '23 at 08:58
  • Unfortunately `.ContextMenu` ($context) does not support said property – Nawad-sama Jan 16 '23 at 09:03
  • Looking on Microsoft - you're not using the correect object to use ShowCheckedMargin property. It's `System.Windows.Forms.ToolStripDropDownMenu`, not `System.Windows.Forms.ContextMenu` – Scepticalist Jan 16 '23 at 09:25
  • I am aware of that, but so far haven't been able to show a menu when right-clicking, using `System.Windows.Forms.ToolStripDropDownMenu`. – Nawad-sama Jan 16 '23 at 09:36
  • Thats a different quesiton altogether. You cant use methods/properties that dont exist on `System.Windows.Forms.ContextMenu` – Scepticalist Jan 16 '23 at 10:25

1 Answers1

1

For anyone with the same problem. I've managed to figure it out. Another post from SO allowed me to do so.

I had to replace .ContextMenu with .ContextMenuStrip for the Menu itself, replace .MenuItem with .ToolStripMenuItem, add .ShowImageMargin to ContextMenuStrip variable, then finall add items via .Items.AddRange(@()).

Before
enter image description here
After
enter image description here

In the end the code looks like this and works as intended.

add-type -AssemblyName 'System.Windows.Forms'
Add-Type -AssemblyName 'System.Drawing'
Add-Type -AssemblyName 'PresentationFramework'


$2 = 
"BASE 64 CODE"

$bitmap = New-Object System.Windows.Media.Imaging.BitmapImage
$bitmap.BeginInit()
$bitmap.StreamSource = [System.IO.MemoryStream][System.Convert]::FromBase64String($2)
$bitmap.EndInit()
$bitmap.Freeze()

$image = [System.Drawing.Bitmap][System.Drawing.Image]::FromStream($bitmap.StreamSource)

$icon = [System.Drawing.Icon]::FromHandle($image.GetHicon())

$app = New-Object System.Windows.Forms.NotifyIcon
$app.Text = ""
$app.Icon = $icon
$app.Visible = $true

$Zenek = New-Object System.Windows.Forms.ToolStripMenuItem
$Zenek.Text = "Zenek"
$Zenek.Checked = $true

$NetExt = New-Object System.Windows.Forms.ToolStripMenuItem
$NetExt.Text = "NetExt"

$Busy = New-Object System.Windows.Forms.ToolStripMenuItem
$Busy.Text = "BUSY"

$Time = New-Object System.Windows.Forms.ToolStripMenuItem
$Time.Text = "Time"

$Exit = New-object System.Windows.Forms.ToolStripMenuItem
$Exit.Text = "Exit"

$sep = New-Object System.Windows.Forms.ToolStripSeparator

$context = New-Object System.Windows.Forms.ContextMenuStrip
$context.ShowImageMargin = $false
$context.Items.AddRange(@($Zenek, $NetExt, $Busy, $Time, $sep, $Exit))

$app.ContextMenuStrip = $context



$keepAwakeScript = {
    while (1) {
      $wsh = New-Object -ComObject WScript.Shell
      $wsh.SendKeys('+{F15}')
      Start-Sleep -seconds 59
    }
}


Start-Job -ScriptBlock $keepAwakeScript -Name "keepAwake"|out-null

$Zenek.Add_Click({Set-Clipboard -Value "SOME TEXT"})

$NetExt.Add_Click({Set-Clipboard -Value "SOME OTHER TEXT"})

$Busy.Add_Click({
$running = Get-Job|?{$_.Name -like 'KAPS'}

$icon = new-object System.Drawing.Icon("MY PRIVATE LOCATION\red.ico")
$app.Icon = $icon
if($running -eq $null){
Start-Job -Name KAPS -ScriptBlock{
while ($true){
$shell = New-Object -ComObject WScript.Shell
$shell.SendKeys('{CAPSLOCK}')
Start-Sleep 1
}
}
}else{
Stop-Job KAPS
Remove-Job KAPS
$icon = [System.Drawing.Icon]::FromHandle($image.GetHicon())
$app.Icon = $icon
}
})

$Time.Add_Click({



$main = New-Object System.Windows.Forms.Form
$main.ClientSize = '200,200'
$main.MinimizeBox = $false
$main.MaximizeBox = $false

$label = New-Object System.Windows.Forms.Label
$label.Size = '190,30'
$label.Location = '10,10'
$label.Text = 'Ile minut?'
$font = New-Object System.Drawing.Font("Arial", 23)
$label.Font = $font

$textbox = New-Object System.Windows.Forms.TextBox
$textbox.Size = '50,100'
$textbox.Location = '10,70'

$button = New-Object System.Windows.Forms.Button
$button.Size = '50,50'
$button.Location = '10,120'
$button.Text = 'GO'
$button.Add_Click({
$timer.Start()
$textbox.Visible =$false
$button.Visible = $false
$label.Visible = $false
$script:1 = New-TimeSpan -minutes ([int]$textbox.Text)
$label2.Visible = $true
$label2.Text = $1.ToString("mm\:ss")
})

$timer = New-Object System.Windows.Forms.Timer
$timer.Enabled = $false
$timer.Interval = '1000'
$second = New-TimeSpan -Seconds 1
$timer.Add_Tick({

$script:1 = $1.Subtract($second)

$label2.Text = $1.ToString("mm\:ss")
if($script:1.TotalSeconds -le 0){$timer.Stop(); $timer.Dispose(); [System.Windows.Forms.Application]::SetSuspendState("Hibernate", $true, $false); $main.Close(); $main.Dispose()}


})

$label2 = New-Object System.Windows.Forms.Label
$label2.Size = '190,30'
$label2.Location = '10,10'
$label2.Text = $1
$font = New-Object System.Drawing.Font("Arial", 23)
$label2.Font = $font 
$label2.Visible = $false

$main.Controls.Add($textbox)
$main.Controls.Add($button)
$main.Controls.Add($label)
$main.Controls.Add($label2)
$main.ShowDialog()

})

$Exit.Add_Click({
    $app.Visible = $false
    Stop-Job -Name "keepAwake"
    $appContext.ExitThread()
    #Stop-Process -Id $PID
})

$appContext = New-Object System.Windows.Forms.ApplicationContext
[void][System.Windows.Forms.Application]::Run($appContext)
Nawad-sama
  • 151
  • 2
  • 12
  • The job which autopress CAPSLOCK didn't turn off. I had to delete this process. It really gets in the way and it's not needed in the code. Why was it necessary to introduce the problem with the self-pressing key into the code? – Garric Feb 06 '23 at 13:01
  • The code is rare for powershell. Thank you. – Garric Feb 06 '23 at 13:02
  • Why did you include Hibernate in the code and not warn about this timer? – Garric Feb 06 '23 at 13:34
  • Because Bibernate will not take effect unless you execute 'Time' menu item – Nawad-sama Feb 06 '23 at 13:38
  • 1
    Your hibernation worked for me without warning. Because....yes, that's because...this code has been stripped for spare parts – Garric Feb 06 '23 at 15:57
  • I can't set icons for each submenu item. The ToolStripMenuItem must allow this. '$Zenek.Image' parameter for example. Don't you know why? 16*16 bitmap image, – Garric Feb 06 '23 at 16:10
  • Not very automated, but better than nothing: $Zenek.BackgroundImage = $image; $Zenek.BackgroundImageLayout = [System.Windows.Forms.ImageLayout]::None – Garric Feb 06 '23 at 16:54
  • Check this article. It should be usefull. I've not tried it, because I wanted text only menu items – Nawad-sama Feb 06 '23 at 17:06
  • https://www.systanddeploy.com/2020/09/build-powershell-systray-tool-with.html?m=0 – Nawad-sama Feb 06 '23 at 17:06
  • By the way. Emoji worked to. – Garric Feb 06 '23 at 17:32
  • Yes. You article works. Thanks. In the article Part 1 (Create the main part) p 5. and 6. mast be at the end of code – Garric Feb 06 '23 at 18:13