June 23, 2011

Key Events in XNA 4.0

One of the top requested features for XNA since release was the ability to intercept key press events instead of just the key up/down events so that people could do text input easily.

Still can't do it in XNA 4.0, but here's a way of working around it by adding a message filter. Please be aware that they may break this in the future if they don't use Windows Forms for their form in XNA 5.

First, the keyboard filter class...


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;

namespace RomSteady.Xna.GameEngine.Input
{
public class KeyboardMessageFilter : IMessageFilter
{
[DllImport("user32.dll")]
static extern bool TranslateMessage(ref Message lpMsg);

const int WM_CHAR = 0x0102;
const int WM_KEYDOWN = 0x0100;

public bool PreFilterMessage(ref Message m)
{
if (m.Msg == WM_KEYDOWN)
{
TranslateMessage(ref m);
}
else if (m.Msg == WM_CHAR)
{
if (KeyPressed != null)
KeyPressed.Invoke(this,
new KeyboardMessageEventArgs()
{
Character = Convert.ToChar((int)m.WParam)
});
}
return false;
}

public event EventHandler KeyPressed;
}

public class KeyboardMessageEventArgs : EventArgs
{
public char Character;
}
}


...and now to wire it up so you can get those KeyPressed events. In your Initialize() function...


...
var keyboardFilter = new KeyboardMessageFilter();
keyboardFilter.KeyPressed +=
new EventHandler(keyboardFilter_KeyPressed);
System.Windows.Forms.Application.AddMessageFilter(keyboardFilter);
...


This code isn't flawless, but is working well enough for my purposes.

No comments: