PowerShellでポップアップメニューを表示する(フォント変更対応)

前に書いたのは、フォントの変更ができませんでした。
今回はフォント変更にも対応してみました。
関数の引数を簡易にする都合上、一律変更となっていますが、もちろん個別変更も可能です。
また、修正すればイタリック体にするとかも可能となります。
一度でも呼ぶと、System.Windows.Formsがロードされるのが不可逆なのは同じ。



スクリプト

function Show-PopupMenu() {
	Param (
		[string[]]$Items,
		[string]$Splitter = ',',
		[string]$Separator = '^',
		[int]$x = [int]::MinValue,
		[int]$y = [int]::MinValue,
		[string]$FontName = $null,
		[single]$FontSize = [single]9
	)

	if(!('System.Windows.Forms.Form' -as [type])) {
		Add-Type -AssemblyName System.Windows.Forms
	}
	if($Items.Count -eq 1 -and ![string]::IsNullOrEmpty($Splitter)) {
		$Items = $Items[0].Split($Splitter)
	}

	$form = New-Object System.Windows.Forms.Form
	$form.Opacity = 0
	$form.ShowInTaskbar = $false
	$onClick = {
		Param ($sender, $ev)
		$form.Name = $sender.Name
	}
	$components = New-Object System.ComponentModel.Container
	$contextMenu = New-Object System.Windows.Forms.ContextMenuStrip $components
	$contextMenu.SuspendLayout()
	$mis = New-Object 'System.Collections.Generic.List[System.Collections.Generic.List[System.Windows.Forms.ToolStripMenuItem]]'
	$mis.Add((New-Object 'System.Collections.Generic.List[System.Windows.Forms.ToolStripMenuItem]'))
	$idxb = 0
	$idxs = 0
	$idxsp = @()
	for($i = 0; $i -lt $Items.Count; $i++) {
		$put = $true
		if([string]::IsNullOrEmpty($Separator)) {
			$it = @()
			$it += $Items[$i]
		} else {
			$it = $Items[$i].Split($Separator, 2)
		}
		if($it[0].Length -gt 0) {
			if($it[0][0] -eq '\') {
				switch($it[0][1]) {
					'>' {
						$idxsp += $idxs
						$idxb++
						$idxs = 0
						$mis.Add((New-Object 'System.Collections.Generic.List[System.Windows.Forms.ToolStripMenuItem]'))
						$put = $false
					}
					'<' {
						$idxb--;
						$idxs = $idxsp[$idxb]
						$mis[$idxb][$idxs - 1].DropDownItems.AddRange($mis[$idxb + 1].ToArray())
						$mis[$idxb][$idxs - 1].Remove_Click($onClick)
						$put = $false
					}
					default {
						$it[0] = $it[0].Substring(1);
					}
				}
			}
		}
		if($put) {
			$mis[$idxb].Add((New-Object System.Windows.Forms.ToolStripMenuItem $it[0]))
			if($it.Count -eq 1) {
				$mis[$idxb][$idxs].Name = $it[0]
			} else {
				$mis[$idxb][$idxs].Name = $it[1]
			}
			if(![string]::IsNullOrEmpty($FontName)) {
				$mis[$idxb][$idxs].Font = New-Object System.Drawing.Font $FontName, $FontSize
			}
			$mis[$idxb][$idxs].Add_Click($onClick)
			$idxs++
		}
	}

	$contextMenu.Items.AddRange($mis[0].ToArray())
	$contextMenu.Add_Closed({
		$form.Close()
	})
	$contextMenu.ResumeLayout($false)
	$timer = New-Object System.Windows.Forms.Timer
	$timer.Interval = 10
	$timer.Add_Tick({
		$timer.Enabled = $false
		if($x -eq [int]::MinValue) { $x = [System.Windows.Forms.Cursor]::Position.X }
		if($y -eq [int]::MinValue) { $y = [System.Windows.Forms.Cursor]::Position.Y }
		$contextMenu.Show($x, $y)
	})
	$timer.Enabled = $true
	[void]$form.ShowDialog()
	$form.Name
	$contextMenu.Dispose()
	$components.Dispose()
	$form.Dispose()

	return $ret
}

使い方

基本的な使い方は

Show-PopupMenu a,b,c

といった感じ。
選択すると、選択したものが、キャンセルは空文字。


フォントを変更するには、

Show-PopupMenu a,b,c -FontName HGP創英角ポップ体 -FontSize 15.75

FontSizeは初期値9になっています。


他の使い方は、以下を参考にしてください。
PowerShellでポップアップメニューを表示する - じゅんじゅんのきまぐれ

のうがき

タイマー使って、妙なこすいことしてます。
Formを出す前にContextMenuStripのShowすると、Formのロードで消されてしまうので。
Formを出すのは、メッセージポンプを回すためです。