问题
http://www.microsoft.com/windowsxp/using/accessibility/characterrepeatrate.mspx - There's an option in Windows for setting repeat delay. It means the delay between first keystroke and the other ones if one keeps pressing the key. I'm creating a sort of game and I need to get rid of this "feature".
So far I've managed to find this method:
[DllImport("user32.dll")]
static extern ushort GetAsyncKeyState(int vKey);
public static bool IsKeyPushedDown(Keys keyData)
{
return 0 != (GetAsyncKeyState((int)keyData) & 0x8000);
}
But the method IsKeyPushedDown finds out if the key is pressed AT THE MOMENT of calling the function - so I need a loop to test if key is down. Problem is that still it doesn't catches all keystrokes - I have too slow loop I guess.
Second choice is overriding of ProcessCmdKey:
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
// processing keys
if (keyData == Keys.Left || keyData == Keys.Right || keyData == Keys.Up || keyData == Keys.Down)
{
return true;
}
else
{
return base.ProcessCmdKey(ref msg, keyData);
}
}
this works really good but it's affected with repeat delay and therefore movement of my monster in my game is like:
Is there a solution for my problem? Thanks
EDIT: I solved the problem by combining both procedures. But it's very ugly solution. I still hope there's better solution.
回答1:
You should be handling KeyDown
and KeyUp
rather than ProcessCmdKey
if you want greater control over what happens between the time a key is pressed and released.
The absolute easiest thing to do in your scenario would be to have a timer on your form that moves the monster. Enable the timer (and set some sort of variable or deltaX and deltaY that indicates how to move the monster) when KeyDown
is fired, then stop the timer when KeyUp
is fired.
Edit
As an example (very barebones)
public class MyForm : Form
{
private int deltaX;
private int deltaY;
private const int movementAmount = 10;
private Timer movementTimer = new Timer();
public MyForm()
{
movementTimer.Interval = 100; // make this whatever interval you'd like there to be in between movements
movementTimer.Tick += new EventHandler(movementTimer_Tick);
}
void movementTimer_Tick(object sender, EventArgs e)
{
myMonster.Location = new Point(myMonster.X + deltaX, myMonster.Y + deltaY);
}
protected override void OnKeyDown(KeyEventArgs e)
{
base.OnKeyDown(e);
switch (e.KeyCode)
{
case Keys.Left:
{
deltaX -=movementAmount;
} break;
case Keys.Right:
{
deltaX += movementAmount;
} break;
case Keys.Up:
{
deltaY -= movementAmount;
} break;
case Keys.Down:
{
deltaY += movementAmount;
} break;
}
UpdateTimer();
}
protected override void OnKeyUp(KeyEventArgs e)
{
base.OnKeyUp(e);
switch (e.KeyCode)
{
case Keys.Left:
{
deltaX += movementAmount;
} break;
case Keys.Right:
{
deltaX -= movementAmount;
} break;
case Keys.Up:
{
deltaY += movementAmount;
} break;
case Keys.Down:
{
deltaY -= movementAmount;
} break;
}
UpdateTimer();
}
private void UpdateTimer()
{
movementTimer.Enabled = deltaX != 0 || deltaY != 0;
}
}
来源:https://stackoverflow.com/questions/1172621/how-can-i-get-rid-of-character-repeat-delay-in-c