VB.NET中ListView右键调用ContextMenuStrip弹出位置异常如何解决
解决方案
核心错误原因
你的代码第一个参数传递的控件和事件绑定的控件不匹配:事件绑定的是ListViewResults的鼠标抬起事件,但Show方法第一个父容器参数传的是ListView1,如果两个控件不是同一个实例,传入的相对坐标会基于错误的控件换算,必然出现位置错位。
修正后的实现代码
方式1:基于ListView的相对坐标弹出(推荐,精度最高)
直接将事件绑定的ListView作为父容器,传入鼠标事件自带的客户端坐标即可:
Private Sub ListViewResults_MouseUp(sender As Object, e As MouseEventArgs) Handles ListViewResults.MouseUp If e.Button = Windows.Forms.MouseButtons.Right Then lvChangedFilesMenuStrip.Show(ListViewResults, e.Location) End If End Sub
e.Location本身就等价于New Point(e.X, e.Y)的结构,不需要额外实例化。
方式2:基于全局鼠标位置弹出
如果要使用屏幕坐标(比如Cursor.Position),直接调用对应重载即可,不需要传父控件参数:
lvChangedFilesMenuStrip.Show(Cursor.Position)
之前写法的错误说明
- 传
New Point(e.X, e.Y)时第一个控件参数错误,相对坐标被换算到了错误的控件坐标系下 - 把
Cursor.Position(屏幕坐标)传给带父控件参数的Show重载时,系统会把屏幕坐标误当成父控件的内部坐标做二次换算,导致菜单飞到屏幕边缘 - 直接传
e.X, e.Y调用双整数参数的Show重载时,该重载要求输入的是全局屏幕坐标,而e.X/e.Y是ListView内部的相对坐标,直接传自然位置错误
可选扩展:菜单对齐右键选中的条目下方
如果需要菜单严格对齐右键点击的ListView条目底部,而不是鼠标点击位置,可以加命中测试逻辑:
Private Sub ListViewResults_MouseUp(sender As Object, e As MouseEventArgs) Handles ListViewResults.MouseUp If e.Button = Windows.Forms.MouseButtons.Right Then Dim hitTestInfo = ListViewResults.HitTest(e.X, e.Y) If hitTestInfo.Item IsNot Nothing Then ' 选中右键点击的条目 ListViewResults.SelectedItems.Clear() hitTestInfo.Item.Selected = True ' 菜单显示在条目左下角位置 lvChangedFilesMenuStrip.Show(ListViewResults, hitTestInfo.Item.Bounds.Left, hitTestInfo.Item.Bounds.Bottom) End If End If End Sub
内容的提问来源于stack exchange,提问作者Ted Kon
相关产品推荐
相关产品推荐

