2009-08-19 24 views
24

Tôi đang tạo một trò chơi nhỏ, trò chơi được in lên bảng điều khiển ở dạng cửa sổ. Bây giờ tôi muốn nắm bắt các sự kiện keydown để xem nếu các phím mũi tên đã được ép, vấn đề tuy nhiên là tôi dường như không thể nắm bắt nó.C# cố gắng chụp sự kiện KeyDown trên một biểu mẫu

Hãy để tôi giải thích, trên biểu mẫu tôi có 4 nút và các điều khiển khác và nếu người dùng nhấn một trong các nút (để kích hoạt sự kiện trò chơi) thì nút có tiêu điểm và tôi không thể chụp chuyển động với các phím mũi tên.

tôi đã cố gắng một cái gì đó giống như

private void KeyDown(KeyEventArgs e) 
    { 
     if (e.KeyCode == Keys.Left) 
     { 
      game.MovePlayer(DonutWarsLibrary.GameObjects.Direction.E); 
      game.DrawObjects(panel1.CreateGraphics()); 
     } 
     else if (e.KeyCode == Keys.Right) 
     { 
      game.MovePlayer(DonutWarsLibrary.GameObjects.Direction.W); 
      game.DrawObjects(panel1.CreateGraphics()); 
     } 
     else if (e.KeyCode == Keys.Up) 
     { 
      game.MovePlayer(DonutWarsLibrary.GameObjects.Direction.N); 
      game.DrawObjects(panel1.CreateGraphics()); 
     } 
     else if (e.KeyCode == Keys.Down) 
     { 
      game.MovePlayer(DonutWarsLibrary.GameObjects.Direction.S); 
      game.DrawObjects(panel1.CreateGraphics()); 
     } 
    } 

và sau đó khi chính thức xuống Sự kiện này được ép, tôi sử dụng này

private void MainForm_KeyDown(object sender, KeyEventArgs e) 
    { 
     KeyDown(e); 
    } 

Tôi cũng đã thêm KeyDown cho các nút và các điều khiển khác nhau trên cửa sổ hình thức, nhưng tôi không nhận được bất kỳ phản ứng lại. Tôi đã thiết lập một điểm ngắt bên trong hàm để xem nó có được gọi hay không, nhưng điểm ngắt đó không bao giờ kích hoạt?

Bất kỳ ý tưởng nào?

Tối ưu nhất là có sự kiện KeyDown chung kích hoạt (bất kể điều khiển hiện có tiêu điểm) và sau đó gọi phương thức KeyDown.

Trả lời

17

Override IsInputKey hành vi


Bạn phải ghi đè hành vi IsInputKey để thông báo rằng bạn muốn quyền Ar phím hàng được coi là một InputKey và không phải là một phím hành vi đặc biệt. Đối với điều đó, bạn phải ghi đè lên phương pháp cho mỗi điều khiển của bạn. tôi sẽ khuyên bạn nên tạo Button thắng của bạn, hãy nói myButton

Lớp dưới đây tạo ra một nút tùy chỉnh đó sẽ ghi đè các IsInputKey phương pháp để các phím mũi tên bên phải không được điều trị như một chìa khóa đặc biệt. Từ đó bạn có thể dễ dàng làm cho nó cho các phím mũi tên khác hoặc bất cứ điều gì khác.

public partial class MyButton : Button 
    { 
     protected override bool IsInputKey(Keys keyData) 
     { 
      if (keyData == Keys.Right) 
      { 
       return true; 
      } 
      else 
      { 
       return base.IsInputKey(keyData); 
      } 
     } 
    } 

Sau đó, bạn có thể đối xử với sự kiện sự kiện KeyDown của bạn trong mỗi nút khác nhau hoặc ở dạng bản thân:

Trong Buttons' KeyDown Phương pháp cố gắng thiết lập các thuộc tính:

private void myButton1_KeyDown(object sender, KeyEventArgs e) 
{ 
    e.Handled = true; 
    //DoSomething(); 
} 

- HOẶC -

xử lý hành vi chung trong biểu mẫu: (không được đặt e.Handled = true; trong các nút)

private void Form1_KeyDown(object sender, KeyEventArgs e) 
{ 
    //DoSomething(); 
} 
+1

Đó là bán làm việc, bây giờ tôi nhận được sự kiện keydown nhưng khi tôi nhấn các nút, họ vẫn trở thành tập trung và sau đó nó dừng lại để làm việc trừ khi tôi nhấn phím mũi tên trên cho đến khi nó vòng qua tất cả và họ mất tập trung. – Patrick

+0

Bạn đang bắt các sự kiện KeyDown "Keys.Left" và "Keys.Right" như thế nào? –

+0

Tôi đã chỉnh sửa câu trả lời của mình để tham chiếu Phương thức IsInputKey –

29

Bạn đã đặt thuộc tính KeyPreview của biểu mẫu thành true? Điều đó sẽ khiến cho biểu mẫu nhận được "cái nhìn đầu tiên" tại các sự kiện quan trọng.

Cập nhật: việc này hoạt động bình thường khi số Button tập trung có vẻ hơi phức tạp. Nút Điều khiển chặn các phím mũi tên và di chuyển tiêu điểm đến điều khiển kế tiếp hoặc trước đó theo thứ tự tab theo cách sao cho các sự kiện KeyDown, KeyUpKeyPress không được nâng lên. Tuy nhiên, sự kiện PreviewKeyDown được nâng lên, do đó có thể được sử dụng:

private void Form_KeyDown(object sender, KeyEventArgs e) 
{ 
    e.Handled = ProcessKeyDown(e.KeyCode); 
} 

// event handler for the PreViewKeyDown event for the buttons 
private void ArrowButton_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e) 
{ 
    ProcessKeyDown(e.KeyCode); 

} 

private bool ProcessKeyDown(Keys keyCode) 
{ 
    switch (keyCode) 
    { 
     case Keys.Up: 
      { 
       // act on up arrow 
       return true; 
      } 
     case Keys.Down: 
      { 
       // act on down arrow 
       return true; 
      } 
     case Keys.Left: 
      { 
       // act on left arrow 
       return true; 
      } 
     case Keys.Right: 
      { 
       // act on right arrow 
       return true; 
      } 
    } 
    return false; 
} 

Tuy nhiên, trọng tâm di chuyển xung quanh một cách khá xấu xí ...

+0

Đó là bán làm việc, bây giờ tôi có được sự kiện KeyDown nhưng khi tôi nhấn nút, họ vẫn trở nên tập trung và sau đó nó dừng lại để làm việc trừ khi tôi bấm phím mũi tên trên cùng cho đến khi nó vòng qua tất cả chúng và chúng mất tập trung. – Patrick

+0

@Patrick: có, các phím mũi tên và nút điều khiển dường như có mối quan hệ rất chặt chẽ. Tôi đã cập nhật câu trả lời của tôi, cho nó một bước về phía trước. –

7
public partial class Form1 : Form 
{ 
    public Form1() 
    { 
     InitializeComponent(); 
     KeyPreview = true; 
     KeyDown += new KeyEventHandler(Form1_KeyDown); 
    } 

    void Form1_KeyDown(object sender, KeyEventArgs e) 
    { 
     System.Diagnostics.Debug.Write(e.KeyCode); 
    } 
} 
+1

Bạn không biết rằng câu trả lời của bạn tiết kiệm rất nhiều thời gian của tôi. Cảm ơn rất nhiều. –

+0

Nó phải là 'KeyPreview = true;' mà làm cho KeyDown kích hoạt –

16

Tôi tin rằng cách dễ nhất giải quyết vấn đề này là thông qua trọng phương pháp ProcessCmdKey() của biểu mẫu. Bằng cách đó, logic xử lý khóa của bạn được thực hiện bất kể điều khiển nào tập trung vào thời điểm nhấn phím. Bên cạnh đó, bạn thậm chí có thể chọn để kiểm soát tập trung nhận được chìa khóa sau khi bạn xử lý nó (trả về false) hay không (trả về true).
ít trò chơi ví dụ của bạn có thể được viết lại như thế này:

protected override bool ProcessCmdKey(ref Message msg, Keys keyData) 
{ 
    if (keyData == Keys.Left) 
    { 
     MoveLeft(); DrawGame(); DoWhatever(); 
     return true; //for the active control to see the keypress, return false 
    } 
    else if (keyData == Keys.Right) 
    { 
     MoveRight(); DrawGame(); DoWhatever(); 
     return true; //for the active control to see the keypress, return false 
    } 
    else if (keyData == Keys.Up) 
    { 
     MoveUp(); DrawGame(); DoWhatever(); 
     return true; //for the active control to see the keypress, return false 
    } 
    else if (keyData == Keys.Down) 
    { 
     MoveDown(); DrawGame(); DoWhatever(); 
     return true; //for the active control to see the keypress, return false 
    } 
    else 
     return base.ProcessCmdKey(ref msg, keyData); 
} 
+0

Thật tuyệt vời, nhưng phím cách không xử lý – Singlet

+2

Giải pháp tuyệt vời. Chụp tất cả các lần nhấn phím. Ngay cả không gian. – Kibbee

+0

Đây là cách dễ nhất để giải quyết các vấn đề đó và cũng làm việc hoàn hảo cho tôi. –

Các vấn đề liên quan