Last active
June 20, 2019 23:10
-
-
Save saber-nyan/c1d75fa4e65a2fcc84fdf6b0c8576947 to your computer and use it in GitHub Desktop.
Keyboard layout switch on any key, source: http://haali.su/winutils/ + @AHOHNMYC enhancements
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#define _WIN32_WINNT 0x500 | |
#include <windows.h> | |
#include <tchar.h> | |
TCHAR g_prog_dir[MAX_PATH*2]; | |
DWORD g_prog_dir_len; | |
HHOOK g_khook; | |
HANDLE g_hEvent; | |
UINT g_key; | |
LRESULT CALLBACK KbdHook(int nCode, WPARAM wParam, LPARAM lParam) { | |
HWND hWnd; | |
if (nCode == HC_ACTION) { | |
KBDLLHOOKSTRUCT* ks = (KBDLLHOOKSTRUCT*)lParam; | |
if (ks->vkCode==g_key) { | |
/* Negative value => high bit is set => Shift is pressed => collapsing */ | |
if (GetKeyState(VK_SHIFT)<0) | |
goto skip; | |
if (wParam==WM_KEYDOWN) { | |
hWnd=GetForegroundWindow(); | |
if (hWnd) | |
PostMessage(hWnd,WM_INPUTLANGCHANGEREQUEST,0,(LPARAM)HKL_NEXT); | |
} | |
return 1; | |
} | |
} | |
skip: | |
return CallNextHookEx(g_khook,nCode,wParam,lParam); | |
} | |
void failedx(const TCHAR *msg) { | |
MessageBox(NULL,msg,_T("Error"),MB_OK|MB_ICONERROR); | |
ExitProcess(1); | |
} | |
void failed(const TCHAR *msg) { | |
DWORD fm; | |
TCHAR *msg1,*msg2; | |
const TCHAR *args[2]; | |
fm=FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM| | |
FORMAT_MESSAGE_IGNORE_INSERTS, | |
NULL,GetLastError(),0,(LPTSTR)&msg1,0,NULL); | |
if (fm==0) | |
ExitProcess(1); | |
args[0]=msg; | |
args[1]=msg1; | |
fm=FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_STRING| | |
FORMAT_MESSAGE_ARGUMENT_ARRAY, | |
_T("%1: %2"),0,0,(LPTSTR)&msg2,0,(va_list*)&args[0]); | |
if (fm==0) | |
ExitProcess(1); | |
MessageBox(NULL,msg2,_T("Error"),MB_OK|MB_ICONERROR); | |
ExitProcess(1); | |
} | |
void CALLBACK TimerCb(__attribute__((unused)) HWND hWnd, | |
__attribute__((unused)) UINT uMsg, | |
__attribute__((unused)) UINT_PTR idEvent, | |
__attribute__((unused)) DWORD dwTime) { | |
if (WaitForSingleObject(g_hEvent,0)==WAIT_OBJECT_0) | |
PostQuitMessage(0); | |
} | |
int __main() { | |
MSG msg; | |
DWORD sz; | |
BOOL fQuit=FALSE; | |
TCHAR *cmd; | |
g_key=VK_APPS; | |
cmd=GetCommandLine(); | |
sz=lstrlen(cmd); | |
if (sz>2 && lstrcmp(cmd+sz-2,_T(" q"))==0) | |
fQuit=TRUE; | |
else { | |
UINT nk=0; | |
TCHAR *qq=cmd+sz; | |
while (qq>cmd && qq[-1]>=_T('0') && qq[-1]<=_T('9')) | |
--qq; | |
while (*qq) | |
nk=nk*10+*qq++-_T('0'); | |
if (nk) | |
g_key=nk; | |
} | |
g_hEvent=CreateEvent(NULL,TRUE,FALSE,_T("HaaliLSwitch")); | |
if (g_hEvent==NULL) | |
failed(_T("CreateEvent()")); | |
if (GetLastError()==ERROR_ALREADY_EXISTS) { | |
if (fQuit) { | |
SetEvent(g_hEvent); | |
goto quit; | |
} | |
failedx(_T("LSwitch is already running!")); | |
} | |
if (fQuit) | |
failedx(_T("LSwitch is not running!")); | |
sz=GetModuleFileName(NULL,g_prog_dir,MAX_PATH); | |
if (sz==0) | |
failed(_T("GetModuleFileName()")); | |
if (sz==MAX_PATH) | |
failedx(_T("Module file name is too long.")); | |
while (sz>0 && g_prog_dir[sz-1]!=_T('\\')) | |
--sz; | |
g_prog_dir_len=sz; | |
if (SetTimer(NULL,0,500,TimerCb)==0) | |
failed(_T("SetTimer()")); | |
g_khook=SetWindowsHookEx(WH_KEYBOARD_LL,KbdHook,GetModuleHandle(0),0); | |
if (g_khook==0) | |
failed(_T("SetWindowsHookEx()")); | |
while (GetMessage(&msg,0,0,0)) { | |
TranslateMessage(&msg); | |
DispatchMessage(&msg); | |
} | |
UnhookWindowsHookEx(g_khook); | |
quit: | |
CloseHandle(g_hEvent); | |
ExitProcess(0); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Meow-meow-meow
Moew-oewm-emwoemwoemweom