ToolStripDropDownButton - 使用Esc键更改下拉行为

时间:2011-12-20 07:00:14

标签: c# winforms wndproc

我有一个带有ToolStripDropDownButton的自定义控件。 ToolStripDropDownButton有许多工具条项(具体来说,是一个自定义工具条项目,它们是复选框)。用户可以选择他们想要的复选框项目,然后处理DropDownClosed事件,然后使用这些选中的项目。

目标是让用户通过点击转义键来取消他的选择。问题是当按下Escape键时DropDownClosed事件也会触发。因此,当用户选择选项并想要按Escape取消选择时,DropDownClosed事件将触发,我最终“应用”这些设置。

我试过在托管ToolStripDropDownButton的控件上玩下面的覆盖:

protected override bool ProcessCmdKey
protected override bool ProcessKeyPreview
protected override void WndProc

没有太大成功,因为下拉似乎在处理任何这些事件之前隐藏。 修改此行为的最佳方法是什么?

3 个答案:

答案 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事件是否被视为已取消。