mirror of
https://github.com/reactos/reactos.git
synced 2025-05-28 05:28:14 +00:00
[KBSWITCH]
- Use strsafe functions - Use Shell Hooks in dll for detecting keyboard layout switching - Fix bug in loading kbsdll * Detection switch keyboard layout is now working in Windovs, but does not work in ReactOS (WH_SHELL not work in win32k) svn path=/trunk/; revision=72143
This commit is contained in:
parent
a32f426a76
commit
bc10137a10
3 changed files with 97 additions and 106 deletions
|
@ -7,9 +7,10 @@
|
|||
|
||||
#include "../kbswitch.h"
|
||||
|
||||
HHOOK hKeyboardHook, hLangHook, hWinHook;
|
||||
HINSTANCE hInstance;
|
||||
HWND hKbSwitchWnd;
|
||||
HHOOK hWinHook = NULL;
|
||||
HHOOK hShellHook = NULL;
|
||||
HINSTANCE hInstance = NULL;
|
||||
HWND hKbSwitchWnd = NULL;
|
||||
|
||||
static VOID
|
||||
SendMessageToMainWnd(UINT Msg, WPARAM wParam, LPARAM lParam)
|
||||
|
@ -17,40 +18,6 @@ SendMessageToMainWnd(UINT Msg, WPARAM wParam, LPARAM lParam)
|
|||
PostMessage(hKbSwitchWnd, Msg, wParam, lParam);
|
||||
}
|
||||
|
||||
/* Not used yet */
|
||||
LRESULT CALLBACK
|
||||
KeyboardHookProc(int code, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
return CallNextHookEx(hKeyboardHook, code, wParam, lParam);
|
||||
}
|
||||
|
||||
LRESULT CALLBACK
|
||||
LangHookProc(int code, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
PMSG msg;
|
||||
msg = (PMSG) lParam;
|
||||
|
||||
switch (msg->message)
|
||||
{
|
||||
case WM_INPUTLANGCHANGEREQUEST:
|
||||
{
|
||||
SendMessageToMainWnd(WM_LANG_CHANGED, wParam, msg->lParam);
|
||||
}
|
||||
break;
|
||||
|
||||
case WM_HOTKEY:
|
||||
{
|
||||
if (msg->hwnd)
|
||||
{
|
||||
SendMessageToMainWnd(WM_LOAD_LAYOUT, (WPARAM)msg->hwnd, msg->lParam);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return CallNextHookEx(hLangHook, code, wParam, lParam);
|
||||
}
|
||||
|
||||
LRESULT CALLBACK
|
||||
WinHookProc(int code, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
|
@ -69,18 +36,6 @@ WinHookProc(int code, WPARAM wParam, LPARAM lParam)
|
|||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case HCBT_CREATEWND:
|
||||
{
|
||||
RegisterHotKey((HWND)wParam, id, MOD_ALT, VK_F10);
|
||||
}
|
||||
break;
|
||||
|
||||
case HCBT_DESTROYWND:
|
||||
{
|
||||
UnregisterHotKey((HWND)wParam, id);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
GlobalDeleteAtom(id);
|
||||
|
@ -88,25 +43,40 @@ WinHookProc(int code, WPARAM wParam, LPARAM lParam)
|
|||
return CallNextHookEx(hWinHook, code, wParam, lParam);
|
||||
}
|
||||
|
||||
LRESULT CALLBACK
|
||||
ShellHookProc(int code, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
switch (code)
|
||||
{
|
||||
case HSHELL_LANGUAGE:
|
||||
{
|
||||
SendMessageToMainWnd(WM_LANG_CHANGED, wParam, lParam);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return CallNextHookEx(hShellHook, code, wParam, lParam);
|
||||
}
|
||||
|
||||
BOOL WINAPI
|
||||
KbSwitchSetHooks(VOID)
|
||||
{
|
||||
hKeyboardHook = SetWindowsHookEx(WH_KEYBOARD, KeyboardHookProc, hInstance, 0);
|
||||
hLangHook = SetWindowsHookEx(WH_GETMESSAGE, LangHookProc, hInstance, 0);
|
||||
hWinHook = SetWindowsHookEx(WH_CBT, WinHookProc, hInstance, 0);
|
||||
hShellHook = SetWindowsHookEx(WH_SHELL, ShellHookProc, hInstance, 0);
|
||||
|
||||
if ((hKeyboardHook)&&(hLangHook)&&(hWinHook))
|
||||
return TRUE;
|
||||
else
|
||||
if (!hWinHook || !hShellHook)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
VOID WINAPI
|
||||
KbSwitchDeleteHooks(VOID)
|
||||
{
|
||||
if (hKeyboardHook) UnhookWindowsHookEx(hKeyboardHook);
|
||||
if (hLangHook) UnhookWindowsHookEx(hLangHook);
|
||||
if (hWinHook) UnhookWindowsHookEx(hWinHook);
|
||||
if (hShellHook) UnhookWindowsHookEx(hShellHook);
|
||||
}
|
||||
|
||||
BOOL WINAPI
|
||||
|
@ -117,10 +87,15 @@ DllMain(IN HINSTANCE hinstDLL,
|
|||
switch (dwReason)
|
||||
{
|
||||
case DLL_PROCESS_ATTACH:
|
||||
{
|
||||
hInstance = hinstDLL;
|
||||
hKbSwitchWnd = FindWindow(szKbSwitcherName, NULL);
|
||||
if (!hKbSwitchWnd) return FALSE;
|
||||
break;
|
||||
if (!hKbSwitchWnd)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
|
|
|
@ -10,15 +10,15 @@
|
|||
|
||||
#define WM_NOTIFYICONMSG (WM_USER + 248)
|
||||
|
||||
PROC KbSwitchSetHooks = NULL;
|
||||
PROC KbSwitchDeleteHooks = NULL;
|
||||
PKBSWITCHSETHOOKS KbSwitchSetHooks = NULL;
|
||||
PKBSWITCHDELETEHOOKS KbSwitchDeleteHooks = NULL;
|
||||
|
||||
|
||||
static BOOL
|
||||
GetLayoutID(LPTSTR szLayoutNum, LPTSTR szLCID);
|
||||
GetLayoutID(LPTSTR szLayoutNum, LPTSTR szLCID, SIZE_T LCIDLength);
|
||||
|
||||
static BOOL
|
||||
GetLayoutName(LPTSTR szLayoutNum, LPTSTR szName);
|
||||
GetLayoutName(LPTSTR szLayoutNum, LPTSTR szName, SIZE_T NameLength);
|
||||
|
||||
HINSTANCE hInst;
|
||||
HANDLE hProcessHeap;
|
||||
|
@ -41,9 +41,9 @@ CreateTrayIcon(LPTSTR szLCID)
|
|||
if (GetLocaleInfo(lId,
|
||||
LOCALE_SISO639LANGNAME,
|
||||
szBuf,
|
||||
sizeof(szBuf) / sizeof(TCHAR)) == 0)
|
||||
ARRAYSIZE(szBuf)) == 0)
|
||||
{
|
||||
lstrcpy(szBuf, _T("??"));
|
||||
StringCchCopy(szBuf, ARRAYSIZE(szBuf), _T("??"));
|
||||
}
|
||||
|
||||
hdcsrc = GetDC(NULL);
|
||||
|
@ -103,9 +103,10 @@ AddTrayIcon(HWND hwnd)
|
|||
TCHAR szLCID[CCH_LAYOUT_ID + 1];
|
||||
TCHAR szName[MAX_PATH];
|
||||
|
||||
GetLayoutID(_T("1"), szLCID);
|
||||
GetLayoutName(_T("1"), szName);
|
||||
GetLayoutID(_T("1"), szLCID, ARRAYSIZE(szLCID));
|
||||
GetLayoutName(_T("1"), szName, ARRAYSIZE(szName));
|
||||
|
||||
memset(&tnid, 0, sizeof(tnid));
|
||||
tnid.cbSize = sizeof(NOTIFYICONDATA);
|
||||
tnid.hWnd = hwnd;
|
||||
tnid.uID = 1;
|
||||
|
@ -113,7 +114,7 @@ AddTrayIcon(HWND hwnd)
|
|||
tnid.uCallbackMessage = WM_NOTIFYICONMSG;
|
||||
tnid.hIcon = CreateTrayIcon(szLCID);
|
||||
|
||||
lstrcpyn(tnid.szTip, szName, sizeof(tnid.szTip) / sizeof(TCHAR));
|
||||
StringCchCopy(tnid.szTip, ARRAYSIZE(tnid.szTip), szName);
|
||||
|
||||
Shell_NotifyIcon(NIM_ADD, &tnid);
|
||||
}
|
||||
|
@ -123,6 +124,7 @@ DelTrayIcon(HWND hwnd)
|
|||
{
|
||||
NOTIFYICONDATA tnid;
|
||||
|
||||
memset(&tnid, 0, sizeof(tnid));
|
||||
tnid.cbSize = sizeof(NOTIFYICONDATA);
|
||||
tnid.hWnd = hwnd;
|
||||
tnid.uID = 1;
|
||||
|
@ -135,6 +137,7 @@ UpdateTrayIcon(HWND hwnd, LPTSTR szLCID, LPTSTR szName)
|
|||
{
|
||||
NOTIFYICONDATA tnid;
|
||||
|
||||
memset(&tnid, 0, sizeof(tnid));
|
||||
tnid.cbSize = sizeof(NOTIFYICONDATA);
|
||||
tnid.hWnd = hwnd;
|
||||
tnid.uID = 1;
|
||||
|
@ -142,13 +145,13 @@ UpdateTrayIcon(HWND hwnd, LPTSTR szLCID, LPTSTR szName)
|
|||
tnid.uCallbackMessage = WM_NOTIFYICONMSG;
|
||||
tnid.hIcon = CreateTrayIcon(szLCID);
|
||||
|
||||
lstrcpyn(tnid.szTip, szName, sizeof(tnid.szTip) / sizeof(TCHAR));
|
||||
StringCchCopy(tnid.szTip, ARRAYSIZE(tnid.szTip), szName);
|
||||
|
||||
Shell_NotifyIcon(NIM_MODIFY, &tnid);
|
||||
}
|
||||
|
||||
static BOOL
|
||||
GetLayoutID(LPTSTR szLayoutNum, LPTSTR szLCID)
|
||||
GetLayoutID(LPTSTR szLayoutNum, LPTSTR szLCID, SIZE_T LCIDLength)
|
||||
{
|
||||
DWORD dwBufLen;
|
||||
DWORD dwRes;
|
||||
|
@ -178,7 +181,7 @@ GetLayoutID(LPTSTR szLayoutNum, LPTSTR szLCID)
|
|||
if (RegQueryValueEx(hKey, szTempLCID, NULL, NULL, (LPBYTE)szLCID, &dwBufLen) != ERROR_SUCCESS)
|
||||
{
|
||||
// No substitute found, then use the old LCID
|
||||
lstrcpy(szLCID, szTempLCID);
|
||||
StringCchCopy(szLCID, LCIDLength, szTempLCID);
|
||||
}
|
||||
|
||||
RegCloseKey(hKey);
|
||||
|
@ -186,24 +189,24 @@ GetLayoutID(LPTSTR szLayoutNum, LPTSTR szLCID)
|
|||
else
|
||||
{
|
||||
// Substitutes key couldn't be opened, so use the old LCID
|
||||
lstrcpy(szLCID, szTempLCID);
|
||||
StringCchCopy(szLCID, LCIDLength, szTempLCID);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
VOID
|
||||
GetLayoutIDByHkl(HKL hKl, LPTSTR szLayoutID)
|
||||
GetLayoutIDByHkl(HKL hKl, LPTSTR szLayoutID, SIZE_T LayoutIDLength)
|
||||
{
|
||||
/*
|
||||
FIXME!!! This way of getting layout ID incorrect!
|
||||
This will not work correctly for 0001040a, 00010410, etc
|
||||
*/
|
||||
wsprintf(szLayoutID, _T("%08x"), LOWORD(hKl));
|
||||
StringCchPrintf(szLayoutID, LayoutIDLength, _T("%08x"), LOWORD(hKl));
|
||||
}
|
||||
|
||||
static BOOL
|
||||
GetLayoutName(LPTSTR szLayoutNum, LPTSTR szName)
|
||||
GetLayoutName(LPTSTR szLayoutNum, LPTSTR szName, SIZE_T NameLength)
|
||||
{
|
||||
HKEY hKey;
|
||||
DWORD dwBufLen;
|
||||
|
@ -212,20 +215,22 @@ GetLayoutName(LPTSTR szLayoutNum, LPTSTR szName)
|
|||
HANDLE hLib;
|
||||
UINT i, j, k;
|
||||
|
||||
if(!GetLayoutID(szLayoutNum, szLCID))
|
||||
if (!GetLayoutID(szLayoutNum, szLCID, ARRAYSIZE(szLCID)))
|
||||
return FALSE;
|
||||
|
||||
wsprintf(szBuf, _T("SYSTEM\\CurrentControlSet\\Control\\Keyboard Layouts\\%s"), szLCID);
|
||||
StringCchPrintf(szBuf, ARRAYSIZE(szBuf), _T("SYSTEM\\CurrentControlSet\\Control\\Keyboard Layouts\\%s"), szLCID);
|
||||
|
||||
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, (LPCTSTR)szBuf, 0, KEY_QUERY_VALUE, &hKey) == ERROR_SUCCESS)
|
||||
{
|
||||
dwBufLen = sizeof(szBuf);
|
||||
dwBufLen = sizeof(szDispName);
|
||||
|
||||
if (RegQueryValueEx(hKey, _T("Layout Display Name"), NULL, NULL, (LPBYTE)szDispName, &dwBufLen) == ERROR_SUCCESS)
|
||||
{
|
||||
if (szDispName[0] == '@')
|
||||
{
|
||||
for (i = 0; i < _tcslen(szDispName); i++)
|
||||
size_t len = _tcslen(szDispName);
|
||||
|
||||
for (i = 0; i < len; i++)
|
||||
{
|
||||
if ((szDispName[i] == ',') && (szDispName[i + 1] == '-'))
|
||||
{
|
||||
|
@ -239,14 +244,14 @@ GetLayoutName(LPTSTR szLayoutNum, LPTSTR szName)
|
|||
else szDispName[i] = szDispName[i + 1];
|
||||
}
|
||||
|
||||
if (ExpandEnvironmentStrings(szDispName, szPath, MAX_PATH))
|
||||
if (ExpandEnvironmentStrings(szDispName, szPath, ARRAYSIZE(szPath)))
|
||||
{
|
||||
hLib = LoadLibrary(szPath);
|
||||
if (hLib)
|
||||
{
|
||||
if (LoadString(hLib, _ttoi(szIndex), szPath, sizeof(szPath) / sizeof(TCHAR)) != 0)
|
||||
if (LoadString(hLib, _ttoi(szIndex), szPath, ARRAYSIZE(szPath)) != 0)
|
||||
{
|
||||
_tcscpy(szName, szPath);
|
||||
StringCchCopy(szName, NameLength, szPath);
|
||||
RegCloseKey(hKey);
|
||||
FreeLibrary(hLib);
|
||||
return TRUE;
|
||||
|
@ -257,7 +262,7 @@ GetLayoutName(LPTSTR szLayoutNum, LPTSTR szName)
|
|||
}
|
||||
}
|
||||
|
||||
dwBufLen = sizeof(szBuf);
|
||||
dwBufLen = NameLength * sizeof(TCHAR);
|
||||
|
||||
if (RegQueryValueEx(hKey, _T("Layout Text"), NULL, NULL, (LPBYTE)szName, &dwBufLen) == ERROR_SUCCESS)
|
||||
{
|
||||
|
@ -287,10 +292,10 @@ ActivateLayout(HWND hwnd, ULONG uLayoutNum)
|
|||
TCHAR szLangName[MAX_PATH];
|
||||
|
||||
_ultot(uLayoutNum, szLayoutNum, 10);
|
||||
GetLayoutID(szLayoutNum, szLCID);
|
||||
GetLayoutID(szLayoutNum, szLCID, ARRAYSIZE(szLCID));
|
||||
|
||||
// Switch to the new keyboard layout
|
||||
GetLocaleInfo((LANGID)_tcstoul(szLCID, NULL, 16), LOCALE_SLANGUAGE, (LPTSTR)szLangName, sizeof(szLangName) / sizeof(TCHAR));
|
||||
GetLocaleInfo((LANGID)_tcstoul(szLCID, NULL, 16), LOCALE_SLANGUAGE, (LPTSTR)szLangName, ARRAYSIZE(szLangName));
|
||||
UpdateTrayIcon(hwnd, szLCID, szLangName);
|
||||
hKl = LoadKeyboardLayout(szLCID, KLF_ACTIVATE);
|
||||
|
||||
|
@ -313,19 +318,19 @@ BuildLeftPopupMenu(VOID)
|
|||
// Add the keyboard layouts to the popup menu
|
||||
if (RegOpenKeyEx(HKEY_CURRENT_USER, _T("Keyboard Layout\\Preload"), 0, KEY_QUERY_VALUE, &hKey) == ERROR_SUCCESS)
|
||||
{
|
||||
for(dwIndex = 0; ; dwIndex++)
|
||||
for (dwIndex = 0; ; dwIndex++)
|
||||
{
|
||||
dwSize = sizeof(szLayoutNum);
|
||||
if(RegEnumValue(hKey, dwIndex, szLayoutNum, &dwSize, NULL, NULL, NULL, NULL) != ERROR_SUCCESS)
|
||||
if (RegEnumValue(hKey, dwIndex, szLayoutNum, &dwSize, NULL, NULL, NULL, NULL) != ERROR_SUCCESS)
|
||||
break;
|
||||
|
||||
if(!GetLayoutName(szLayoutNum, szName))
|
||||
if (!GetLayoutName(szLayoutNum, szName, ARRAYSIZE(szName)))
|
||||
break;
|
||||
|
||||
AppendMenu(hMenu, MF_STRING, _ttoi(szLayoutNum), szName);
|
||||
}
|
||||
|
||||
(void)CheckMenuItem(hMenu, ulCurrentLayoutNum, MF_CHECKED);
|
||||
CheckMenuItem(hMenu, ulCurrentLayoutNum, MF_CHECKED);
|
||||
|
||||
RegCloseKey(hKey);
|
||||
}
|
||||
|
@ -337,13 +342,18 @@ BOOL
|
|||
SetHooks(VOID)
|
||||
{
|
||||
hDllLib = LoadLibrary(_T("kbsdll.dll"));
|
||||
if (!hDllLib) return FALSE;
|
||||
|
||||
KbSwitchSetHooks = (PROC) GetProcAddress(hDllLib, MAKEINTRESOURCEA(1));
|
||||
KbSwitchDeleteHooks = (PROC) GetProcAddress(hDllLib, MAKEINTRESOURCEA(2));
|
||||
|
||||
if ((KbSwitchSetHooks == NULL)||(KbSwitchDeleteHooks == NULL))
|
||||
if (!hDllLib)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
KbSwitchSetHooks = (PKBSWITCHSETHOOKS) GetProcAddress(hDllLib, "KbSwitchSetHooks");
|
||||
KbSwitchDeleteHooks = (PKBSWITCHDELETEHOOKS) GetProcAddress(hDllLib, "KbSwitchDeleteHooks");
|
||||
|
||||
if (KbSwitchSetHooks == NULL || KbSwitchDeleteHooks == NULL)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return KbSwitchSetHooks();
|
||||
}
|
||||
|
@ -362,21 +372,21 @@ GetNextLayout(VOID)
|
|||
ULONG Ret = ulCurrentLayoutNum;
|
||||
|
||||
_ultot(ulCurrentLayoutNum, szLayoutNum, 10);
|
||||
if (!GetLayoutID(szLayoutNum, szLayoutID))
|
||||
if (!GetLayoutID(szLayoutNum, szLayoutID, ARRAYSIZE(szLayoutID)))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
_ultot(Ret + 1, szLayoutNum, 10);
|
||||
|
||||
if (GetLayoutID(szLayoutNum, szLayoutID))
|
||||
if (GetLayoutID(szLayoutNum, szLayoutID, ARRAYSIZE(szLayoutID)))
|
||||
{
|
||||
return (Ret + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
_ultot(Ret - 1, szLayoutNum, 10);
|
||||
if (GetLayoutID(szLayoutNum, szLayoutID))
|
||||
if (GetLayoutID(szLayoutNum, szLayoutID, ARRAYSIZE(szLayoutID)))
|
||||
return (Ret - 1);
|
||||
else
|
||||
return -1;
|
||||
|
@ -408,8 +418,8 @@ WndProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam)
|
|||
|
||||
case WM_LANG_CHANGED:
|
||||
{
|
||||
GetLayoutIDByHkl((HKL)lParam, szLCID);
|
||||
GetLocaleInfo((LANGID)_tcstoul(szLCID, NULL, 16), LOCALE_SLANGUAGE, (LPTSTR)szLangName, sizeof(szLangName) / sizeof(TCHAR));
|
||||
GetLayoutIDByHkl((HKL)lParam, szLCID, ARRAYSIZE(szLCID));
|
||||
GetLocaleInfo((LANGID)_tcstoul(szLCID, NULL, 16), LOCALE_SLANGUAGE, (LPTSTR)szLangName, ARRAYSIZE(szLangName));
|
||||
UpdateTrayIcon(hwnd, szLCID, szLangName);
|
||||
|
||||
return 0;
|
||||
|
@ -424,8 +434,8 @@ WndProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam)
|
|||
|
||||
case WM_WINDOW_ACTIVATE:
|
||||
{
|
||||
GetLayoutIDByHkl(GetKeyboardLayout(GetWindowThreadProcessId((HWND)wParam, 0)), szLCID);
|
||||
GetLocaleInfo((LANGID)_tcstoul(szLCID, NULL, 16), LOCALE_SLANGUAGE, (LPTSTR)szLangName, sizeof(szLangName) / sizeof(TCHAR));
|
||||
GetLayoutIDByHkl(GetKeyboardLayout(GetWindowThreadProcessId((HWND)wParam, 0)), szLCID, ARRAYSIZE(szLCID));
|
||||
GetLocaleInfo((LANGID)_tcstoul(szLCID, NULL, 16), LOCALE_SLANGUAGE, (LPTSTR)szLangName, ARRAYSIZE(szLangName));
|
||||
UpdateTrayIcon(hwnd, szLCID, szLangName);
|
||||
|
||||
return 0;
|
||||
|
@ -526,11 +536,11 @@ _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInst, LPTSTR lpCmdLine, INT nCmdSh
|
|||
|
||||
switch (GetUserDefaultUILanguage())
|
||||
{
|
||||
case MAKELANGID(LANG_HEBREW, SUBLANG_DEFAULT):
|
||||
SetProcessDefaultLayout(LAYOUT_RTL);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
case MAKELANGID(LANG_HEBREW, SUBLANG_DEFAULT):
|
||||
SetProcessDefaultLayout(LAYOUT_RTL);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
hMutex = CreateMutex(NULL, FALSE, szKbSwitcherName);
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
#pragma once
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <windef.h>
|
||||
#include <winbase.h>
|
||||
|
@ -7,6 +9,7 @@
|
|||
#include <wingdi.h>
|
||||
#include <shellapi.h>
|
||||
#include <tchar.h>
|
||||
#include <strsafe.h>
|
||||
|
||||
#include "resource.h"
|
||||
|
||||
|
@ -21,4 +24,7 @@
|
|||
#define WM_WINDOW_ACTIVATE (WM_USER + 10300)
|
||||
#define WM_LOAD_LAYOUT (WM_USER + 10400)
|
||||
|
||||
typedef BOOL (WINAPI *PKBSWITCHSETHOOKS) (VOID);
|
||||
typedef VOID (WINAPI *PKBSWITCHDELETEHOOKS) (VOID);
|
||||
|
||||
TCHAR szKbSwitcherName[] = _T("kbswitcher");
|
||||
|
|
Loading…
Reference in a new issue