2012-03-05 9 views
0

私は矢印で移動することができる単純なアプリケーションを作ろうとしています。これまでは、ユーザーがProcessCmdKey()メソッドを上、下、左と右に移動できるように管理していました。矢印キーを検出 - 複数のキーを一度に

protected override bool ProcessCmdKey(ref Message msg, Keys keyData) 
     { 
      if (keyData == Keys.Up) 
      { 
       statek.Y--; 
       return true; 
      } 
      if (keyData == Keys.Left) 
      { 
       statek.X--; 
       return true; 
      } 
      if (keyData == Keys.Right) 
      { 
       statek.X++; 
       return true; 
      } 
      if (keyData == Keys.Down) 
      { 
       statek.Y++; 
       return true; 
      } 
      return base.ProcessCmdKey(ref msg, keyData); 
     } 

問題は、私はユーザーに斜めにも行きたいと思っています。同時に、同じように。私はいくつかの解決策を探そうとしましたが、不幸にも運がありません。 私はそれを変更しようとすると、左/右のキーを回転/回転させるので、上のキーは「上へ」ではなく「上へ」であることを意味します。しかしまず第一に、2つのキーを一度に作る必要があります。

ですから、対角線上を移動するには、2つのキーを同時に使用することができますか?

PS。 Atm、私はピクチャボックス上の楕円を動かして、Point statek = new Point(250, 470);コードを変更するので、タイマーがきつくなるたびに、XまたはYが変更されたかどうかを確認し、新しい場所に描画します。頻繁にダニ - これは私が今リアルタイムの動きを達成しようとした方法です。それは複雑なアプリケーションではありません。

答えて

2

まず、矢印キーを保持するためにビット列挙を作成状態:次に

[Flags] 
enum ArrowsPressed 
{ 
    None = 0x00, 
    Left = 0x01, 
    Right = 0x02, 
    Up = 0x04, 
    Down = 0x08, 
    All = 0x0F 
} 

状態を追跡するための部材と、それを変更する機能を、

ArrowsPressed arrowsPressed; 

void ChangeArrowsState(ArrowsPressed changed, bool isPressed) 
{ 
    if (isPressed) 
    { 
     arrowsPressed |= changed; 
    } 
    else 
    { 
     arrowsPressed &= ArrowsPressed.All^changed; 
    } 
} 
KeyDownイベントとkeyUpイベントは、(フォームが子コントロールがそれらを盗むしたい場合は、キー受信できるようにtrueにフォームのKeyPreviewプロパティを設定することを忘れないでください

上書き、最後に

protected override void OnKeyDown(KeyEventArgs e) 
{ 
    base.OnKeyDown(e); 
    switch (e.KeyCode) 
    { 
     case Keys.Down: 
      ChangeArrowsState(ArrowsPressed.Down, true); 
      break; 
     case Keys.Up: 
      ChangeArrowsState(ArrowsPressed.Up, true); 
      break; 
     case Keys.Left: 
      ChangeArrowsState(ArrowsPressed.Left, true); 
      break; 
     case Keys.Right: 
      ChangeArrowsState(ArrowsPressed.Right, true); 
      break; 
     default: 
      return; 
    } 
    HandleArrows(); 
    e.Handled = true; 
} 
protected override void OnKeyUp(KeyEventArgs e) 
{ 
    base.OnKeyUp(e); 
    switch (e.KeyCode) 
    { 
     case Keys.Down: 
      ChangeArrowsState(ArrowsPressed.Down, false); 
      break; 
     case Keys.Up: 
      ChangeArrowsState(ArrowsPressed.Up, false); 
      break; 
     case Keys.Left: 
      ChangeArrowsState(ArrowsPressed.Left, false); 
      break; 
     case Keys.Right: 
      ChangeArrowsState(ArrowsPressed.Right, false); 
      break; 
     default: 
      return; 
    } 
    e.Handled = true; 
} 

を使用して、 。GetKeyboardStateタイマーのWi周りにこの時間を利用して

Point position; 
private void HandleArrows() 
{ 
    if ((arrowsPressed & ArrowsPressed.Down) != ArrowsPressed.None) 
    { 
     position.Y++; 
    } 
    if ((arrowsPressed & ArrowsPressed.Up) != ArrowsPressed.None) 
    { 
     position.Y--; 
    } 
    if ((arrowsPressed & ArrowsPressed.Left) != ArrowsPressed.None) 
    { 
     position.X--; 
    } 
    if ((arrowsPressed & ArrowsPressed.Right) != ArrowsPressed.None) 
    { 
     position.X++; 
    } 
    // Do whatever is needed using position 
} 
+0

これは良い答えです。 –

+0

機能しません、キーは繰り返しを停止します。タイマーが必要です。 –

+0

@ハンスはい、あなたは絶対に正しいです。 Windowsは、最後に押されたキーのWM_KEYDOWNメッセージを送信します。このキーを離すと動きが止まります。タイマーは確かにこのような状況で役に立ちますが、タイマーを使用する場合は、PinvokeをGetKeyboardStateに使用することになります。 –

2

現在、Key_Down状態にあるすべてのキーのリストを保持する必要があります。

これにより、どのキーが押されたかを追跡し、どの組み合わせが有効であるかを判断できます。

各イベントは、キーダウン/アップイベントごとに1回トリガします。したがって、1つのイベントで2つのキーを検出することはできませんが、イベントの外部にあるコレクションでこの情報を追跡できます。

1

改良版、すべてのキーを追跡し、それらが示す方向にポイントを移動し、あなたの位置のテストを保持するポイント構造押されたキーをチェックする関数を呼び出し、ArrowsPressed列挙を構築し、移動を実行する関数 を呼び出します。他のいくつかのキーを使用したい場合は、virtualKeyToArrowsPressed Dictionaryに入れます。

const int VK_LEFT = 0x25; 
const int VK_UP = 0x26; 
const int VK_RIGHT = 0x27; 
const int VK_DOWN = 0x28; 

[DllImport("user32.dll")] 
[return: MarshalAs(UnmanagedType.Bool)] 
static extern bool GetKeyboardState(byte[] lpKeyState); 

byte[] keys = new byte[256]; 

[Flags] 
enum ArrowsPressed 
{ 
    None = 0x00, 
    Left = 0x01, 
    Right = 0x02, 
    Up = 0x04, 
    Down = 0x08, 
    All = 0x0F 
} 
Dictionary<int, ArrowsPressed> virtualKeyToArrowsPressed = new Dictionary<int, ArrowsPressed> 
{ 
    { VK_LEFT, ArrowsPressed.Left }, 
    { VK_RIGHT, ArrowsPressed.Right }, 
    { VK_UP, ArrowsPressed.Up }, 
    { VK_DOWN, ArrowsPressed.Down }, 
}; 

protected override void OnLoad(EventArgs e) 
{ 
    base.OnLoad(e); 

    timer1.Tick += timer1_Tick; 
    timer1.Interval = 100; 
    timer1.Start(); 
} 

void timer1_Tick(object sender, EventArgs e) 
{ 
    if (GetKeyboardState(keys)) 
    { 
     ArrowsPressed arrowsPressed = ArrowsPressed.None; 
     foreach (KeyValuePair<int, ArrowsPressed> kvp in virtualKeyToArrowsPressed) 
     { 
      if ((keys[kvp.Key] & 0x80) != 0) 
      { 
       arrowsPressed |= kvp.Value; 
      } 
     } 
     if (arrowsPressed != ArrowsPressed.None) 
     { 
      HandleArrows(arrowsPressed); 
     } 
    } 
} 

Point position; 
private void HandleArrows(ArrowsPressed arrowsPressed) 
{ 
    if ((arrowsPressed & ArrowsPressed.Down) != ArrowsPressed.None) 
    { 
     position.Y++; 
    } 
    if ((arrowsPressed & ArrowsPressed.Up) != ArrowsPressed.None) 
    { 
     position.Y--; 
    } 
    if ((arrowsPressed & ArrowsPressed.Left) != ArrowsPressed.None) 
    { 
     position.X--; 
    } 
    if ((arrowsPressed & ArrowsPressed.Right) != ArrowsPressed.None) 
    { 
     position.X++; 
    } 
    // Do whatever is needed using position 
} 
関連する問題