Skip to content

Instantly share code, notes, and snippets.

@saber-nyan
Last active June 20, 2019 23:10
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save saber-nyan/c1d75fa4e65a2fcc84fdf6b0c8576947 to your computer and use it in GitHub Desktop.
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
#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);
}
@MustacheFeetTail
Copy link

MustacheFeetTail commented Nov 20, 2018

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