XNA - Keyboard text input

后端 未结 5 429
爱一瞬间的悲伤
爱一瞬间的悲伤 2020-12-29 08:28

Okay, so basically I want to be able to retrieve keyboard text. Like entering text into a text field or something. I\'m only writing my game for windows. I\'ve disregarded u

相关标签:
5条回答
  • 2020-12-29 08:53

    Maybe I'm not understanding the question, but why can't you use the XNA Keyboard and KeyboardState classes?

    0 讨论(0)
  • 2020-12-29 08:58

    This page is on top of google result about WM_CHAR interception in xna, so i leave here some note. Maybe this will be useful for other (if they will be able to understand my English =)) ).

    I try code with windowshook from Sekhat, but seems there should be WH_GETMESSAGE passed to SetWindowsHookEx instead Win32.HookType.WH_CALLWNDPROC (only with WH_GETMESSAGE code lparaw will point to Win32.Message ).

    Also there is sometime duplicated messages (with wparam 0). (look here - http://msdn.microsoft.com/en-us/library/ms644981%28v=VS.85%29.aspx something about PM_NOREMOVE/PM_REMOVE in WPARAM )

    When i add something like this

        if (nCode >= 0 && wParam == 1)
        {
            Win32.TranslateMessage(ref lParam); 
            WndProc(ref lParam);
        }
    

    wm_keypress wm_char duplication stopped (i supose 1 is PM_NOREMOVE or PM_REMOVE).

    P.S. nuclex variant now show 404 page, but can be viewed with webarchive. nuclex variant works, but it cause broken mouseWheel processing from native XNA MouseState (on XNA 3.1) =(

    0 讨论(0)
  • 2020-12-29 09:09

    Here's a simple way, IMO, to have the space, back, A-Z and then the special chars !,@,#,$,%,^,&,*,(,). (Note, you need to import System.Linq) Here are the fields:

    Keys[] keys;
    bool[] IskeyUp;
    string[] SC = { ")" , "!", "@", "#", "$", "%", "^", "&", "*", "("};//special characters
    

    Constructor:

    keys = new Keys[38];
    Keys[] tempkeys;
    tempkeys = Enum.GetValues(typeof(Keys)).Cast<Keys>().ToArray<Keys>();
    int j = 0;
    for (int i = 0; i < tempkeys.Length; i++)
    {
        if (i == 1 || i == 11 || (i > 26 && i < 63))//get the keys listed above as well as A-Z
        {
            keys[j] = tempkeys[i];//fill our key array
            j++;
        }
    }
    IskeyUp = new bool[keys.Length]; //boolean for each key to make the user have to release the key before adding to the string
    for (int i = 0; i < keys.Length; i++)
        IskeyUp[i] = true;
    

    And Finally, the update method:

    string result = "";
    
    public override void Update(GameTime gameTime)
    {
        KeyboardState state = Keyboard.GetState();
        int i = 0;
        foreach (Keys key in keys)
        {
            if (state.IsKeyDown(key))
            {
                if (IskeyUp[i])
                {
                    if (key == Keys.Back && result != "") result = result.Remove(result.Length - 1);
                    if (key == Keys.Space) result += " ";
                    if (i > 1 && i < 12)
                    {
                        if (state.IsKeyDown(Keys.RightShift) || state.IsKeyDown(Keys.LeftShift))
                            result += SC[i - 2];//if shift is down, and a number is pressed, using the special key
                        else result += key.ToString()[1];
                    }
                    if (i > 11 && i < 38)
                    {
                        if (state.IsKeyDown(Keys.RightShift) || state.IsKeyDown(Keys.LeftShift))
                           result += key.ToString();
                        else result += key.ToString().ToLower(); //return the lowercase char is shift is up.
                    }
                }
                IskeyUp[i] = false; //make sure we know the key is pressed
            }
            else if (state.IsKeyUp(key)) IskeyUp[i] = true;
            i++;
        }
        base.Update(gameTime, otherScreenHasFocus, coveredByOtherScreen);
    }
    

    Hopefull this well help. I personally thought it was easier to use than the hooks, and this also can easily be modified for special results (such as shuffling the keys).

    0 讨论(0)
  • 2020-12-29 09:10

    I used the solution from this gamedev.net post and it works great :)

    0 讨论(0)
  • 2020-12-29 09:11

    For adding a windows hook in XNA

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Runtime.InteropServices;
    using System.Diagnostics;
    using System.Reflection;
    
    /* Author: Sekhat
     * 
     * License: Public Domain.
     * 
     * Usage:
     *
     * Inherit from this class, and override the WndProc function in your derived class, 
     * in which you handle your windows messages.
     * 
     * To start recieving the message, create an instance of your derived class, passing in the
     * window handle of the window you want to listen for messages for.
     * 
     * in XNA: this would be the Game.Window.Handle property
     * in Winforms Form.Handle property
     */
    
    namespace WindowsHookExample
    {
        public abstract class WindowsHook : IDisposable
        {
            IntPtr hHook;
            IntPtr hWnd;
            // Stored here to stop it from getting garbage collected
            Win32.WndProcDelegate wndProcDelegate;
    
            public WindowsHook(IntPtr hWnd)
            {
                this.hWnd = hWnd;
    
                wndProcDelegate = WndProcHook;
    
                CreateHook();
            }
    
            ~WindowsHook()
            {
                Dispose(false);
            }
    
            private void CreateHook()
            {
    
                uint threadId = Win32.GetWindowThreadProcessId(hWnd, IntPtr.Zero);
    
                hHook = Win32.SetWindowsHookEx(Win32.HookType.WH_CALLWNDPROC, wndProcDelegate, IntPtr.Zero, threadId);
    
            }
    
            private int WndProcHook(int nCode, IntPtr wParam, ref Win32.Message lParam)
            {
                if (nCode >= 0)
                {
                    Win32.TranslateMessage(ref lParam); // You may want to remove this line, if you find your not quite getting the right messages through. This is here so that WM_CHAR is correctly called when a key is pressed.
                    WndProc(ref lParam);
                }
    
                return Win32.CallNextHookEx(hHook, nCode, wParam, ref lParam);
            }
    
            protected abstract void WndProc(ref Win32.Message message);
    
            #region Interop Stuff
            // I say thankya to P/Invoke.net.
            // Contains all the Win32 functions I need to deal with
            protected static class Win32
            {
                public enum HookType : int
                {
                    WH_JOURNALRECORD = 0,
                    WH_JOURNALPLAYBACK = 1,
                    WH_KEYBOARD = 2,
                    WH_GETMESSAGE = 3,
                    WH_CALLWNDPROC = 4,
                    WH_CBT = 5,
                    WH_SYSMSGFILTER = 6,
                    WH_MOUSE = 7,
                    WH_HARDWARE = 8,
                    WH_DEBUG = 9,
                    WH_SHELL = 10,
                    WH_FOREGROUNDIDLE = 11,
                    WH_CALLWNDPROCRET = 12,
                    WH_KEYBOARD_LL = 13,
                    WH_MOUSE_LL = 14
                }
    
                public struct Message
                {
                    public IntPtr lparam;
                    public IntPtr wparam;
                    public uint msg;
                    public IntPtr hWnd;
                }
    
                /// <summary>
                ///  Defines the windows proc delegate to pass into the windows hook
                /// </summary>                  
                public delegate int WndProcDelegate(int nCode, IntPtr wParam, ref Message m);
    
                [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
                public static extern IntPtr SetWindowsHookEx(HookType hook, WndProcDelegate callback,
                    IntPtr hMod, uint dwThreadId);
    
                [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
                public static extern bool UnhookWindowsHookEx(IntPtr hhk);
    
                [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
                public static extern int CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, ref Message m);
    
                [DllImport("coredll.dll", SetLastError = true)]
                public static extern IntPtr GetModuleHandle(string module);
    
                [DllImport("user32.dll", EntryPoint = "TranslateMessage")]
                public extern static bool TranslateMessage(ref Message m);
    
                [DllImport("user32.dll")]
                public extern static uint GetWindowThreadProcessId(IntPtr window, IntPtr module);
            }
            #endregion
    
            #region IDisposable Members
    
            public void Dispose()
            {
                Dispose(true);
            }
    
            private void Dispose(bool disposing)
            {
                if (disposing)
                {
                    // Free managed resources here
                }
                // Free unmanaged resources here
                if (hHook != IntPtr.Zero)
                {
                    Win32.UnhookWindowsHookEx(hHook);
                }
            }
    
            #endregion
        }
    }
    
    0 讨论(0)
提交回复
热议问题