我有一个简单的下拉样式的组合框。我想在用户右键单击列表中的项目时打开一个新窗口,但无法让它检测到发生了右键单击。
我的代码:
private void cmbCardList_MouseClick(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Right && cmbCardList.SelectedIndex != -1)
{
frmViewCard vc = new frmViewCard();
vc.updateCardDisplay(cmbCardList.SelectedItem);
vc.Show();
}
}
如果我改变 e.Button == MouseButtons.Left 整个事情就会很好地触发。有什么办法可以让它按我的预期工作吗?
恐怕除非你进行一些认真的黑客攻击,否则这是不可能的。 这篇文章将解释。
为您引述:
单独控制
以下控件不符合标准鼠标单击事件行为:
Button、CheckBox、ComboBox 和 RadioButton 控件
左键单击:单击、鼠标单击
右键单击:没有引发点击事件
左双击:单击、鼠标单击; 点击,鼠标点击
右键双击:无点击事件 凸起
作为这个问题的墓志铭,您可以使用普通的 .NET 功能来完成这项工作;您只需更深入地了解事件调用堆栈即可。不处理 MouseClick 事件,而是处理 MouseDown 事件。我最近不得不做类似的事情,我只是覆盖了 OnMouseDown 方法,而不是附加处理程序。但是,处理程序也应该工作。这是代码:
protected override void OnMouseDown(MouseEventArgs e)
{
if (e.Button == MouseButtons.Right && !HandlingRightClick)
{
HandlingRightClick = true;
if (!cmsRightClickMenu.Visible)
cmsRightClickMenu.Show(this, e.Location);
else cmsRightClickMenu.Hide();
}
base.OnMouseDown(e);
}
protected override void OnMouseUp(MouseEventArgs e)
{
HandlingRightClick = false;
base.OnMouseUp(e);
}
private bool HandlingRightClick { get; set; }
HandlingRightClick属性是为了防止多次触发OnMouseDown逻辑; UI 将发送多个 MouseDown 消息,这可能会干扰隐藏右键菜单。为了防止这种情况,我只在第一个 MouseDown 触发器上执行一次逻辑(该逻辑非常简单,我不关心两次调用是否发生竞争,但您可能会这样做),然后忽略任何其他 MouseDown 触发器,直到发生 MouseUp。它并不完美,但它可以满足您的需要。
您可以使用 ContextMenuStrip 的 Opening 事件来处理右键单击事件。
var chk = new CheckBox();
chk.ContextMenuStrip = cmsNone;
private void cmsNone_Opening(object sender, CancelEventArgs e)
{
e.Cancel = true;
var cms = (ContextMenuStrip)sender;
var chk = cms.SourceControl;
//do your stuff
}
我以最简单的方式使用了 MouseDown:
if (e.Button != MouseButtons.Right) return;
(new Controls.FormComboContextMenu()).Show(cmb, cmb.PointToClient(Cursor.Position + new Size(5, 5)));
无论我们用两个鼠标按钮单击四周,它都始终有效。