问题描述
我制作了一个程序,每当按下键盘上的一个键时,就会输出一个喀哒声。 当我在PC(使用Ryzen 3900x)和一台笔记本电脑(使用i7 8850h)上尝试该程序时,即使快速键入,它也可以毫无延迟地完美输出声音。
但是在我用于学校的较慢笔记本电脑上,它不能正确输出声音,尤其是在快速键入时。 (声音被延迟,或者在停止之前只起到了很小的作用)
除了PlaySound可能太慢或其他原因之外,我找不到其他问题。它与加载声音文件没有任何关系,因为我正在播放内存中的声音。这也不是按键的识别,因为控制台输出(按下哪个键)几乎是即时的。
这是我的代码:
#ifndef UNICODE
#define UNICODE
#endif // UNICODE
#include <stdio.h>
#include <stdlib.h>
#include <w32api.h>
#define WINVER WindowsXP
#include <windows.h>
#include <winuser.h>
BYTE* byteAudio = NULL;
LRESULT CALLBACK WinProc(HWND hwnd,UINT uMsg,WParaM wParam,LParaM lParam)
{
if(uMsg == WM_INPUT)
{
HRAWINPUT hRawInput = (HRAWINPUT)lParam;
RAWINPUT input = { 0 };
UINT size = sizeof(input);
GetRawInputData(hRawInput,RID_INPUT,&input,&size,sizeof(RAWINPUTHEADER));
if(input.data.keyboard.Flags == 0)
{
//PlaySoundW(TEXT("res/click.wav"),NULL,SND_ASYNC | SND_FILENAME);
PlaySound(byteAudio,SND_MEMORY,SND_ASYNC | SND_MEMORY);
printf("vkey: %x,flag: %d\n",input.data.keyboard.VKey,input.data.keyboard.Flags);
}
}
return DefWindowProc(hwnd,uMsg,wParam,lParam);
}
int APIENTRY WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpComLine,int iShowCmd)
{
const char* CLASS_NAME = "RawInputClass";
FILE* fPtr;
long lFileSize;
//Gets file size
fPtr = fopen("res/click.wav","rb");
if(!fPtr)
{
printf("Error while opening file!");
return -1;
}
fseek(fPtr,SEEK_END);
lFileSize = ftell(fPtr);
rewind(fPtr);
//Reads file into byte-Array
byteAudio = (BYTE*)malloc(lFileSize * sizeof(BYTE));
if(!byteAudio)
{
printf("byteAudio; OUT_OF_MEMORY"); //If that happens,it is probably time for an upgrade
return -1;
}
fread(byteAudio,lFileSize,1,fPtr);
fclose(fPtr);
//Create Message-Only window
WNDCLASS wnd = { 0 };
wnd.hInstance = GetModuleHandle(NULL);
wnd.lpfnWndProc = WinProc;
wnd.lpszClassName = CLASS_NAME;
RegisterClass(&wnd);
HWND hWnd = CreateWindowExW(0,CLASS_NAME,TEXT("THE WINDOW IS INVISIBLE SO WHO CARES!"),HWND_MESSAGE,GetModuleHandle(NULL),NULL);
RAWINPUTDEVICE rid = { 0 };
rid.usUsagePage = 0x01;
rid.usUsage = 0x06; //keyboard
rid.dwFlags = RIDEV_INPUTSINK | RIDEV_NOLEGACY;
rid.hwndTarget = hWnd;
RegisterRawInputDevices(&rid,sizeof(RAWINPUTDEVICE));
MSG msg;
while(GetMessage(&msg,0))
{
TranslateMessage(&msg);
dispatchMessage(&msg);
}
}
解决方法
您正在使用轮询方法,该方法很慢。
while(GetMessage(&msg,NULL,0))
{
/* stuff */
}
了解什么是中断以及这些中断的用途。这些将解决您的问题。