1

I am making a program and I want it to be able to read key presses. It does that just fine but I am running into some trouble when I am trying to get the name of the key that was pressed. The code just stops in the middle of the program and for what part is ran it does not give the expected output. Here is my code.

#include <iostream>
#include <Windows.h>

#pragma comment(lib, "User32.lib")

using std::cout;
using std::endl;
using std::wcout;

void test(short vk)
{
    WCHAR key[16];
    GetKeyNameTextW(MapVirtualKeyW(vk, MAPVK_VK_TO_CHAR), key, _countof(key));
    wcout << "Key: " << key << endl;
}

int main()
{
    cout << "Running...." << endl;

    test(0x44); // Key: D
    test(0x45); // Key: E
    test(0x46); // Key: F

    return 0;
}

The output this gives me is

Running....
Key:

and the output I am expecting is

Running....
Key: D
Key: E
Key: F

or at least something very close to that. It should display that those three hexadecimal numbers represent D, E, and F.

The test function is one I made to test turning the virtual key codes into the keys they represent but have so far been unsuccessful. Any help is appreciated!

tadman
  • 208,517
  • 23
  • 234
  • 262
  • 1
    Code looks OK, time to fire up the debugger... – Paul Sanders Aug 25 '20 at 01:46
  • I am new to C++ and I am unfamiliar with how to run the debugger. The way I run my programs is I compile it using cl (Microsoft's compiler) then I run the executable and I do this all from the command line. How do I do the debugger? – Salty Sodiums Aug 25 '20 at 01:48
  • 1
    https://learn.microsoft.com/en-us/visualstudio/debugger/quickstart-debug-with-cplusplus?view=vs-2019 – Thomas Sablik Aug 25 '20 at 01:54

1 Answers1

1

Read the documentation. MapVirtualKeyW(vk, MAPVK_VK_TO_CHAR) is not valid input for GetKeyNameTextW(), as you are mapping a virtual key code to a character, but GetKeyNameTextW() expects a hardware scan code instead (amongst other flags), such as from the LPARAM of a WM_KEY(DOWN|UP) message.

You are also not ensuring that your key[] buffer is null-terminated if GetKeyNameTextW() fails, so you risk passing garbage to std::wcout.

In this case, virtual key codes 0x44..0x46 can be output as-is once converted by MapVirtualKeyW(), there is no need to use GetKeyNameTextW() for them, eg:

void test(short vk)
{
    UINT ch = MapVirtualKeyW(vk, MAPVK_VK_TO_CHAR);
    if (ch != 0) {
        wcout << L"Key: " << (wchar_t)ch << endl;
    }
    else {
        wcout << L"No Key translated" << endl;
    }
}
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • Does the L mean that it is an L-value? Also what is the difference between and L-value and an R-value? Also what if the key is caps lock or shift or something similar? – Salty Sodiums Aug 25 '20 at 02:30
  • 1
    "*Does the L mean that it is an L-value?*" No, it means the string literal uses wide characters (`wchar_t`) instead of narrow characters (`char`). You can't pass a `char*` string to `std::wcout`, you will just get a memory address printed out. "*Also what is the difference between and L-value and an R-value?*" - that is a whole subject of its own, so I suggest you get a [good C++ book](https://stackoverflow.com/questions/388242/). "*Also what if the key is caps lock or shift or something similar?*" - then `MAPVK_VK_TO_CHAR` will fail and `MapVirtualKeyW()` will return 0. – Remy Lebeau Aug 25 '20 at 02:38