Skip to content

Instantly share code, notes, and snippets.

@WestonThayer
Created August 9, 2019 01:01
Show Gist options
  • Star 7 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save WestonThayer/9b7a0e04b045be1656ce9f01de141cd2 to your computer and use it in GitHub Desktop.
Save WestonThayer/9b7a0e04b045be1656ce9f01de141cd2 to your computer and use it in GitHub Desktop.
App to get Windows scancodes

How to compile

On a Windows machine, you'll first need Visual Studio (the free version is fine). Once that's complete:

  1. Open a command prompt
  2. Find vcvarsall.bat in your VS installation path, then call it with x64 as it's argument. It will look something like: call "C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\vcvarsall.bat" x64
  3. Run cl main.c -nologo -Zi -link user32.lib

That should compile and generate main.exe.

All credit goes to mrmixer), I just added a few more logs to see the scancode.

/*
Display an empty window. The window needs to have the focus to output something.
It shows:
- how to get input from the key position (scancode) instead of the virtual key code (VK_);
- how to use raw input for keyboard inputs;
- how to display the name of a scancode key localized in the user language.
- how to get text input.
You can toggle between virtual key and raw input by left clicking on the window.
Raw input output start with "RW".
Virtual key output start with "VK".
You can toggle between displaying key presses or not by right clicking on the window.
Compile with:
call "C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\vcvarsall.bat" x64
cl main.c -nologo -Zi -link user32.lib
*/
#include <assert.h>
#include <stdio.h>
#include <fcntl.h>
#define UNICODE
#include <windows.h>
unsigned int running = 1;
/*
Store the key as the last state (up = 0, down = 1) of the key in the frame + the number of state transition in the frame.
It allows handling several keypresses of one key in the same frame if you want to.
*/
unsigned char scancodes[256] = { 0 };
#define key_pressed 0x1
#define key_transitionCountMask 0xfe
/*
The scancode values come from:
- http://download.microsoft.com/download/1/6/1/161ba512-40e2-4cc9-843a-923143f3456c/scancode.doc (March 16, 2000).
- http://www.computer-engineering.org/ps2keyboard/scancodes1.html
- using MapVirtualKeyEx( VK_*, MAPVK_VK_TO_VSC_EX, 0 ) with the english us keyboard layout
- reading win32 WM_INPUT keyboard messages.
*/
enum Scancode {
sc_escape = 0x01,
sc_1 = 0x02,
sc_2 = 0x03,
sc_3 = 0x04,
sc_4 = 0x05,
sc_5 = 0x06,
sc_6 = 0x07,
sc_7 = 0x08,
sc_8 = 0x09,
sc_9 = 0x0A,
sc_0 = 0x0B,
sc_minus = 0x0C,
sc_equals = 0x0D,
sc_backspace = 0x0E,
sc_tab = 0x0F,
sc_q = 0x10,
sc_w = 0x11,
sc_e = 0x12,
sc_r = 0x13,
sc_t = 0x14,
sc_y = 0x15,
sc_u = 0x16,
sc_i = 0x17,
sc_o = 0x18,
sc_p = 0x19,
sc_bracketLeft = 0x1A,
sc_bracketRight = 0x1B,
sc_enter = 0x1C,
sc_controlLeft = 0x1D,
sc_a = 0x1E,
sc_s = 0x1F,
sc_d = 0x20,
sc_f = 0x21,
sc_g = 0x22,
sc_h = 0x23,
sc_j = 0x24,
sc_k = 0x25,
sc_l = 0x26,
sc_semicolon = 0x27,
sc_apostrophe = 0x28,
sc_grave = 0x29,
sc_shiftLeft = 0x2A,
sc_backslash = 0x2B,
sc_z = 0x2C,
sc_x = 0x2D,
sc_c = 0x2E,
sc_v = 0x2F,
sc_b = 0x30,
sc_n = 0x31,
sc_m = 0x32,
sc_comma = 0x33,
sc_preiod = 0x34,
sc_slash = 0x35,
sc_shiftRight = 0x36,
sc_numpad_multiply = 0x37,
sc_altLeft = 0x38,
sc_space = 0x39,
sc_capsLock = 0x3A,
sc_f1 = 0x3B,
sc_f2 = 0x3C,
sc_f3 = 0x3D,
sc_f4 = 0x3E,
sc_f5 = 0x3F,
sc_f6 = 0x40,
sc_f7 = 0x41,
sc_f8 = 0x42,
sc_f9 = 0x43,
sc_f10 = 0x44,
sc_numLock = 0x45,
sc_scrollLock = 0x46,
sc_numpad_7 = 0x47,
sc_numpad_8 = 0x48,
sc_numpad_9 = 0x49,
sc_numpad_minus = 0x4A,
sc_numpad_4 = 0x4B,
sc_numpad_5 = 0x4C,
sc_numpad_6 = 0x4D,
sc_numpad_plus = 0x4E,
sc_numpad_1 = 0x4F,
sc_numpad_2 = 0x50,
sc_numpad_3 = 0x51,
sc_numpad_0 = 0x52,
sc_numpad_period = 0x53,
sc_alt_printScreen = 0x54, /* Alt + print screen. MapVirtualKeyEx( VK_SNAPSHOT, MAPVK_VK_TO_VSC_EX, 0 ) returns scancode 0x54. */
sc_bracketAngle = 0x56, /* Key between the left shift and Z. */
sc_f11 = 0x57,
sc_f12 = 0x58,
sc_oem_1 = 0x5a, /* VK_OEM_WSCTRL */
sc_oem_2 = 0x5b, /* VK_OEM_FINISH */
sc_oem_3 = 0x5c, /* VK_OEM_JUMP */
sc_eraseEOF = 0x5d,
sc_oem_4 = 0x5e, /* VK_OEM_BACKTAB */
sc_oem_5 = 0x5f, /* VK_OEM_AUTO */
sc_zoom = 0x62,
sc_help = 0x63,
sc_f13 = 0x64,
sc_f14 = 0x65,
sc_f15 = 0x66,
sc_f16 = 0x67,
sc_f17 = 0x68,
sc_f18 = 0x69,
sc_f19 = 0x6a,
sc_f20 = 0x6b,
sc_f21 = 0x6c,
sc_f22 = 0x6d,
sc_f23 = 0x6e,
sc_oem_6 = 0x6f, /* VK_OEM_PA3 */
sc_katakana = 0x70,
sc_oem_7 = 0x71, /* VK_OEM_RESET */
sc_f24 = 0x76,
sc_sbcschar = 0x77,
sc_convert = 0x79,
sc_nonconvert = 0x7B, /* VK_OEM_PA1 */
sc_media_previous = 0xE010,
sc_media_next = 0xE019,
sc_numpad_enter = 0xE01C,
sc_controlRight = 0xE01D,
sc_volume_mute = 0xE020,
sc_launch_app2 = 0xE021,
sc_media_play = 0xE022,
sc_media_stop = 0xE024,
sc_volume_down = 0xE02E,
sc_volume_up = 0xE030,
sc_browser_home = 0xE032,
sc_numpad_divide = 0xE035,
sc_printScreen = 0xE037,
/*
sc_printScreen:
- make: 0xE02A 0xE037
- break: 0xE0B7 0xE0AA
- MapVirtualKeyEx( VK_SNAPSHOT, MAPVK_VK_TO_VSC_EX, 0 ) returns scancode 0x54;
- There is no VK_KEYDOWN with VK_SNAPSHOT.
*/
sc_altRight = 0xE038,
sc_cancel = 0xE046, /* CTRL + Pause */
sc_home = 0xE047,
sc_arrowUp = 0xE048,
sc_pageUp = 0xE049,
sc_arrowLeft = 0xE04B,
sc_arrowRight = 0xE04D,
sc_end = 0xE04F,
sc_arrowDown = 0xE050,
sc_pageDown = 0xE051,
sc_insert = 0xE052,
sc_delete = 0xE053,
sc_metaLeft = 0xE05B,
sc_metaRight = 0xE05C,
sc_application = 0xE05D,
sc_power = 0xE05E,
sc_sleep = 0xE05F,
sc_wake = 0xE063,
sc_browser_search = 0xE065,
sc_browser_favorites = 0xE066,
sc_browser_refresh = 0xE067,
sc_browser_stop = 0xE068,
sc_browser_forward = 0xE069,
sc_browser_back = 0xE06A,
sc_launch_app1 = 0xE06B,
sc_launch_email = 0xE06C,
sc_launch_media = 0xE06D,
sc_pause = 0xE11D45,
/*
sc_pause:
- make: 0xE11D 45 0xE19D C5
- make in raw input: 0xE11D 0x45
- break: none
- No repeat when you hold the key down
- There are no break so I don't know how the key down/up is expected to work. Raw input sends "keydown" and "keyup" messages, and it appears that the keyup message is sent directly after the keydown message (you can't hold the key down) so depending on when GetMessage or PeekMessage will return messages, you may get both a keydown and keyup message "at the same time". If you use VK messages most of the time you only get keydown messages, but some times you get keyup messages too.
- when pressed at the same time as one or both control keys, generates a 0xE046 (sc_cancel) and the string for that scancode is "break".
*/
};
unsigned int scancodeList[] = {
sc_escape,
sc_1,
sc_2,
sc_3,
sc_4,
sc_5,
sc_6,
sc_7,
sc_8,
sc_9,
sc_0,
sc_minus,
sc_equals,
sc_backspace,
sc_tab,
sc_q,
sc_w,
sc_e,
sc_r,
sc_t,
sc_y,
sc_u,
sc_i,
sc_o,
sc_p,
sc_bracketLeft,
sc_bracketRight,
sc_enter,
sc_controlLeft,
sc_a,
sc_s,
sc_d,
sc_f,
sc_g,
sc_h,
sc_j,
sc_k,
sc_l,
sc_semicolon,
sc_apostrophe,
sc_grave,
sc_shiftLeft,
sc_backslash,
sc_z,
sc_x,
sc_c,
sc_v,
sc_b,
sc_n,
sc_m,
sc_comma,
sc_preiod,
sc_slash,
sc_shiftRight,
sc_numpad_multiply,
sc_altLeft,
sc_space,
sc_capsLock,
sc_f1,
sc_f2,
sc_f3,
sc_f4,
sc_f5,
sc_f6,
sc_f7,
sc_f8,
sc_f9,
sc_f10,
sc_numLock,
sc_scrollLock,
sc_numpad_7,
sc_numpad_8,
sc_numpad_9,
sc_numpad_minus,
sc_numpad_4,
sc_numpad_5,
sc_numpad_6,
sc_numpad_plus,
sc_numpad_1,
sc_numpad_2,
sc_numpad_3,
sc_numpad_0,
sc_numpad_period,
sc_alt_printScreen,
sc_bracketAngle,
sc_f11,
sc_f12,
sc_oem_1,
sc_oem_2,
sc_oem_3,
sc_eraseEOF,
sc_oem_4,
sc_oem_5,
sc_zoom,
sc_help,
sc_f13,
sc_f14,
sc_f15,
sc_f16,
sc_f17,
sc_f18,
sc_f19,
sc_f20,
sc_f21,
sc_f22,
sc_f23,
sc_oem_6,
sc_katakana,
sc_oem_7,
sc_f24,
sc_sbcschar,
sc_convert,
sc_nonconvert,
sc_media_previous,
sc_media_next,
sc_numpad_enter,
sc_controlRight,
sc_volume_mute,
sc_launch_app2,
sc_media_play,
sc_media_stop,
sc_volume_down,
sc_volume_up,
sc_browser_home,
sc_numpad_divide,
sc_printScreen,
sc_altRight,
sc_cancel,
sc_home,
sc_arrowUp,
sc_pageUp,
sc_arrowLeft,
sc_arrowRight,
sc_end,
sc_arrowDown,
sc_pageDown,
sc_insert,
sc_delete,
sc_metaLeft,
sc_metaRight,
sc_application,
sc_power,
sc_sleep,
sc_wake,
sc_browser_search,
sc_browser_favorites,
sc_browser_refresh,
sc_browser_stop,
sc_browser_forward,
sc_browser_back,
sc_launch_app1,
sc_launch_email,
sc_launch_media,
sc_pause
};
size_t getScancodeOffset(unsigned int scancode) {
size_t result = scancode;
size_t group_0_end = sc_nonconvert;
size_t group_1_start = sc_media_previous;
size_t group_1_end = sc_launch_media;
size_t group_2_start = sc_pause;
if (scancode >= group_2_start) {
result = group_0_end + 1 + (group_1_end - group_1_start) + 1 + (scancode - group_2_start);
}
else if (scancode >= group_1_start) {
result = group_0_end + 1 + (scancode - group_1_start);
}
assert(result <= 0xff);
return result;
}
void syncKeys(void) {
size_t index = 0;
while (index < sizeof(scancodeList) / sizeof(scancodeList[0])) {
unsigned int scancode = scancodeList[index];
size_t offset;
unsigned int vk;
unsigned short keyState;
if (scancode == 0x45) {
scancode = 0xE045;
}
else if (scancode == 0xE11D45) {
scancode = 0x45;
}
offset = getScancodeOffset(scancode);
vk = MapVirtualKeyEx(scancode, MAPVK_VSC_TO_VK_EX, 0);
keyState = GetAsyncKeyState(vk);
scancodes[offset] = ((keyState & (0x1 << 15)) > 0) ? key_pressed : 0;
index++;
}
}
void clearKeys(void) {
size_t index = 0;
while (index < sizeof(scancodes) / sizeof(scancodes[0])) {
scancodes[index] = (scancodes[index] & key_pressed) << 1;
index++;
}
}
LRESULT CALLBACK windowProc(HWND window, UINT message, WPARAM wParam, LPARAM lParam) {
LRESULT result = 0;
switch (message) {
case WM_CLOSE:
case WM_QUIT:
case WM_DESTROY: {
running = 0;
} break;
/* Doesn't go through peekmessage. */
case WM_SYSCOMMAND: {
/* Remove beeping sound when ALT + some key is pressed. */
if (wParam == SC_KEYMENU) {
result = 0;
}
else {
result = DefWindowProc(window, message, wParam, lParam);
}
} break;
case WM_SETFOCUS: {
syncKeys();
result = 0;
} break;
case WM_KILLFOCUS: {
clearKeys();
result = 0;
} break;
/* End of no peekmessage */
default: {
result = DefWindowProc(window, message, wParam, lParam);
} break;
}
return result;
}
unsigned int getScancodeName(unsigned int scancode, wchar_t* buffer, unsigned int bufferLength) {
unsigned int result = 0;
unsigned int extended = scancode & 0xffff00;
unsigned int lParam = 0;
if (extended) {
if (extended == 0xE11D00) {
lParam = 0x45 << 16;
}
else {
lParam = (0x100 | (scancode & 0xff)) << 16;
}
}
else {
lParam = scancode << 16;
if (scancode == 0x45) {
lParam |= (0x1 << 24);
}
}
result = GetKeyNameText(lParam, buffer, bufferLength);
return result;
}
unsigned int isPressed(unsigned int scancode) {
size_t offset = getScancodeOffset(scancode);
unsigned int result = scancodes[offset] & key_pressed;
return result;
}
unsigned int justPressed(unsigned int scancode) {
size_t offset = getScancodeOffset(scancode);
unsigned int result = (scancodes[offset] & key_pressed) && (scancodes[offset] & key_transitionCountMask);
return result;
}
unsigned int justReleased(unsigned int scancode) {
size_t offset = getScancodeOffset(scancode);
unsigned int result = !(scancodes[offset] & key_pressed) && (scancodes[offset] & key_transitionCountMask);
return result;
}
int main(void) {
WNDCLASS windowClass = { 0 };
HWND window = 0;
RAWINPUTDEVICE rawInputDevice = { 0 };
unsigned int rawInputRegistered = 0;
unsigned int pauseScancodeRead = 0;
unsigned short textInputBuffer[64] = { 0 };
size_t textInputCount = 0;
unsigned int useRawInput = 0;
unsigned int displayKeys = 1;
unsigned short highSurrogate = 0;
/* Set stdout as UTF-16. */
_setmode(_fileno(stdout), _O_U16TEXT);
windowClass.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
windowClass.lpfnWndProc = windowProc;
windowClass.lpszClassName = L"window_scancodes";
windowClass.hCursor = LoadCursor(0, IDC_ARROW);
windowClass.cbWndExtra = 0;
RegisterClass(&windowClass);
window = CreateWindowEx(0, L"window_scancodes", L"Scancodes", WS_OVERLAPPEDWINDOW, 0, 0, 300, 200, 0, 0, 0, 0);
ShowWindow(window, SW_SHOW);
/*
Incomplete list of the usage page and usage ID that you can use for raw inputs:
https://msdn.microsoft.com/windows/hardware/drivers/hid/top-level-collections-opened-by-windows-for-system-use
Flags: https://msdn.microsoft.com/en-us/library/windows/desktop/ms645565(v=vs.85).aspx
RIDEV_NOLEGACY: If set, this prevents any devices specified by usUsagePage or usUsage from generating legacy messages. This is only for the mouse and keyboard.
*/
rawInputDevice.usUsagePage = 0x01;
rawInputDevice.usUsage = 0x06;
rawInputDevice.dwFlags = 0;
rawInputDevice.hwndTarget = 0;
rawInputRegistered = RegisterRawInputDevices(&rawInputDevice, 1, sizeof(rawInputDevice));
while (running) {
MSG message;
/* When a key is held down you only get keydown message at intervals. */
size_t scancodeIndex = 0;
while (scancodeIndex < sizeof(scancodes) / sizeof(scancodes[0])) {
scancodes[scancodeIndex] &= key_pressed;
scancodeIndex++;
}
textInputCount = 0;
while (PeekMessage(&message, 0, 0, 0, PM_REMOVE)) {
switch (message.message) {
case WM_LBUTTONDOWN: {
useRawInput = !useRawInput;
} break;
case WM_RBUTTONDOWN: {
displayKeys = !displayKeys;
} break;
case WM_SYSKEYDOWN:
case WM_SYSKEYUP:
case WM_KEYDOWN:
case WM_KEYUP: {
unsigned int scancode = (message.lParam >> 16) & 0xff;
unsigned int extended = (message.lParam >> 24) & 0x1;
unsigned char pressed = ((~message.lParam) >> 31) & key_pressed;
unsigned char transition = 0;
unsigned char value = 0;
size_t offset = 0;
/*
- sc_pause is 0xE11D45 but the extended flag is not set in lParam so the lParam scancode is 0x45;
- sc_numLock is 0x45 but the extended flag is set in lParam so the lParam scancode is 0xE045;
Force them to the "right" value.
Alt + print screen returns scancode 0x54. Force it to return 0xE037 because 0x54 doesn't have a name for the key.
*/
if (extended) {
if (scancode != 0x45) {
scancode |= 0xE000;
}
}
else {
if (scancode == 0x45) {
scancode = 0xE11D45;
}
else if (scancode == 0x54) {
scancode = 0xE037;
}
}
wprintf(L"WestonSc: %u \n", scancode);
offset = getScancodeOffset(scancode);
if (scancode == 0xE037) {
transition = 1; /* Force transition because print screen only sends key up messages.*/
}
else {
transition = (scancodes[offset] & key_pressed) != pressed;
}
value = scancodes[offset] & key_transitionCountMask;
value += (transition << 1);
value |= pressed;
if (!useRawInput) {
scancodes[offset] = value;
}
TranslateMessage(&message);
} break;
case WM_INPUT: {
RAWINPUT rawInput;
unsigned int rawInputSize = sizeof(rawInput);
GetRawInputData((HRAWINPUT)message.lParam, RID_INPUT, &rawInput, &rawInputSize, sizeof(RAWINPUTHEADER));
if (rawInput.header.dwType == RIM_TYPEKEYBOARD) {
unsigned int pressed = 0;
unsigned int ignore = 0;
unsigned int scancode = rawInput.data.keyboard.MakeCode; /* MakeCode is unsigned short. */
unsigned short flags = rawInput.data.keyboard.Flags;
assert(scancode <= 0xff);
/*
rawInput.data.keyboard.Reserved;
rawInput.data.keyboard.VKey;
rawInput.data.keyboard.Message;
rawInput.data.keyboard.ExtraInformation;
*/
if ((flags & RI_KEY_BREAK) == 0) {
pressed = 1;
}
if (flags & RI_KEY_E0) {
scancode |= 0xE000;
}
else if (flags & RI_KEY_E1) {
scancode |= 0xE100;
}
/* The pause scancode is in 2 parts: a WM_INPUT with 0xE11D and one WM_INPUT with 0x45. */
if (pauseScancodeRead) {
if (scancode == 0x45) {
scancode = 0xE11D45;
}
pauseScancodeRead = 0;
}
else if (scancode == 0xE11D) {
pauseScancodeRead = 1;
}
else if (scancode == 0x54) {
/* Alt + print screen return scancode 0x54 but we want it to return 0xE037 because 0x54 will not return a name for the key. */
scancode = 0xE037;
}
/*
Some scancodes we can ignore:
- 0xE11D: first part of the Pause scancode (handled above);
- 0xE02A: first part of the Print Screen scancode if no Shift, Control or Alt keys are pressed;
- 0xE02A, 0xE0AA, 0xE036, 0xE0B6: generated in addition of Insert, Delete, Home, End, Page Up, Page Down, Up, Down, Left, Right when num lock is on; or when num lock is off but one or both shift keys are pressed;
- 0xE02A, 0xE0AA, 0xE036, 0xE0B6: generated in addition of Numpad Divide and one or both Shift keys are pressed;
- Some of those a break scancode;
When holding a key down, the pre/postfix (0xE02A) is not repeated.
*/
if (scancode == 0xE11D || scancode == 0xE02A || scancode == 0xE0AA || scancode == 0xE0B6 || scancode == 0xE036) {
ignore = 1;
}
if (!ignore && useRawInput) {
size_t offset = getScancodeOffset(scancode);
unsigned char transition = (scancodes[offset] & key_pressed) != pressed;
unsigned char value = scancodes[offset] & key_transitionCountMask;
value += (transition << 1);
value |= pressed;
scancodes[offset] = value;
}
}
} break;
case WM_CHAR: {
/*
WM_CHAR is generated when WM_KEYDOWN message are passed to TranslateMessage;
wParam is UTF-16.
If the codepoint is 4 bytes, there are 2 WM_CHAR message, one with the high surrogate and one with the low surrogate.
https://msdn.microsoft.com/en-us/library/windows/desktop/ms646276(v=vs.85).aspx
*/
/* UTF-16 to codepoint */
unsigned int c = (unsigned int)message.wParam;
unsigned short utf16_hi_surrogate_start = 0xD800;
unsigned short utf16_lo_surrogate_start = 0xDC00;
unsigned short utf16_surrogate_end = 0xDFFF;
if (c >= utf16_hi_surrogate_start && c < utf16_lo_surrogate_start) {
highSurrogate = (unsigned short)c;
}
else {
if (c >= utf16_lo_surrogate_start && c <= utf16_surrogate_end) {
unsigned short lowSurrogate = (unsigned short)c;
c = (highSurrogate - utf16_hi_surrogate_start) << 10;
c |= (lowSurrogate - utf16_lo_surrogate_start);
c += 0x10000;
highSurrogate = 0;
}
/* Save the codepoint ( the variable c ) here. */
}
/* In this example I only need the UTF-16 characters. */
if (textInputCount < (sizeof(textInputBuffer) / sizeof(textInputBuffer[0])) - 1) {
textInputBuffer[textInputCount++] = (unsigned short)message.wParam;
textInputBuffer[textInputCount] = 0;
}
} break;
default: {
TranslateMessage(&message);
DispatchMessage(&message);
} break;
}
}
if (displayKeys) {
size_t index = 0;
while (index < sizeof(scancodeList) / sizeof(scancodeList[0])) {
/* The name is UTF-16. */
wchar_t textBuffer[64] = L" : ";
unsigned int length = 0;
unsigned int sc = scancodeList[index];
if (useRawInput) {
textBuffer[0] = 'R';
textBuffer[1] = 'W';
}
else {
textBuffer[0] = 'V';
textBuffer[1] = 'K';
}
length = getScancodeName(sc, textBuffer + 4, sizeof(textBuffer));
if (justPressed(sc)) {
wprintf(textBuffer);
wprintf(L" scancode: ");
wprintf(L"%u", sc);
wprintf(L" just pressed\n");
}
if (isPressed(sc)) {
wprintf(textBuffer);
wprintf(L" scancode: ");
wprintf(L"%u", sc);
wprintf(L" pressed\n");
}
if (justReleased(sc)) {
wprintf(textBuffer);
wprintf(L" scancode: ");
wprintf(L"%u", sc);
wprintf(L" just released\n\n");
}
index++;
}
}
if (textInputCount > 0) {
wprintf(L"Text input: ");
wprintf((wchar_t*)textInputBuffer);
wprintf(L"\n");
}
/* "Simulate" vsync */
Sleep(16);
}
return 0;
}
@jamiehankins
Copy link

I know this is two years ago, which is an eternity in this stuff, but there are a couple of changes that you could make to make the output more helpful.

  1. Add this somewhere around the top:
#define DIGITS(x) (x > 0xff ? x > 0xffff ? x > 0xffffff ? 8 : 6 : 4 : 2)
  1. Change the sprintf statements to look like this:
wprintf(L"WestonSc: 0x%0*x\r\n", DIGITS(scancode), scancode);

Thanks for writing this, it's very cool! :-)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment