keyboard fix for desktop apps

Monkey Targets Forums/XNA/keyboard fix for desktop apps

skid(Posted 2013) [#1]
We need forms and interop (call dll) so need to either edit our own and/or template version of Program.cs with these replacement lines in the header:


#if WINDOWS
using System.Windows;
using System.Windows.Forms;
using System.Runtime.InteropServices;
#endif



In target/modules/xna/native/xnagame.cs replace last blocks of public virtual void Run() implementation with this:


#if WINDOWS
		_form = System.Windows.Forms.Form.FromHandle(_app.Window.Handle) as System.Windows.Forms.Form;
		if (MonkeyConfig.XNA_WINDOW_FULLSCREEN != "1")
		{
			_form.FormClosing+=FormClosing;
		}
		MessageFilter keyboardFilter = new MessageFilter();
		System.Windows.Forms.Application.AddMessageFilter(keyboardFilter); 
		
#endif		



and add this code where we intercept the windows message pump for our form and feed monkey non xna based keyboard events:


	public class MessageFilter : IMessageFilter{
		[DllImport("user32.dll")]
		static extern bool TranslateMessage(ref Message lpMsg); 
				
		const int WM_CHAR = 0x0102;
		const int WM_KEYDOWN = 0x0100;
		const int WM_KEYUP = 0x0101;

		public bool PreFilterMessage(ref Message m){
			switch(m.Msg){
				case WM_CHAR:
					int wp = m.WParam.ToInt32();
					if (wp > 31)
					{
						Game().KeyEvent(3, wp);
					}
					return true;
				case WM_KEYDOWN:
					if(TranslateMessage(ref m)){
						Game().KeyEvent(1,m.WParam.ToInt32());
					}
					return true;
				case WM_KEYUP:
					if (TranslateMessage(ref m)){
						Game().KeyEvent(2, m.WParam.ToInt32());
					}
					return true;
				default:
					break;
			}
			return false;
		}
	}



and replace PollKeyboard and PollMouse with these




Erik(Posted 2013) [#2]
Thanks! Perfect timing, I was thinking about writing this myself, but now I don't have to! :)


Erik(Posted 2013) [#3]
Make KeyToChar public and change WM_KEYDOWN to this to handle arrow keys and the other special char keys:

  case WM_KEYDOWN:
    if(TranslateMessage(ref m)){
      Game().KeyEvent(1,m.WParam.ToInt32());
      var keychar = BBXnaGame._xnaGame.KeyToChar(m.WParam.ToInt32());
      if (keychar!=0)
        Game().KeyEvent(3, keychar);
    }
    return true;


.


skid(Posted 2013) [#4]
Thanks Erik.

Mouse code should also I think, be moved to the message pump.

I haven't been able to work out how to post safely to the GameThread in monkey yet.


skid(Posted 2013) [#5]
and a nicer EndApp implementation:

	public static int g_EndApp(){
		g__game.Quit();		
		return 0;
	}



Erik(Posted 2013) [#6]
Well, that didn't work, shift and alt stopped working, here is another version that only overrides the special char keys:

  case WM_KEYDOWN:
    if(TranslateMessage(ref m)){
      Game().KeyEvent(1,m.WParam.ToInt32());
      var keychar = BBXnaGame._xnaGame.KeyToChar(m.WParam.ToInt32());
      if (keychar==8 ||
          keychar==9 ||
          keychar==13 ||
          keychar==27 ||
          keychar==127 ||
          keychar==65569 ||
          keychar==65570 ||
          keychar==65571 ||
          keychar==65572 ||
          keychar==65573 ||
          keychar==65574 ||
          keychar==65575 ||
          keychar==65576 ||
          keychar==65581)
              Game().KeyEvent(3, keychar);
    }
  return true;