2013-02-26 10 views
1

При кодировании маленькой игры я столкнулся с проблемой; мои формы KeyDown и KeyUp события не срабатывают вообще.Событие KeyDown не срабатывает?

Это кода формы:

public class GameForm : Form 
{ 
    private ControllableBlock player; 

    public GameForm() 
    { 
     KeyDown += Game_KeyDown; 
     KeyUp += Game_KeyUp; 

     player = new ControllableBlock(); 
     Controls.Add(player); 
    } 

    private void Game_KeyDown(object sender, KeyEventArgs e) 
    { 
     player.ReactToKey(e.KeyCode); 
    } 

    private void Game_KeyUp(object sender, KeyEventArgs e) 
    { 
     player.ReactToKey(e.KeyCode); 
    } 
} 

Там намного больше происходит, но я только вставил соответствующий код.

Я уже пробовал установить this.KeyPreview = true; и звонил this.Focus();, не работает. Проблема не в методе ReactToKey(), я уже установил там точку останова, и событие никогда не запускается.


Edit: После некоторых тестов я пришел к выводу, что проблема в моей ControllableBlock. Но я понятия не имею, почему, но я над этим работаю. Если я прокомментирую все, что связано с player, события начинают стрелять.


Edit 2: Похоже, эта проблема меня наследуя моей ControllableBlock от Control. Если я наследую его от Panel, он отлично работает. Почему это? Не могу я запустить событие, если я унаследовал от управления? Класс ControllableBlock пуст, так что он даже не делает ничего, кроме наследования от Control.


Edit 3: Теперь, когда я начал щедроты, я хотел бы уточнить, что я не ищу решение о том, как сделать огнь событий, я ищу для причина, почему они не срабатывают, если я наследую от Control.

+0

'player.Obstacles.Add (препятствие)', что здесь происходит? Я попытался воспроизвести вашу проблему, но все обработчики событий с 'this.KeyPreview = true' работают хорошо (кроме клавиш со стрелками - подумают об обходном пути здесь). Без этой строки, действительно, не происходит никаких событий – Nogard

+0

Я не знаю, почему ваш не работает, но мои работы. Просто создайте новый элемент управления, когда будет показана форма, сфокусируйте это управление так, как показано на рисунке: + = (s, e) => {myControl.Focus(); }; 'и затем нажмите несколько клавиш вниз, это сработает. Если вы хотите сфокусировать свой контроль нажатием мыши, я думаю, что это не сфокусировано именно так, и вы думали, что это не сработало? –

ответ

3

Я был в состоянии воспроизвести подобный вопрос (который, как мы надеемся, связанные ..)

Объяснение:

  • управления, которые возвращают CanSelect==true выбираются для ввода с клавиатуры
  • пустой потомка Control() является выбирается, один из Panel() не
  • Будет выбран первый выбираемый элемент управления, добавленный к форме
  • Выбранный контроль украдет события клавиатуры от своих родителей по умолчанию
  • Некоторые ключи, используемые для навигации в пределах окна требуют дополнительных шагов, чтобы быть дальнейшей обработки

Проверить here хороший обзор того, как работает ввод окна клавиатуры.

код воспроизвести его:

public class GameForm : Form 
{ 
    public GameForm() 
    { 
     this.KeyDown += Game_KeyDown; 
     var tests = new List<Control[]>() { 
      new[] { new Panel() }, 
      new[] { new Panel(), new Panel() }, 
      new[] { new Control() }, 
      new[] { new Control(), new Panel() }, 
      new[] { new Panel(), new Control() } 
     }; 
     // When test index 2 to 4 used, keyboard input does not reach form level 
     Controls.AddRange(tests[0]);    
     // When uncommented, ensures all keyboard input reaches form level 
     /*this.KeyPreview = true;    
     // Additional plumbing required along with KeyPreview to allow arrow and other reserved keys 
     foreach (Control control in this.Controls) 
     { 
      control.PreviewKeyDown += control_PreviewKeyDown; 
     }*/ 
    } 
    void control_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e) 
    { 
     e.IsInputKey = true; 
    } 
    private void Game_KeyDown(object sender, KeyEventArgs e) 
    { 
     // breakpoint here 
     Debug.WriteLine(e.KeyCode); 
    } 
} 
+0

Этот ответ может быть интересным, но это не поможет решить проблему. – Elmue

0

Попробуйте переместить настройку обработчика в событие Form_Load, а не в конструктор. Если в конструкторе не будет вызова Initialize()? Я бы не стал рекомендовать его удалить

Если ControllableBlock наследуется от Panel, у него будет больше событийных подключений и улучшена настройка интерфейса пользовательского интерфейса, чем базовый объект Control.

+0

Инициализировать что? Это все закодировано вручную, и я вообще не использовал конструктора. Все, что нужно инициализировать, инициализируется в конструкторе. Событие Form_Load не помогло. Он выстрелил, так что проблема в ключевых событиях. –

4

Если ваши мероприятия должны быть применены во всей области, попробуйте установить свойство KeyPreview на true - это позволит вам запускать соответствующие события независимо от сфокусированного управления.

this.KeyPreview = true; 

В противном случае вы должны прикрепить эти события непосредственно к управлению, которое будет обрабатывать их.

Edit:

Я удалил InitializeComponent(); от моей формы и получил поведение, идентичное ваш.

После реализации решения, представленного в this вопрос, все события начали нормально функционировать.
Копировать фрагмент кода здесь:

protected override bool ProcessCmdKey(ref Message msg, Keys keyData) { 
     if (keyData == Keys.Left) { 
      // Do your staff for Left Key here 

      return true; 
     } 
     // you need to add if condition to every direction you want to handle 
     return base.ProcessCmdKey(ref msg, keyData); 
    } 
+0

Он делает это правильно. Вы только что сделали это по-старому. –

+0

вот как VS2012 генерирует их с .Net 4.5 ... узнал что-то новое сегодня, спасибо. Отредактированный ответ, чтобы выделить еще одну возможную опцию – Nogard

+0

@Nogard К сожалению, это я уже упомянул в своем основном сообщении. Прочтите последние изменения для получения дополнительной информации. –

0

Вы должны сделать свой Выбирается управления, прежде чем он может получить фокус.

Попробуйте добавить следующие строки в конструкторе:

this.SetStyle(ControlStyles.Selectable, true); 

И убедитесь, что вы даете форму фокуса после его отображения. Или, переопределите OnMouseDown() и вызовите this.Focus() в нем.

+0

Без разницы:/ –

Смежные вопросы