Reputation: 3923
I have a form with a listview for which I have a right click context menu. I'd like the menu to only appear if the right clikc is above the selected item in the listview - at the moment it appears anywhere in the listview windows and even if nothing is selected.
Add-Type -AssemblyName System.Windows.Forms
$form = New-Object System.Windows.Forms.Form
$form.Text = "Foo"
$form.Size = '400,400'
$CMitemEnable = New-Object System.Windows.Forms.ToolStripMenuItem
$CMitemEnable.Text = 'Enable'
$CMitemDisable = New-Object System.Windows.Forms.ToolStripMenuItem
$CMitemDisable.Text = 'Disable'
$lvcontextmenu = New-Object System.Windows.Forms.ContextMenuStrip
$lvcontextmenu.ShowImageMargin = $false
$lvcontextmenu.Items.AddRange(@($CMitemEnable,$CMitemDisable))
$listviewbox = New-Object System.Windows.Forms.ListView
$listviewbox.View = [System.Windows.Forms.View]::Details
$listviewbox.Location = '15,20'
$listviewbox.Size = '340,150'
$listviewbox.Columns.Add('Host',180) | Out-Null
$listviewbox.FullRowSelect = $true
$listviewbox.MultiSelect = $false
# $listviewbox.ContextMenuStrip = $lvcontextmenu
$InfoText = New-Object System.Windows.Forms.TextBox
$InfoText.Location = '15,180'
$InfoText.Size = '340,120'
$InfoText.Multiline = $true
$InfoText.ScrollBars = "Vertical"
$InfoText.ReadOnly = $true
$form.Controls.AddRange(@($listviewbox,$InfoText))
$listviewbox.Items.AddRange(@('Foobar1','foobar2'))
$listviewbox.Add_MouseDown({
$listviewbox.contextmenustrip = $null
If($listviewbox.SelectedItems.Count){
$listviewbox.contextmenustrip = $lvcontextmenu
$InfoText.AppendText("`r`n" + ($this.SelectedItems[0].Text))
}
Else {
$InfoText.AppendText("`r`nNothing selected")
$listviewbox.contextmenustrip = $null
}
})
# Show form
$form.ShowDialog() | Out-Null
$form.Dispose()
I've not done context menus before and can't see for the life of me how to implement the event handler for this - there's examples for C etc but can someone point me in the right direction for Powershell please?
Upvotes: 1
Views: 2594
Reputation: 125207
Considering the following points:
ContextMenuStrip
for the ListView
MouseClick
event, so first the item will be selected, then your code run. (As an alternative, if you prefer mouse down, then you need to need to put your logic in BeginInvoke
to make sure it will run after selection of item.)GetBound
method of the selected item and e.Location
, check if the clicked location is inside the item rectangleContextMenuStrip
using Show
by passing Cursor.Position
Here is a working example:
Add-Type -AssemblyName System.Windows.Forms
$form = New-Object System.Windows.Forms.Form
$form.Text ="Test"
$form.Controls.AddRange(@(
($listView1 = [System.Windows.Forms.ListView] @{
Dock = [System.Windows.Forms.DockStyle]::Fill;
FullRowSelect = $true;
View = [System.Windows.Forms.View]::Details;
})
))
$contextMenuStrip1 = [System.Windows.Forms.ContextMenuStrip]@{}
$listView1.Columns.Add("C1") | Out-Null
$listView1.Columns.Add("C2") | Out-Null
$listView1.Items.Add("Item1") | Out-Null
$listView1.Items.Add("Item2") | Out-Null
$contextMenuStrip1.Items.Add("Menu 1") | Out-Null
$contextMenuStrip1.Items.Add("Menu 2") | Out-Null
$listView1.Add_MouseClick({param($sender,$e)
if ($e.Button -eq [System.Windows.Forms.MouseButtons]::Right){
if ($listView1.FocusedItem.GetBounds(
[System.Windows.Forms.ItemBoundsPortion]::Entire).Contains($e.Location)){
$contextMenuStrip1.Show([System.Windows.Forms.Cursor]::Position)
}
}
})
$form.ShowDialog() | Out-Null
$form.Dispose()
$contextMenuStrip1.Dispose()
Upvotes: 3
Reputation: 3923
The following event handler works as intended - a combination of hints from both of you, thanks.
$listviewbox.Add_MouseUp({
$listviewbox.contextmenustrip = $null
If($listviewbox.SelectedItems.Count){
$listviewbox.contextmenustrip = $lvcontextmenu
$InfoText.AppendText("`r`n" + ($this.SelectedItems[0].Text))
}
Else {
$InfoText.AppendText("`r`nNothing selected")
$listviewbox.contextmenustrip = $null
}
})
Upvotes: 0
Reputation: 61068
Maybe there is a cleaner way, but this works for me:
First, remove line 22 ($listviewbox.ContextMenuStrip = $lvcontextmenu
)
and then change the Click-handler for the $listviewbox
into:
$listviewbox.Add_Click({
If($this.SelectedItems.Count){
$this.ContextMenuStrip = $lvcontextmenu
$InfoText.AppendText("`r`n" + ($this.SelectedItems[0].Text))
}
Else {
$this.ContextMenuStrip = $null
$InfoText.AppendText("`r`nNothing selected")
}
})
Upvotes: 0