我找到了一种方法来处理ListView Header
列中的右键单击。
我需要定义一个新的ListView
项并覆盖WndProc
。
public class ListViewUpdated : ListView
{
public ContextMenuStrip HeaderContextMenu { get; set; }
private frmMain mainForm;
public ListViewUpdated()
{
mainForm = null;
}
public void setAttributes(frmMain frm, ContextMenuStrip menu)
{
mainForm = frm;
HeaderContextMenu = menu;
}
protected override void WndProc(ref System.Windows.Forms.Message m)
{
base.WndProc(ref m);
if (m.Msg == 0x7b)
{ //WM_CONTEXTMENU
if (m.WParam != this.Handle)
{
mainForm.Invoke(mainForm.delegateDeleteColumn,
new Object[] { HeaderContextMenu });
}
}
}
private void InitializeComponent()
{
this.SuspendLayout();
this.ResumeLayout(false);
}
}
这确实很好用。我使用了一个委托,因此事件触发器可以是表单中的一个函数。
到目前为止,表格中的事件是:
if (tabControl1.SelectedIndex == 0)
{
System.Drawing.Point mousePos = lsvRequestsByParameters.PointToClient(Control.MousePosition);
hitTest = lsvRequestsByParameters.HitTest(mousePos);
}
else
{
System.Drawing.Point mousePos = lsvRequestsByParametersToSave.PointToClient(Control.MousePosition);
hitTest = lsvRequestsByParametersToSave.HitTest(mousePos);
}
HeaderContextMenu.Show(Control.MousePosition);
它被正确调用。
它允许我弹出标题上的上下文菜单。
问题是选项之一是删除列:
private void deleteColumnToolStripMenuItem2_Click(object sender, EventArgs e)
{
int columnIndex = hitTest.Item.SubItems.IndexOf(hitTest.SubItem);
lsvRequestsByParameters.Columns.RemoveAt(columnIndex);
}
问题如下:
int columnIndex = hitTest.Item.SubItems.IndexOf(hitTest.SubItem);
似乎当我设置hitTest
变量时,如果鼠标位于标题之上,则它不会返回可用的内容。请注意,如果单击一个空单元格,以这种方式使用hitTest会正确地返回columnIndex
。
那么我该怎样做才能获得columnIndex
?
答案 0 :(得分:1)
只要Items
ListView
中有HitTest
,您就可以愚弄 Point eLoc = listView1.PointToClient(Control.MousePosition);
ListViewHitTestInfo hit = null;
int i = 0;
do
{
Point vp = new Point(eLoc.X, listView1.Items[i].Bounds.Top);
hit = listView1.HitTest(vp);
i++;
}
while( hit.SubItem == null && i < listView1.Items.Count);
var ColumnIndex = hit.Item.SubItems.IndexOf(hit.SubItem);
喂食 的位置>标题..:
SubItems
请注意,只有当Items[0]
呈锯齿状时才需要循环。否则,您可以随时前往ListView
。
<强>更新强>
如果您有理由想要点击空 private List<Rectangle> lvHeaderBounds = new List<Rectangle>();
的标题,则可以使用此解决方法:
声明一个包含标题的所有边界矩形的变量:
ColumnClick
在上面处理 Point eLoc = listView1.PointToClient(Control.MousePosition);
var ColumnIndex = -1;
if (listView1.Items.Count == 0)
{
getHeaders(listView1);
for (int i = 0; i < lvHeaderBounds.Count; i++)
if (lvHeaderBounds[i].X + lvHeaderBounds[i].Width > eLoc.X)
{
ColumnIndex = i;
break;
}
}
else...
的代码中使用了这个:
ColumHeader
要收集边界矩形,我们需要在void getHeaders(ListView lv)
{
lvHeaderBounds.Clear();
for (int i = 0; i < lv.Columns.Count; i++)
{
ColumnHeader ch = lv.Columns[i];
int left = i == 0 ? 0 : lvHeaderBounds[i-1].X + ch.Width;
Rectangle r = new Rectangle(left, 0, ch.Width, 0);
lvHeaderBounds.Add(r);
}
}
集合上循环。这是一个实现此功能的功能:
private void listView1_ColumnReordered(object sender, ColumnReorderedEventArgs e)
{
if (lvHeaderBounds != null) lvHeaderBounds.Clear();
getHeaders(sender as ListView);
}
private void listView1_ColumnWidthChanged(object sender, ColumnWidthChangedEventArgs e)
{
if (lvHeaderBounds != null) lvHeaderBounds.Clear();
getHeaders(sender as ListView);
}
当用户或代码修改标题布局时,我们还需要刷新我们的集合:
Height
请注意,列表中的0
值均为Share with me folder
!
另请注意,在我的测试中,即使在调整标题和/或滚动它们之后,代码也能正常工作..