C# 为什么我的WinForms上下文菜单没有出现在鼠标所在的位置?
在我的应用程序中,我有一个用于配置某些选项的C# 为什么我的WinForms上下文菜单没有出现在鼠标所在的位置?,c#,winforms,contextmenu,C#,Winforms,Contextmenu,在我的应用程序中,我有一个用于配置某些选项的DataGridView。其思想是,您可以在第一列中输入您想要的任何文本,但如果右键单击,它将为您提供明确支持的值。我需要这是一个文本框,而不是下拉列表,因为我需要支持编辑无效(或旧)配置 我想要的是用户在字段名列中右键单击,并拥有一个上下文菜单,该菜单根据配置的类型而有效。因此,我对以下事件进行了编码 private void grvFieldData_CellMouseClick(object sender, DataGridViewCel
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);
}
}
}
private void grvFieldData_CellMouseClick(对象发送方,DataGridViewCellMouseEventArgs e)
{
//如果右键单击“字段名”列,请创建上下文菜单
//该字段具有公认的选项
if(e.Button==MouseButtons.Right&&grvFieldData.Columns[e.ColumnIndex].Name==clmFieldName”)
{
ContextMenu=新建ContextMenu();
if(_supportedDataGrids.ContainsKey((cmbDataGrid.SelectedItem作为DataGridFieldList.GridName))
{
//循环遍历所有字段并将它们添加到关联菜单中
列表字段=_支持的数据网格[((cmbDataGrid.SelectedItem作为DataGridFieldList.GridName)];
fields.Sort();
foreach(字段中的字符串字段)
menu.MenuItems.Add(新MenuItem(字段));
//在显示关联菜单之前,确保至少有一个字段
如果(menu.MenuItems.Count>0)
显示(如位置、左右对齐、右对齐);
}
}
}
这是“正确的”,但是上下文菜单出现在窗体的顶部,而不是鼠标指针所在的位置。如果我将Show()
调用更改为使用DataGridView
而不是表单,我会遇到同样的问题,但它会出现在网格的左上角,而不是鼠标所在的位置
奇怪的是,如果我将此事件更改为MouseClick
事件(而不是CellMouseclick
事件),则所有操作都会正常进行,并且上下文菜单会精确显示鼠标指针所在的位置。此选项的问题是,用户可能没有右键单击当前选定的单元格,这意味着当他们单击菜单项时,选定的单元格将被更改,而不是右键单击的单元格
有人知道为什么用
CellMouseClick
创建的上下文菜单没有显示在正确的位置吗?尝试使用PointToClient
获得正确的位置,它没有显示在正确的位置,因为e.位置是相对于父对象左上角的位置,在这种情况下,这就是细胞本身。位置属性始终相对于其容器
要获取鼠标光标相对于窗体本身左上角的位置,可以使用
this.PointToClient(Cursor.Position);
第二个参数是鼠标相对于单元格左上角的位置。按照编程,使该偏移相对于表单,这将使菜单显示在表单的左上角。使用DGV作为第一个参数也不起作用,现在它位于网格的左上角
有几种方法可以解决这个问题,但这是最简单的方法:
Point pos = this.PointToClient(Cursor.Position);
menu.Show(this, pos, LeftRightAlignment.Right);
您可以任意将其替换为grvFieldData。我已经解决了这个问题。。。人们可能会觉得这种方法很奇怪,但效果很好!) 如果我们想在DATGRIDVIEW单元格中按下右鼠标BTN,而不是在屏幕中间或其他地方看到上下文菜单,则需要: 做一些变量
int x=0;
int y=0;
为datagridview1 lke生成一个“MouseMove”事件,该事件:
private void dataGridView1_MouseMove(object sender, MouseEventArgs e)
{
x = e.X;
y = e.Y;
}
及
在datagridview鼠标单击事件中欢迎您:
if e.button= mousebutton.right
{
contextmenu1.Show(MousePosition);
}
没有<代码> PotoToCLIONT(E位置)将上下文菜单放在屏幕的顶部,并且<代码> PooToScCurn(E.Load)将上下文菜单放在窗体的中间部分。GrvFieldDistaPosiToCoLIONT(E位置)同样的问题,即使我将
此调用更改为grvFieldData
:-/如何获取单击的单元格位置(单元格不是控件,因此我无法将其传递到Show()
)或鼠标的屏幕位置?嘿,我的答案会稍微复杂一些,加上一些X和Y坐标。我希望我能知道光标。几周前的位置+1为简单起见!太棒了,这真是个奇迹<代码>光标。位置是我所缺少的!这种解决方案有不必要的开销,因为用户将鼠标移动到网格上(我认为这种情况会经常发生),它会不断地写入内存。事件已包含该位置。
private void dataGridView1_CellMouseClick(object sender, DataGridViewCellMouseEventArgs e)
{
if (e.Button == System.Windows.Forms.MouseButtons.Right)
{
contextMenuStrip1.Show(dataGridView1, x,y);
}
}
if e.button= mousebutton.right
{
contextmenu1.Show(MousePosition);
}