This tool will listen for ASUS notebook's FN keystrokes. And it will map ROG key to Scroll Lock and Fan key to Num Lock. (Ctrl + Num Lock = Pause key).
$ clang main.cpp -o rog.exe && rog.exe| // Introduce some shit (a.k.a. winapi) | |
| #define UNICODE | |
| #include <windows.h> | |
| #pragma comment(lib, "user32") | |
| // #include <fcntl.h> | |
| #define _O_U16TEXT 0x00020000 | |
| #define _O_U8TEXT 0x00040000 | |
| #include <io.h> | |
| #include <stdio.h> | |
| enum ASUSKEYS : UINT { | |
| ROG_KEY = 56, | |
| FN_F10 = 107, | |
| MUTE = 124, | |
| FN_V = 138, | |
| FN_C = 158, | |
| FN_F5 = 174, | |
| FN_LEFT = 178, | |
| FN_RIGHT = 179, | |
| FN_UP = 196, | |
| FN_DOWN = 197, | |
| // Aliases | |
| FAN_KEY = FN_F5, | |
| }; | |
| const wchar_t pClassName[] = L"ROGKeyRebind"; | |
| const wchar_t pWindowName[] = L"ROGKeyRebind"; | |
| UINT pAPCI = RegisterWindowMessageW(L"ACPI Notification through ATKHotkey from BIOS"); | |
| void SendScanCode(WORD scancode) { | |
| INPUT ip; | |
| ip.type = INPUT_KEYBOARD; | |
| ip.ki.time = 0; | |
| ip.ki.wVk = 0; | |
| ip.ki.dwExtraInfo = 0; | |
| ip.ki.dwFlags = KEYEVENTF_SCANCODE; | |
| ip.ki.wScan = scancode; | |
| SendInput(1, &ip, sizeof(INPUT)); | |
| ip.ki.dwFlags = KEYEVENTF_SCANCODE | KEYEVENTF_KEYUP; | |
| SendInput(1, &ip, sizeof(INPUT)); | |
| return; | |
| } | |
| LRESULT CALLBACK MainWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { | |
| if (uMsg == pAPCI) { | |
| switch (wParam) { | |
| case ASUSKEYS::MUTE: | |
| wprintf(L"Mute key\n"); | |
| break; | |
| case ASUSKEYS::FAN_KEY: | |
| wprintf(L"Fan key\n"); | |
| SendScanCode(0x45); // Send NumLock | |
| break; | |
| case ASUSKEYS::ROG_KEY: | |
| wprintf(L"ROG key\n"); | |
| SendScanCode(0x46); // Send ScrollLock | |
| break; | |
| case ASUSKEYS::FN_F10: | |
| wprintf(L"Fn + 10 key\n"); | |
| break; | |
| case ASUSKEYS::FN_C: | |
| wprintf(L"Fn + C key\n"); | |
| break; | |
| case ASUSKEYS::FN_V: | |
| wprintf(L"Fn + V key\n"); | |
| break; | |
| case ASUSKEYS::FN_UP: | |
| wprintf(L"Fn + Up Arrow key\n"); | |
| break; | |
| case ASUSKEYS::FN_LEFT: | |
| wprintf(L"Fn + Left Arrow key\n"); | |
| break; | |
| case ASUSKEYS::FN_DOWN: | |
| wprintf(L"Fn + Down Arrow key\n"); | |
| break; | |
| case ASUSKEYS::FN_RIGHT: | |
| wprintf(L"Fn + Right Arrow key\n"); | |
| break; | |
| default: | |
| wprintf(L"Unknown key: %d\n", wParam); | |
| break; | |
| } | |
| } else { | |
| switch (uMsg) { | |
| case WM_DESTROY: | |
| wprintf(L"Error window destroyed. Shutting down.\n"); | |
| PostQuitMessage(0); | |
| ExitProcess(4); | |
| break; | |
| default: | |
| break; | |
| } | |
| } | |
| return DefWindowProcW(hWnd, uMsg, wParam, lParam); | |
| } | |
| int main() { | |
| _setmode(_fileno(stdout), _O_U16TEXT); | |
| HMODULE hInst = GetModuleHandleW(nullptr); | |
| if (hInst == 0) { | |
| wprintf(L"Error getting module.\n"); | |
| return 2; | |
| } | |
| WNDCLASSEXW wc = {}; | |
| wc.lpfnWndProc = MainWndProc; | |
| wc.hInstance = hInst; | |
| wc.lpszClassName = pWindowName; | |
| wc.cbSize = sizeof(wc); | |
| RegisterClassEx(&wc); | |
| HWND hWnd = CreateWindowExW( | |
| 0, | |
| wc.lpszClassName, | |
| pWindowName, | |
| WS_VISIBLE, | |
| -1, -1, 1, 1, | |
| nullptr, | |
| nullptr, | |
| hInst, | |
| nullptr | |
| ); | |
| if (hWnd == 0) { | |
| wprintf(L"Error spawning window.\n"); | |
| return 3; | |
| } | |
| ShowWindow(hWnd, SW_HIDE); | |
| ChangeWindowMessageFilterEx( | |
| hWnd, | |
| pAPCI, | |
| MSGFLT_ALLOW, | |
| nullptr | |
| ); | |
| wprintf(L"Listening for keys.\n"); | |
| MSG msg; | |
| int bRet = -1; | |
| while ((bRet = GetMessageW(&msg, hWnd, 0, 0)) != 0) { | |
| if (bRet < 0) { | |
| wprintf(L"Unknown error while getting message."); | |
| return 1; | |
| } else { | |
| TranslateMessage(&msg); | |
| DispatchMessage(&msg); | |
| } | |
| } | |
| wprintf(L"Shutting down.\n"); | |
| return 0; | |
| } |