我有一个带有ToolStripDropDownButton的自定义控件。 ToolStripDropDownButton有许多工具条项(具体来说,是一个自定义工具条项目,它们是复选框)。用户可以选择他们想要的复选框项目,然后处理DropDownClosed事件,然后使用这些选中的项目。
目标是让用户通过点击转义键来取消他的选择。问题是当按下Escape键时DropDownClosed事件也会触发。因此,当用户选择选项并想要按Escape取消选择时,DropDownClosed事件将触发,我最终“应用”这些设置。
我试过在托管ToolStripDropDownButton的控件上玩下面的覆盖:
protected override bool ProcessCmdKey
protected override bool ProcessKeyPreview
protected override void WndProc
没有太大成功,因为下拉似乎在处理任何这些事件之前隐藏。 修改此行为的最佳方法是什么?
答案 0 :(得分:2)
尝试使用此版本的ToolStripDropDown
拦截 Esc 键,关闭下拉列表:
public class ToolStripDropDownEx : ToolStripDropDown {
protected override bool ProcessDialogKey(Keys keyData) {
if (keyData == Keys.Escape)
return true;
else
return base.ProcessDialogKey(keyData);
}
}
答案 1 :(得分:0)
KeyDown或KeyPressed事件怎么样?有希望在DropDownClosed事件之前触发其中一个,然后你可以检查Escape是否被按下,这样你就可以为DropDownClosed处理程序设置一个标志。
编辑:如果在DropDownClosed事件之后触发ProcessCmdKey或ProcessKeyPreview,您可以使用计时器构建延迟。 DropDownClosed启动计时器,然后ProcessCmdKey或ProcessKeyPreview可以设置一个标志,如果按下Escape。当计时器Ticks时,您可以撤消或应用用户完成的检查。
答案 2 :(得分:0)
好的,覆盖不能处理ToolStripDropDownButton的原因是因为它不是具有焦点的组件。当显示下拉列表时,下拉列表中的项具有焦点,并且在显示下拉列表时正在触发toolBoxButton项上的所有可用覆盖(ProcessCmdKey,ProcessDialogKey等)。
最后,我为ToolStrip项本身(本例中为复选框)和容纳ToolStripDropDownButton创建了两个派生类。
public class EscapingToolStripCheckBox : CustomControls.ToolStripCheckBox
{
private EscapingToolStripDropDownButton _parent;
public EscapingToolStripCheckBox(EscapingToolStripDropDownButton parent)
: base()
{
_parent = parent;
}
protected override bool ProcessCmdKey(ref Message m, Keys keyData)
{
if (keyData == Keys.Enter)
{
_parent.HandleSelection(false);
return true;
}
else if (keyData == Keys.Escape)
{
_parent.HandleSelection(true);
return true;
}
// Dont need to execute HandleSelection under any other condition.
return base.ProcessCmdKey(ref m, keyData);
}
}
...其中HandleSelection采用布尔值来确定是否要取消选择。
public void HandleSelection(bool selectionCancelled)
{
_selectionCancelled = selectionCancelled;
this.HideDropDown();
}
从那里,我可以轻松地检查属性(在控件本身或作为事件参数的一部分),以确定DropDownClosed事件是否被视为已取消。