为啥我的 WinForms 上下文菜单没有出现在鼠标所在的位置?
Posted
技术标签:
【中文标题】为啥我的 WinForms 上下文菜单没有出现在鼠标所在的位置?【英文标题】:Why does my WinForms context menu not appear where the mouse is?为什么我的 WinForms 上下文菜单没有出现在鼠标所在的位置? 【发布时间】:2011-02-23 16:39:05 【问题描述】:在我的应用程序中,我有一个DataGridView
,用于配置一些选项。这个想法是您可以在第一列中输入您想要的任何文本,但是如果您右键单击它将为您提供明确支持的值。我需要这是一个文本框而不是下拉列表,因为我需要支持编辑无效(或旧)配置。
我想要的是用户在字段名称列中单击鼠标右键,并拥有一个上下文菜单,该菜单根据这是什么类型的配置而有效。因此,我编写了以下事件
private void grvFieldData_CellMouseClick(object sender, DataGridViewCellMouseEventArgs e)
// If this is a right click on the Field name column, create a context menu
// with recognized options for that field
if (e.Button == MouseButtons.Right && grvFieldData.Columns[e.ColumnIndex].Name == "clmFieldName")
ContextMenu menu = new ContextMenu();
if (_supportedDataGrids.ContainsKey((cmbDataGrid.SelectedItem as DataGridFieldList).GridName))
// Loop through all the fields and add them to the context menu
List<string> fields = _supportedDataGrids[((cmbDataGrid.SelectedItem as DataGridFieldList).GridName)];
fields.Sort();
foreach (string field in fields)
menu.MenuItems.Add(new MenuItem(field));
// Make sure there is at least one field before displaying the context menu
if (menu.MenuItems.Count > 0)
menu.Show(this, e.Location, LeftRightAlignment.Right);
这“正确”工作,但上下文菜单出现在表单的顶部,而不是鼠标指针所在的位置。如果我将 Show()
调用更改为使用 DataGridView
而不是表单,我会遇到同样的问题,但它会出现在网格的左上角,而不是鼠标所在的位置。
奇怪的是,如果我将此事件更改为 MouseClick
事件(而不是 CellMouseclick
事件),一切正常,并且上下文菜单准确出现在鼠标指针所在的位置。这个选项的问题是用户可能没有右键单击当前选择的单元格,这意味着当他们单击菜单项时,所选单元格将被更改,而不是他们右键单击的单元格。
有人知道为什么使用CellMouseClick
创建的上下文菜单没有显示在正确的位置吗?
【问题讨论】:
【参考方案1】: menu.Show(this, e.Location, LeftRightAlignment.Right);
第二个参数是鼠标位置,相对于单元格的左上角。按照编程,您使该偏移量相对于表单 this,这将使菜单出现在表单的左上角。使用 DGV 作为第一个参数也不起作用,现在它位于网格的左上角。
有几种方法可以解决这个问题,但这是最简单的方法:
Point pos = this.PointToClient(Cursor.Position);
menu.Show(this, pos, LeftRightAlignment.Right);
你可以任意替换this为grvFieldData。
【讨论】:
嘿,我的答案会稍微复杂一点,加上一堆 X 和 Y 坐标。我希望我几周前知道 Cursor.Position! +1 为简单起见! 太棒了,这就像一个魅力!Cursor.Position
是我错过的!【参考方案2】:
在datagridview鼠标点击事件中:
if e.button= mousebutton.right
contextmenu1.Show(MousePosition);
【讨论】:
【参考方案3】:尝试使用PointToClient
获得合适的位置
【讨论】:
不。PointToClient(e.Location)
将上下文菜单置于屏幕顶部,PointToScreen(e.Location)
出于某种原因将上下文菜单置于窗体中间。
grvFieldData.PointToClient(e.Location)
同样的问题,即使我将this
调用更改为grvFieldData
:-/【参考方案4】:
它没有显示在正确的位置,因为 e.Location 是相对于父对象左上角的位置,在这种情况下是单元格本身。位置属性始终与其容器相关。
要获取鼠标光标相对于表单左上角的位置,可以使用
this.PointToClient(Cursor.Position);
【讨论】:
如何获取被点击单元格的位置(单元格不是控件,因此我无法将其传递给Show()
)或鼠标的屏幕位置?【参考方案5】:
我已经解决了这个问题......人们可能会觉得这个方法很奇怪,但它工作正常!) 如果我们想在 datagridview 单元格中按下鼠标右键时看到上下文菜单,并且就在那里,而不是在屏幕中间或其他地方,我们需要:
制作一些变量
int x=0;
int y=0;
为 datagridview1 创建一个“MouseMove”事件,例如:
private void dataGridView1_MouseMove(object sender, MouseEventArgs e)
x = e.X;
y = e.Y;
和
private void dataGridView1_CellMouseClick(object sender, DataGridViewCellMouseEventArgs e)
if (e.Button == System.Windows.Forms.MouseButtons.Right)
contextMenuStrip1.Show(dataGridView1, x,y);
欢迎您
【讨论】:
这个解决方案有不必要的开销,因为用户将鼠标移到网格上(我认为这种情况经常发生)它会不断地写入内存。该事件已包含该位置。以上是关于为啥我的 WinForms 上下文菜单没有出现在鼠标所在的位置?的主要内容,如果未能解决你的问题,请参考以下文章
在 WinForms 中为上下文菜单动态选择菜单项的正确方法是啥?
为啥我的隐式 ContextMenu 样式不会覆盖 TextBox 上下文菜单样式?