TreeControl/SRxCheckCommandToolStripMenuItem.ps1
|
#Requires -Version 5.1 using namespace System using namespace System.Collections.Generic using namespace System.Drawing using namespace System.Windows.Forms using namespace System.Windows.Forms.VisualStyles class SRxCheckCommandToolStripMenuItem : ToolStripMenuItem { hidden [int] $_checkBoxSize = 14 hidden [int] $_leftPadding = 6 hidden [int] $_gapAfterCheckBox = 7 hidden [int] $_rightPadding = 10 hidden [int] $_minimumItemHeight = 24 hidden [Rectangle] $_checkBoxBounds = [Rectangle]::Empty hidden [bool] $_mouseOverCheckBox = $false hidden [bool] $_showCheckBox = $true hidden [bool] $_keepDropDownOpenOnCheckClick = $true hidden [List[EventHandler]] $_checkBoxClickedHandlers hidden [List[EventHandler]] $_commandClickedHandlers SRxCheckCommandToolStripMenuItem() : base() { $this.initializeItem() } SRxCheckCommandToolStripMenuItem([string] $text) : base($text) { $this.initializeItem() } SRxCheckCommandToolStripMenuItem([string] $text, [bool] $isChecked) : base($text) { $this.initializeItem() $this.Checked = $isChecked } hidden [void] initializeItem() { $this.CheckOnClick = $false $this.Image = $null $this.ImageScaling = [ToolStripItemImageScaling]::None $this.AutoSize = $true $this.Margin = [Padding]::Empty $this.Padding = [Padding]::Empty $this._checkBoxClickedHandlers = [List[EventHandler]]::new() $this._commandClickedHandlers = [List[EventHandler]]::new() } hidden [void] setShowCheckBox([bool] $value) { if ($this._showCheckBox -ne $value) { $this._showCheckBox = $value $this._mouseOverCheckBox = $false $this.Invalidate() } } hidden [bool] getShowCheckBox() { return $this._showCheckBox } hidden [void] setKeepDropDownOpenOnCheckClick([bool] $value) { $this._keepDropDownOpenOnCheckClick = $value } hidden [bool] getKeepDropDownOpenOnCheckClick() { return $this._keepDropDownOpenOnCheckClick } [void] addCheckBoxClicked([EventHandler] $handler) { if ($null -ne $handler) { $this._checkBoxClickedHandlers.Add($handler) } } [void] removeCheckBoxClicked([EventHandler] $handler) { if ($null -ne $handler) { [void] $this._checkBoxClickedHandlers.Remove($handler) } } [void] addCommandClicked([EventHandler] $handler) { if ($null -ne $handler) { $this._commandClickedHandlers.Add($handler) } } [void] removeCommandClicked([EventHandler] $handler) { if ($null -ne $handler) { [void] $this._commandClickedHandlers.Remove($handler) } } hidden [void] raiseCheckBoxClicked() { foreach ($handler in $this._checkBoxClickedHandlers.ToArray()) { $handler.Invoke($this, [EventArgs]::Empty) } } hidden [void] raiseCommandClicked() { foreach ($handler in $this._commandClickedHandlers.ToArray()) { $handler.Invoke($this, [EventArgs]::Empty) } } hidden [void] updateCheckBoxBounds() { $top = [Math]::Max(0, [int](($this.Height - $this._checkBoxSize) / 2)) $this._checkBoxBounds = [Rectangle]::new($this._leftPadding, $top, $this._checkBoxSize, $this._checkBoxSize) } [Rectangle] getCheckBoxBounds() { $this.updateCheckBoxBounds() return $this._checkBoxBounds } [bool] isPointInCheckBox([Point] $location) { if (-not $this.getShowCheckBox()) { return $false } $this.updateCheckBoxBounds() $hitBounds = [Rectangle]::new(0, 0, $this._checkBoxBounds.Right + $this._gapAfterCheckBox, $this.Height) return $hitBounds.Contains($location) } [Size] GetPreferredSize([Size] $constrainingSize) { $baseSize = ([ToolStripMenuItem] $this).GetPreferredSize($constrainingSize) $textValue = if ($null -eq $this.Text) { [string]::Empty } else { $this.Text } $textSize = [TextRenderer]::MeasureText($textValue, $this.Font, [Size]::Empty, ([TextFormatFlags]::SingleLine -bor [TextFormatFlags]::NoPadding)) $checkWidth = if ($this.getShowCheckBox()) { $this._checkBoxSize + $this._gapAfterCheckBox } else { 0 } $width = $this._leftPadding + $checkWidth + $textSize.Width + $this._rightPadding $height = [Math]::Max($this._minimumItemHeight, [Math]::Max($this._checkBoxSize + 6, $textSize.Height + 6)) return [Size]::new([Math]::Max($baseSize.Width, $width), [Math]::Max($baseSize.Height, $height)) } hidden [void] OnMouseMove([MouseEventArgs] $e) { $overCheckBox = $this.isPointInCheckBox($e.Location) if ($this._mouseOverCheckBox -ne $overCheckBox) { $this._mouseOverCheckBox = $overCheckBox $this.Invalidate() } ([ToolStripMenuItem] $this).OnMouseMove($e) } hidden [void] OnMouseLeave([EventArgs] $e) { $this._mouseOverCheckBox = $false $this.Invalidate() ([ToolStripMenuItem] $this).OnMouseLeave($e) } hidden [void] OnMouseUp([MouseEventArgs] $e) { if (($e.Button -eq [MouseButtons]::Left) -and $this.isPointInCheckBox($e.Location)) { $this.toggleCheckBox() if ($this.getKeepDropDownOpenOnCheckClick()) { return } } ([ToolStripMenuItem] $this).OnMouseUp($e) } hidden [void] OnClick([EventArgs] $e) { ([ToolStripMenuItem] $this).OnClick($e) $this.raiseCommandClicked() } hidden [void] OnPaint([PaintEventArgs] $e) { $this.drawBackground($e.Graphics) if ($this.getShowCheckBox()) { $this.drawCheckBox($e.Graphics) } $this.drawItemText($e.Graphics) } hidden [void] toggleCheckBox() { if (-not $this.Enabled -or -not $this.getShowCheckBox()) { return } $this.Checked = -not $this.Checked $this.raiseCheckBoxClicked() $this.Invalidate() } hidden [void] drawBackground([Graphics] $graphics) { $bounds = [Rectangle]::new(0, 0, $this.Width, $this.Height) $color = if ($this.Selected) { [SystemColors]::Highlight } elseif ($null -ne $this.Owner) { $this.Owner.BackColor } else { [SystemColors]::Menu } $brush = [SolidBrush]::new($color) try { $graphics.FillRectangle($brush, $bounds) } finally { $brush.Dispose() } } hidden [void] drawCheckBox([Graphics] $graphics) { $this.updateCheckBoxBounds() $state = if (-not $this.Enabled) { if ($this.Checked) { [CheckBoxState]::CheckedDisabled } else { [CheckBoxState]::UncheckedDisabled } } elseif ($this._mouseOverCheckBox) { if ($this.Checked) { [CheckBoxState]::CheckedHot } else { [CheckBoxState]::UncheckedHot } } else { if ($this.Checked) { [CheckBoxState]::CheckedNormal } else { [CheckBoxState]::UncheckedNormal } } if ([CheckBoxRenderer]::IsSupported) { [CheckBoxRenderer]::DrawCheckBox($graphics, $this._checkBoxBounds.Location, $state) } else { $fallback = [ButtonState]::Normal if (-not $this.Enabled) { $fallback = $fallback -bor [ButtonState]::Inactive } if ($this.Checked) { $fallback = $fallback -bor [ButtonState]::Checked } [ControlPaint]::DrawCheckBox($graphics, $this._checkBoxBounds, $fallback) } } hidden [void] drawItemText([Graphics] $graphics) { $textLeft = $this._leftPadding if ($this.getShowCheckBox()) { $textLeft += $this._checkBoxSize + $this._gapAfterCheckBox } $bounds = [Rectangle]::new($textLeft, 0, [Math]::Max(0, $this.Width - $textLeft - $this._rightPadding), $this.Height) $color = if (-not $this.Enabled) { [SystemColors]::GrayText } elseif ($this.Selected) { [SystemColors]::HighlightText } else { $this.ForeColor } $textValue = if ($null -eq $this.Text) { [string]::Empty } else { $this.Text } $flags = [TextFormatFlags]::Left -bor [TextFormatFlags]::VerticalCenter -bor [TextFormatFlags]::SingleLine -bor [TextFormatFlags]::EndEllipsis -bor [TextFormatFlags]::NoPadding [TextRenderer]::DrawText($graphics, $textValue, $this.Font, $bounds, $color, $flags) } } <# USAGE $item = [SRxCheckCommandToolStripMenuItem]::new('Enable Debug', $false) $item.setShowCheckBox($true) $item.setKeepDropDownOpenOnCheckClick($true) $item.addCheckBoxClicked({ param($sender, $eventArgs); Write-Host ('Checked = {0}' -f $sender.Checked) }) $item.addCommandClicked({ param($sender, $eventArgs); Write-Host 'Command text clicked' }) [void] $dropDownButton.DropDownItems.Add($item) $refreshItem = [SRxCheckCommandToolStripMenuItem]::new('Refresh') $refreshItem.setShowCheckBox($false) #> |