在控制台应用程序中使用GetOpenFile和GetKeyState

时间:2013-12-10 23:57:33

标签: winapi console-application

在控制台应用中使用GetKeyState(或GetAsyncKeyState)时,我遇到了奇怪的行为。该应用程序的一个方面是要求用户使用GetFileOpen打开文件。在程序结束时,GetKeyState监视空格键的状态。每当按下空格键时,GetKeyState(或GetAsyncKeyState)函数都不会设置高位。如果我不调用GetOpenFile然后监视GetKeyState,则所有工作都按预期工作。

以下是两种基本情景。

情景1:

#include <windows.h>
int main(int argc, char *argv[])
{
    char filename[ 512 ] = {0};
    OPENFILENAME ofn = {0};
    int filenameSize = 512;
    char title[1000] = {0};

    strcpy(title, "Open File");

    ZeroMemory(&ofn, sizeof(OPENFILENAME));

    ofn.lStructSize = sizeof(OPENFILENAME);
    ofn.hwndOwner = null;
    ofn.lpstrFile = filename;
    ofn.nMaxFile = filenameSize;
    ofn.lpstrFilter = "All files (*.*)\0*.*\0\0";
    ofn.nFilterIndex = 1;
    ofn.lpstrFileTitle = NULL;
    ofn.nMaxFileTitle = 0;
    ofn.lpstrInitialDir = NULL;
    ofn.lpfnHook = NULL;
    ofn.lpstrTitle = title;
    ofn.Flags = OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;

    GetOpenFileName(&ofn);  // filename obtained

    WaitForSpaceBar(); // return value's upper bit is never set for 
                       // GetKeyState(VK_SPACE);
    return 0;
}

情景2:

int main(int argc, char *argv[])
{
    WaitForSpaceBar(); // returns immediately after spacebar is pressed
    return 0;
}

WaitForSpaceBar代码

void WaitForSpaceBar()
{
#define KEY_PRESSED_FLAG 1
    SHORT spacePressed = GetKeyState(VK_SPACE);

    printf("\nPress spacebar to continue...\n");
    while (!(spacePressed & KEY_PRESSED_FLAG))
    {
        Sleep(1);
        spacePressed = GetKeyState(VK_SPACE);

        // for debugging purposes only
        printf("spacePressed = 0x%04x\n", spacePressed);     
    }
}

第一种情况无限期地输出“spacePressed = 0x0000”,无论我按空格键多少次。

第二个场景输出“spacePressed = 0x0000”,直到实际按下空格键。按下后,输出为“spacePressed = 0xffffff81”,程序终止。

有关正在发生的事情的任何想法?

2 个答案:

答案 0 :(得分:2)

如果你没有抽取消息,GetKeyState函数就没用了。

来自documentation

  

说明

     

此函数返回的键状态随线程读取而变化   来自其消息队列的关键消息。状态不反映   与硬件相关的中断级状态。使用   GetAsyncKeyState函数用于检索该信息。

WaitForSpaceBar函数使用以下代码(请注意KEY_PRESSED_FLAG的新值):

void WaitForSpaceBar()
{
    SHORT spacePressed = GetAsyncKeyState(VK_SPACE);
#define KEY_PRESSED_FLAG 0x8000
    printf("\nPress spacebar to continue...\n");
    while (!(spacePressed & KEY_PRESSED_FLAG))
    {
        Sleep(1);
        spacePressed = GetAsyncKeyState(VK_SPACE);

        // for debugging purposes only
        printf("spacePressed = 0x%04x\n", spacePressed);     
    }
}

答案 1 :(得分:1)

MSDN documentation开始,看起来GetKeyState只在你的线程正在为消息发送消息并在响应键盘消息时调用它时才有意义。

  

当此线程从其消息队列中读取关键消息时,此函数返回的键状态会发生变化。

我怀疑GetOpenFile会旋转自己的线程,并且该线程会以某种方式成为您的进程的主要UI线程(因为它是唯一一个进行GUI工作的人)。

如果您正在使用Windows API调用,那么您也可以使用某些特定于控制台的内容,例如ReadConsole

更新:我将问题代码粘贴到VS 2010中,无法重现问题。无论是否调用GetOpenFileName,GetKeyState函数都按预期工作。