钩键盘重复输入(C#/ XNA) - c#

我在XNA项目中使用了Keyboard钩子(使用XNA的任何人都知道内置键盘类对于“文本框”样式键入的输入没有多大用处。

在引入表格之前,它可以很好地用于XNA项目。如果我尝试在项目中实现任何表单,无论是自定义表单,甚至只是OpenFileDialog,该表单的文本框中的任何按键都会加倍,从而几乎无法键入。

有谁知道我如何才能阻止邮件两次到达表单?也许是在我收到消息后就将其丢弃了?也许有更好的解决方案?也许这只是无法完成的事情。

任何帮助表示赞赏。

编辑:

下面是我正在使用的键盘挂钩代码,所有想寻找XNA键盘挂钩的人都可能很熟悉,因为无论我在哪里寻找它,它都会冒出来。

using System;
using System.Runtime.InteropServices;
using System.Windows.Forms; // This class exposes WinForms-style key events.

namespace FatLib.Controls
{
    class KeyboardHookInput : IDisposable
    {
        private string _buffer = "";
        private bool _backSpace = false;
        private bool _enterKey = false; // I added this to the original code

        public string Buffer
        {
            get { return _buffer; }
        }
        public bool BackSpace
        {
            get
            {
                return _backSpace;
            }
        }
        public bool EnterKey
        {
            get
            {
                return _enterKey;
            }
        }
        public void Reset()
        {
            _buffer = "";
            _backSpace = false;
            _enterKey = false;
        }

        public enum HookId
        {
            // Types of hook that can be installed using the SetWindwsHookEx function.
            WH_CALLWNDPROC = 4,
            WH_CALLWNDPROCRET = 12,
            WH_CBT = 5,
            WH_DEBUG = 9,
            WH_FOREGROUNDIDLE = 11,
            WH_GETMESSAGE = 3,
            WH_HARDWARE = 8,
            WH_JOURNALPLAYBACK = 1,
            WH_JOURNALRECORD = 0,
            WH_KEYBOARD = 2,
            WH_KEYBOARD_LL = 13,
            WH_MAX = 11,
            WH_MAXHOOK = WH_MAX,
            WH_MIN = -1,
            WH_MINHOOK = WH_MIN,
            WH_MOUSE_LL = 14,
            WH_MSGFILTER = -1,
            WH_SHELL = 10,
            WH_SYSMSGFILTER = 6,
        };
        public enum WindowMessage
        {
            // Window message types.
            WM_KEYDOWN = 0x100,
            WM_KEYUP = 0x101,
            WM_CHAR = 0x102,
        };

        // A delegate used to create a hook callback.
        public delegate int GetMsgProc(int nCode, int wParam, ref Message msg);

        /// <summary>
        /// Install an application-defined hook procedure into a hook chain.
        /// </summary>
        /// <param name="idHook">Specifies the type of hook procedure to be installed.</param>
        /// <param name="lpfn">Pointer to the hook procedure.</param>
        /// <param name="hmod">Handle to the DLL containing the hook procedure pointed to by the lpfn parameter.</param>
        /// <param name="dwThreadId">Specifies the identifier of the thread with which the hook procedure is to be associated.</param>
        /// <returns>If the function succeeds, the return value is the handle to the hook procedure. Otherwise returns 0.</returns>
        [DllImport("user32.dll", EntryPoint = "SetWindowsHookExA")]
        public static extern IntPtr SetWindowsHookEx(HookId idHook, GetMsgProc lpfn, IntPtr hmod, int dwThreadId);

        /// <summary>
        /// Removes a hook procedure installed in a hook chain by the SetWindowsHookEx function. 
        /// </summary>
        /// <param name="hHook">Handle to the hook to be removed. This parameter is a hook handle obtained by a previous call to SetWindowsHookEx.</param>
        /// <returns>If the function fails, the return value is zero. To get extended error information, call GetLastError.</returns>
        [DllImport("user32.dll")]
        public static extern int UnhookWindowsHookEx(IntPtr hHook);

        /// <summary>
        /// Passes the hook information to the next hook procedure in the current hook chain.
        /// </summary>
        /// <param name="hHook">Ignored.</param>
        /// <param name="ncode">Specifies the hook code passed to the current hook procedure.</param>
        /// <param name="wParam">Specifies the wParam value passed to the current hook procedure.</param>
        /// <param name="lParam">Specifies the lParam value passed to the current hook procedure.</param>
        /// <returns>This value is returned by the next hook procedure in the chain.</returns>
        [DllImport("user32.dll")]
        public static extern int CallNextHookEx(int hHook, int ncode, int wParam, ref Message lParam);

        /// <summary>
        /// Translates virtual-key messages into character messages.
        /// </summary>
        /// <param name="lpMsg">Pointer to an Message structure that contains message information retrieved from the calling thread's message queue.</param>
        /// <returns>If the message is translated (that is, a character message is posted to the thread's message queue), the return value is true.</returns>
        [DllImport("user32.dll")]
        public static extern bool TranslateMessage(ref Message lpMsg);


        /// <summary>
        /// Retrieves the thread identifier of the calling thread.
        /// </summary>
        /// <returns>The thread identifier of the calling thread.</returns>
        [DllImport("kernel32.dll")]
        public static extern int GetCurrentThreadId();

        // Handle for the created hook.
        private readonly IntPtr HookHandle;

        private readonly GetMsgProc ProcessMessagesCallback;

        public KeyboardHookInput()
        {
            // Create the delegate callback:
            this.ProcessMessagesCallback = new GetMsgProc(ProcessMessages);
            // Create the keyboard hook:
            this.HookHandle = SetWindowsHookEx(HookId.WH_KEYBOARD, this.ProcessMessagesCallback, IntPtr.Zero, GetCurrentThreadId());
        }

        public void Dispose()
        {
            // Remove the hook.
            if (HookHandle != IntPtr.Zero) UnhookWindowsHookEx(HookHandle);
        }

        // comments found in this region are all from the original author: Darg.
        private int ProcessMessages(int nCode, int wParam, ref Message msg)
        {
            // Check if we must process this message (and whether it has been retrieved via GetMessage):
            if (nCode == 0 && wParam == 1)
            {
                // We need character input, so use TranslateMessage to generate WM_CHAR messages.
                TranslateMessage(ref msg);

                // If it's one of the keyboard-related messages, raise an event for it:
                switch ((WindowMessage)msg.Msg)
                {
                    case WindowMessage.WM_CHAR:
                        this.OnKeyPress(new KeyPressEventArgs((char)msg.WParam));
                        break;
                    case WindowMessage.WM_KEYDOWN:
                        this.OnKeyDown(new KeyEventArgs((Keys)msg.WParam));
                        break;
                    case WindowMessage.WM_KEYUP:
                        this.OnKeyUp(new KeyEventArgs((Keys)msg.WParam));
                        break;
                }
            }
            // Call next hook in chain:
            return CallNextHookEx(0, nCode, wParam, ref msg);
        }

        public event KeyEventHandler KeyUp;
        protected virtual void OnKeyUp(KeyEventArgs e)
        {
            if (KeyUp != null) KeyUp(this, e);
        }

        public event KeyEventHandler KeyDown;
        protected virtual void OnKeyDown(KeyEventArgs e)
        {
            if (KeyDown != null) KeyDown(this, e);
        }

        public event KeyPressEventHandler KeyPress;
        protected virtual void OnKeyPress(KeyPressEventArgs e)
        {
            if (KeyPress != null) KeyPress(this, e);
            if (e.KeyChar.GetHashCode().ToString() == "524296")
            {
                _backSpace = true;
            }
            else if (e.KeyChar == (char)Keys.Enter)
            {
                _enterKey = true;
            }
            else
            {
                _buffer += e.KeyChar;
            }
        }
    }
}

参考方案

Windows Hook是获得所有按键的一种非常讨厌的方式,并且绝对是不得已的手段。

尝试将Message Filter安装到应用程序中,该应用程序可以监视发送到您的应用程序的所有键盘消息(WM_KEYPRESS,KEYUP,KEYDOWN等),而不会干扰其他应用程序。过滤器还允许您根据需要停止到达应用程序中任何形式的任何消息。

Winapp(C#)调用Java应用程序->设置进度栏 - c#

我有一个C#winapp,它与Java应用程序通信以通过tcp检索数据。现在,我想添加一个进度条,以等待并显示数据下载繁忙。因为这时winapp冻结,直到它拥有来自Java的所有数据为止。现在我想知道如何编程。因为我认为Java应该不时返回某些东西来在c#中设置进度条。我想我需要使用线程来做,但是我不确定如何去做。如果有人有其他想法或例子,那就太好了。 参考…

如何使用BeautifulSoup在<tr>中捕获特定的<td> - python

尝试从nyc Wiki页面中的高中列表中获取所有高中名称。我已经写了足够多的脚本,可以让我获取包含在高中,学业和入学条件列表的表的<tr>标记中的所有信息-但是我如何才能缩小到我认为的范围内在td[0]内休息(会弹出KeyError)-只是学校的名称?到目前为止我写的代码:from bs4 import BeautifulSoup from ur…

合并List <T>和List <Optional <T >> - java

鉴于: List<Integer> integers = new ArrayList<>(Arrays.asList( 10, 12 )); List<Optional<Integer>> optionalIntegers = Arrays.asList( Optional.of(5), Optional.em…

无法从ArrayList <String>转换为List <Comparable> - java

当我写下面的代码时,编译器说 无法从ArrayList<String>转换为List<Comparable>private List<Comparable> get(){ return new ArrayList<String>(); } 但是当我用通配符编写返回类型时,代码会编译。private List&l…

OpenShift构建错误:无法在多模块Maven Spring启动项目的父模块中导入子模块类 - java

我有一个使用spring的多模块Maven项目。通用模块类用作业务模块项目中的直接导入。我可以在本地PC上编译并成功运行它们。当我在OpenShift中部署相同的模块时,出现错误,无法在业务模块中导入通用模块类。项目结构可以总结如下:项目根 通用模块 src pom.xml 业务模块 src pom.xml pom.xml父POM:<?xml vers…