2011-12-20 4 views
0

У меня есть настраиваемый элемент управления с помощью ToolStripDropDownButton. В ToolStripDropDownButton имеется ряд элементов инструментальной панели (в частности, настраиваемые элементы инструментальной панели, которые имеют флажки). Пользователь может выбрать те элементы, которые они хотят, и обрабатывать событие DropDownClosed, а затем использовать эти отмеченные элементы.ToolStripDropDownButton - изменение выпадающего поведения с помощью клавиши Esc

Задача предназначена для использования пользователем Отменить его выбор, нажав кнопку выхода. Проблема в том, что событие DropDownClosed также срабатывает при нажатии клавиши Escape. Поэтому, когда пользователь выбирает параметры и хочет попасть в Escape, чтобы отменить выбор, происходит событие DropDownClosed, и я в конечном итоге «применяю» эти настройки.

Я пытался играть вокруг со следующими переопределениями по контролю размещено ToolStripDropDownButton:

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

без особого успеха, как выпадающие кажется, чтобы скрыть, прежде чем какие-либо из этих событий обрабатываются. Каков наилучший способ изменить это поведение?

ответ

0

Как насчет событий KeyDown или KeyPressed? По крайней мере, один из них, должно быть, должен сгореть перед событием DropDownClosed, а затем вы можете проверить, был ли нажат Escape, чтобы вы могли установить флаг для обработчика DropDownClosed.

Редактировать: Если ProcessCmdKey или ProcessKeyPreview запускаются после события DropDownClosed, вы можете создать задержку с помощью таймера. DropDownClosed запускает таймер, а затем ProcessCmdKey или ProcessKeyPreview может установить флаг, если нажать Escape. Когда таймер Ticks вы можете отменить или применить проверки, выполненные пользователем.

+0

Я уже пробовал это, но дочерние элементы управления обрабатывают событие до основного элемента управления. В форме вы можете установить для Form.KeyPreview значение true, чтобы получать ключевые события перед элементом управления. Но пользовательские элементы управления различны. В любом случае даже попытка обработать ключевое событие, похоже, произойдет * после того, как * раскрывающийся список закрылся. Я могу переопределить метод OnDropDownClosed, но мне нужно указать, был ли нажат Esc. – MoSlo

+1

Как пользователь должен указать, что выбор должен быть применен - ​​щелкнув в любом месте вне меню ToolStrip?Если это так, не лучше ли добавить параметр «Применить» в меню ToolStrip? Тогда пользователь (и ваш код ...) точно знает, когда применять изменения и когда отменять. – Veldmuis

2

Попробуйте использовать эту версию ToolStripDropDown, где он перехватывает ключа Esc от закрытия выпадающего:

public class ToolStripDropDownEx : ToolStripDropDown { 

    protected override bool ProcessDialogKey(Keys keyData) { 
    if (keyData == Keys.Escape) 
     return true; 
    else 
     return base.ProcessDialogKey(keyData); 
    } 
} 
+0

Выглядит многообещающе. Я унаследовал ToolStripDownButton, чтобы обработать KeyDown (processCmdKey, wndProc и т. Д.), Но даст этому попробовать. – MoSlo

0

Ok, причины, почему переопределение не работает на ToolStripDropDownButton происходит потому, что это не было компонент, который имел фокус. Элементы в раскрывающемся меню имели фокус при отображении выпадающего меню и все доступные переопределения (ProcessCmdKey, ProcessDialogKey и т. Д.) На элементах toolBoxButton запускаются при показе выпадающего меню.

В конце концов, я создал два производных класса для самого элемента 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 считается расторгнутым или нет.