//关于raw input 请查看msdn https://msdn.microsoft.com/en-us/library/windows/desktop/ms645536%28v=vs.85%29.aspx
//效率 比 键盘钩子高太多 ,但是BCB 中无法识别 RAWINPUTDEVICE 结构 和RAW相关的函数
//rawinput4.cpp : 定义应用程序的入口点。//#include"stdafx.h"#include"rawinput4.h"#include#include#include
using namespacestd;#define MAX_LOADSTRING 100
//全局变量:
HINSTANCE hInst; //当前实例
TCHAR szTitle[MAX_LOADSTRING]; //标题栏文本
TCHAR szWindowClass[MAX_LOADSTRING]; //主窗口类名
setkeys;//避免按住不放不停的响应keydown
boolIsInKeys(DWORD key)
{set::iterator itor =find(keys.begin(),keys.end(),key);bool result = false;if (itor ==keys.end())
{
keys.insert(key);
result= false;
}else{
result= true;
}returnresult;
}//松开的时候,将key从set中移除
voiderasekey(DWORD key)
{
keys.erase(key);
}//此代码模块中包含的函数的前向声明:
ATOM MyRegisterClass(HINSTANCE hInstance);
BOOL InitInstance(HINSTANCE,int);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM);voidRegKeyboardRawInput(HWND hwnd)
{
RAWINPUTDEVICE Rid[1];
Rid[0].usUsagePage = 0x01;
Rid[0].usUsage = 0x06;
Rid[0].dwFlags = RIDEV_INPUTSINK;//RIDEV_NOLEGACY;//adds HID keyboard and also ignores legacy keyboard messages
Rid[0].hwndTarget =hwnd;if (RegisterRawInputDevices(Rid, 1, sizeof(Rid[0])) ==FALSE) {
MessageBox(NULL,L"注册raw input 失败!",L"注册 raw input",MB_OK+MB_ICONINFORMATION);
}
}intAPIENTRY _tWinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,intnCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
MSG msg;
HACCEL hAccelTable;//初始化全局字符串
LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
LoadString(hInstance, IDC_RAWINPUT4, szWindowClass, MAX_LOADSTRING);
MyRegisterClass(hInstance);//执行应用程序初始化:
if (!InitInstance (hInstance, nCmdShow))
{returnFALSE;
}
hAccelTable=LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_RAWINPUT4));//主消息循环:
while (GetMessage(&msg, NULL, 0, 0))
{if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}return (int) msg.wParam;
}//
//函数: MyRegisterClass()//
//目的: 注册窗口类。//
//注释://
//仅当希望//此代码与添加到 Windows 95 中的“RegisterClassEx”//函数之前的 Win32 系统兼容时,才需要此函数及其用法。调用此函数十分重要,//这样应用程序就可以获得关联的//“格式正确的”小图标。//ATOM MyRegisterClass(HINSTANCE hInstance)
{
WNDCLASSEX wcex;
wcex.cbSize= sizeof(WNDCLASSEX);
wcex.style= CS_HREDRAW |CS_VREDRAW;
wcex.lpfnWndProc=WndProc;
wcex.cbClsExtra= 0;
wcex.cbWndExtra= 0;
wcex.hInstance=hInstance;
wcex.hIcon=LoadIcon(hInstance, MAKEINTRESOURCE(IDI_RAWINPUT4));
wcex.hCursor=LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground= (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName=MAKEINTRESOURCE(IDC_RAWINPUT4);
wcex.lpszClassName=szWindowClass;
wcex.hIconSm=LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));return RegisterClassEx(&wcex);
}//
//函数: InitInstance(HINSTANCE, int)//
//目的: 保存实例句柄并创建主窗口//
//注释://
//在此函数中,我们在全局变量中保存实例句柄并//创建和显示主程序窗口。//BOOL InitInstance(HINSTANCE hInstance, intnCmdShow)
{
HWND hWnd;
hInst= hInstance; //将实例句柄存储在全局变量中
hWnd=CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);if (!hWnd)
{returnFALSE;
}
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
RegKeyboardRawInput(hWnd);returnTRUE;
}//
//函数: WndProc(HWND, UINT, WPARAM, LPARAM)//
//目的: 处理主窗口的消息。//
//WM_COMMAND - 处理应用程序菜单//WM_PAINT - 绘制主窗口//WM_DESTROY - 发送退出消息并返回//
//LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{intwmId, wmEvent;
PAINTSTRUCT ps;
HDC hdc;switch(message)
{caseWM_COMMAND:
wmId=LOWORD(wParam);
wmEvent=HIWORD(wParam);//分析菜单选择:
switch(wmId)
{caseIDM_ABOUT:
DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);break;caseIDM_EXIT:
DestroyWindow(hWnd);break;default:returnDefWindowProc(hWnd, message, wParam, lParam);
}break;caseWM_PAINT:
hdc= BeginPaint(hWnd, &ps);//TODO: 在此添加任意绘图代码...
EndPaint(hWnd, &ps);break;caseWM_DESTROY:
PostQuitMessage(0);break;caseWM_INPUT:
{
UINT dwSize;
GetRawInputData((HRAWINPUT)lParam, RID_INPUT, NULL,&dwSize,sizeof(RAWINPUTHEADER));
LPBYTE lpb= newBYTE[dwSize];if (lpb ==NULL)
{return 0;
}if (GetRawInputData((HRAWINPUT)lParam, RID_INPUT, lpb, &dwSize,sizeof(RAWINPUTHEADER)) !=dwSize )
OutputDebugString (TEXT("GetRawInputData doesn't return correct size !\n"));
RAWINPUT* raw = (RAWINPUT*)lpb;if (raw->header.dwType ==RIM_TYPEKEYBOARD)
{if ( raw->data.keyboard.Message ==WM_KEYDOWN)
{if (!IsInKeys(raw->data.keyboard.VKey))
{char keytext[10] = {0};
BYTE state[256] = {0};//通过虚拟键盘码得到名字
ToAscii(raw->data.keyboard.VKey,raw->data.keyboard.MakeCode,state,(LPWORD)keytext ,0);char buf[10] = {0};string s = "键盘按下 虚键码:"+ string(keytext);
MessageBoxA(NULL,s.c_str(),"键盘",MB_OK);
}
}if( raw->data.keyboard.Message ==WM_KEYUP)
{
erasekey(raw->data.keyboard.VKey);
}
}delete[] lpb;return 0;
}default:returnDefWindowProc(hWnd, message, wParam, lParam);
}return 0;
}//“关于”框的消息处理程序。
INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
UNREFERENCED_PARAMETER(lParam);switch(message)
{caseWM_INITDIALOG:return(INT_PTR)TRUE;caseWM_COMMAND:if (LOWORD(wParam) == IDOK || LOWORD(wParam) ==IDCANCEL)
{
EndDialog(hDlg, LOWORD(wParam));return(INT_PTR)TRUE;
}break;
}return(INT_PTR)FALSE;
}