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);
}