ReactOS  0.4.12-dev-36-g472787f
kbswitch.c File Reference
#include "kbswitch.h"
Include dependency graph for kbswitch.c:

Go to the source code of this file.

Macros

#define WM_NOTIFYICONMSG   (WM_USER + 248)
 

Functions

static BOOL GetLayoutID (LPTSTR szLayoutNum, LPTSTR szLCID, SIZE_T LCIDLength)
 
static BOOL GetLayoutName (LPTSTR szLayoutNum, LPTSTR szName, SIZE_T NameLength)
 
static HICON CreateTrayIcon (LPTSTR szLCID)
 
static VOID AddTrayIcon (HWND hwnd)
 
static VOID DelTrayIcon (HWND hwnd)
 
static VOID UpdateTrayIcon (HWND hwnd, LPTSTR szLCID, LPTSTR szName)
 
VOID GetLayoutIDByHkl (HKL hKl, LPTSTR szLayoutID, SIZE_T LayoutIDLength)
 
BOOL CALLBACK EnumWindowsProc (HWND hwnd, LPARAM lParam)
 
static VOID ActivateLayout (HWND hwnd, ULONG uLayoutNum)
 
static HMENU BuildLeftPopupMenu (VOID)
 
BOOL SetHooks (VOID)
 
VOID DeleteHooks (VOID)
 
ULONG GetNextLayout (VOID)
 
LRESULT UpdateLanguageDisplay (HWND hwnd, HKL hKl)
 
LRESULT UpdateLanguageDisplayCurrent (HWND hwnd, WPARAM wParam)
 
LRESULT CALLBACK WndProc (HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam)
 
INT WINAPI _tWinMain (HINSTANCE hInstance, HINSTANCE hPrevInst, LPTSTR lpCmdLine, INT nCmdShow)
 

Variables

PKBSWITCHSETHOOKS KbSwitchSetHooks = NULL
 
PKBSWITCHDELETEHOOKS KbSwitchDeleteHooks = NULL
 
UINT ShellHookMessage = 0
 
HINSTANCE hInst
 
HANDLE hProcessHeap
 
HMODULE hDllLib
 
ULONG ulCurrentLayoutNum = 1
 

Macro Definition Documentation

◆ WM_NOTIFYICONMSG

#define WM_NOTIFYICONMSG   (WM_USER + 248)

Definition at line 11 of file kbswitch.c.

Referenced by AddTrayIcon(), UpdateTrayIcon(), and WndProc().

Function Documentation

◆ _tWinMain()

INT WINAPI _tWinMain ( HINSTANCE  hInstance,
HINSTANCE  hPrevInst,
LPTSTR  lpCmdLine,
INT  nCmdShow 
)

Definition at line 553 of file kbswitch.c.

554 {
555  WNDCLASS WndClass = {0};
556  MSG msg;
557  HANDLE hMutex;
558  HWND hwnd;
559 
560  switch (GetUserDefaultUILanguage())
561  {
564  break;
565  default:
566  break;
567  }
568 
570  if (!hMutex)
571  return 1;
572 
574  {
575  CloseHandle(hMutex);
576  return 1;
577  }
578 
579  hInst = hInstance;
581 
582  WndClass.style = 0;
583  WndClass.lpfnWndProc = WndProc;
584  WndClass.cbClsExtra = 0;
585  WndClass.cbWndExtra = 0;
586  WndClass.hInstance = hInstance;
587  WndClass.hIcon = NULL;
588  WndClass.hCursor = NULL;
589  WndClass.hbrBackground = NULL;
590  WndClass.lpszMenuName = NULL;
591  WndClass.lpszClassName = szKbSwitcherName;
592 
593  if (!RegisterClass(&WndClass))
594  {
595  CloseHandle(hMutex);
596  return 1;
597  }
598 
599  hwnd = CreateWindow(szKbSwitcherName, NULL, 0, 0, 0, 1, 1, HWND_DESKTOP, NULL, hInstance, NULL);
602 
603  while(GetMessage(&msg,NULL,0,0))
604  {
605  TranslateMessage(&msg);
606  DispatchMessage(&msg);
607  }
608 
609  CloseHandle(hMutex);
610 
611  return 0;
612 }
const DOCKBAR PVOID HWND HWND * hwnd
Definition: tooldock.h:22
#define DispatchMessage
Definition: winuser.h:5631
LANGID WINAPI GetUserDefaultUILanguage(void)
Definition: lang.c:561
BOOL WINAPI TranslateMessage(_In_ const MSG *)
#define CloseHandle
Definition: compat.h:398
#define LAYOUT_RTL
Definition: wingdi.h:1352
#define CreateWindow
Definition: winuser.h:5620
TW_UINT32 TW_UINT16 TW_UINT16 MSG
Definition: twain.h:1827
#define SUBLANG_DEFAULT
Definition: nls.h:168
int cbClsExtra
Definition: winuser.h:3118
DWORD WINAPI GetLastError(VOID)
Definition: except.c:1059
LPCSTR lpszMenuName
Definition: winuser.h:3124
LRESULT CALLBACK WndProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam)
Definition: kbswitch.c:418
HBRUSH hbrBackground
Definition: winuser.h:3123
#define LANG_HEBREW
Definition: nls.h:67
int cbWndExtra
Definition: winuser.h:3119
HINSTANCE hInstance
Definition: charmap.c:20
HCURSOR hCursor
Definition: winuser.h:3122
smooth NULL
Definition: ftsmooth.c:416
HANDLE hMutex
Definition: mutex.c:11
HINSTANCE hInst
Definition: kbswitch.c:24
BOOL WINAPI SetProcessDefaultLayout(DWORD dwDefaultLayout)
Definition: window.c:1686
#define GetProcessHeap()
Definition: compat.h:395
#define CreateMutex
Definition: winbase.h:3570
static const WCHAR L[]
Definition: oid.c:1087
BOOL WINAPI RegisterShellHookWindow(_In_ HWND)
LPCSTR lpszClassName
Definition: winuser.h:3125
UINT style
Definition: winuser.h:3116
#define RegisterWindowMessage
Definition: winuser.h:5706
UINT ShellHookMessage
Definition: kbswitch.c:15
TCHAR szKbSwitcherName[]
Definition: kbswitch.h:30
HINSTANCE hInstance
Definition: winuser.h:3120
#define HWND_DESKTOP
Definition: winuser.h:1195
#define GetMessage
Definition: winuser.h:5656
WNDPROC lpfnWndProc
Definition: winuser.h:3117
#define msg(x)
Definition: auth_time.c:54
#define MAKELANGID(p, s)
Definition: nls.h:15
#define RegisterClass
Definition: winuser.h:5702
#define ERROR_ALREADY_EXISTS
Definition: disk.h:80
WCHAR WndClass[]
Definition: capicon.c:23
HANDLE hProcessHeap
Definition: kbswitch.c:25
HICON hIcon
Definition: winuser.h:3121

◆ ActivateLayout()

static VOID ActivateLayout ( HWND  hwnd,
ULONG  uLayoutNum 
)
static

Definition at line 288 of file kbswitch.c.

Referenced by WndProc().

289 {
290  HKL hKl;
291  TCHAR szLayoutNum[CCH_ULONG_DEC + 1];
292  TCHAR szLCID[CCH_LAYOUT_ID + 1];
293  TCHAR szLangName[MAX_PATH];
294 
295  _ultot(uLayoutNum, szLayoutNum, 10);
296  GetLayoutID(szLayoutNum, szLCID, ARRAYSIZE(szLCID));
297 
298  // Switch to the new keyboard layout
299  GetLocaleInfo((LANGID)_tcstoul(szLCID, NULL, 16), LOCALE_SLANGUAGE, (LPTSTR)szLangName, ARRAYSIZE(szLangName));
300  UpdateTrayIcon(hwnd, szLCID, szLangName);
301  hKl = LoadKeyboardLayout(szLCID, KLF_ACTIVATE);
302 
304 
305  ulCurrentLayoutNum = uLayoutNum;
306 }
#define CCH_LAYOUT_ID
Definition: kbswitch.h:17
#define LOCALE_SLANGUAGE
Definition: winnls.h:26
BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam)
Definition: kbswitch.c:281
#define KLF_ACTIVATE
Definition: winuser.h:111
#define GetLocaleInfo
Definition: winnls.h:1154
#define ARRAYSIZE(array)
Definition: filtermapper.c:47
WORD LANGID
Definition: typedefs.h:79
CHAR * LPTSTR
Definition: xmlstorage.h:192
#define LoadKeyboardLayout
Definition: winuser.h:5682
#define CCH_ULONG_DEC
Definition: kbswitch.h:20
LONG_PTR LPARAM
Definition: windef.h:208
smooth NULL
Definition: ftsmooth.c:416
char TCHAR
Definition: xmlstorage.h:189
static VOID UpdateTrayIcon(HWND hwnd, LPTSTR szLCID, LPTSTR szName)
Definition: kbswitch.c:137
#define MAX_PATH
Definition: compat.h:26
BOOL WINAPI EnumWindows(_In_ WNDENUMPROC, _In_ LPARAM)
static BOOL GetLayoutID(LPTSTR szLayoutNum, LPTSTR szLCID, SIZE_T LCIDLength)
Definition: kbswitch.c:155
#define _tcstoul
Definition: tchar.h:595
UINT_PTR HKL
Definition: msctf.idl:101
ULONG ulCurrentLayoutNum
Definition: kbswitch.c:27
#define _ultot
Definition: tchar.h:610

◆ AddTrayIcon()

static VOID AddTrayIcon ( HWND  hwnd)
static

Definition at line 101 of file kbswitch.c.

Referenced by WndProc().

102 {
103  NOTIFYICONDATA tnid;
104  TCHAR szLCID[CCH_LAYOUT_ID + 1];
106 
107  GetLayoutID(_T("1"), szLCID, ARRAYSIZE(szLCID));
108  GetLayoutName(_T("1"), szName, ARRAYSIZE(szName));
109 
110  memset(&tnid, 0, sizeof(tnid));
111  tnid.cbSize = sizeof(NOTIFYICONDATA);
112  tnid.hWnd = hwnd;
113  tnid.uID = 1;
114  tnid.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP;
116  tnid.hIcon = CreateTrayIcon(szLCID);
117 
118  StringCchCopy(tnid.szTip, ARRAYSIZE(tnid.szTip), szName);
119 
120  Shell_NotifyIcon(NIM_ADD, &tnid);
121 }
static HICON CreateTrayIcon(LPTSTR szLCID)
Definition: kbswitch.c:30
const DOCKBAR PVOID HWND HWND * hwnd
Definition: tooldock.h:22
#define NIF_MESSAGE
Definition: shellapi.h:102
#define CCH_LAYOUT_ID
Definition: kbswitch.h:17
#define ARRAYSIZE(array)
Definition: filtermapper.c:47
#define WM_NOTIFYICONMSG
Definition: kbswitch.c:11
CHAR szTip[128]
Definition: shellapi.h:233
#define NIF_TIP
Definition: shellapi.h:104
NOTIFYICONDATAA NOTIFYICONDATA
Definition: shellapi.h:665
#define NIF_ICON
Definition: shellapi.h:103
char TCHAR
Definition: xmlstorage.h:189
#define _T(x)
Definition: vfdio.h:22
static BOOL GetLayoutName(LPTSTR szLayoutNum, LPTSTR szName, SIZE_T NameLength)
Definition: kbswitch.c:210
#define MAX_PATH
Definition: compat.h:26
static BOOL GetLayoutID(LPTSTR szLayoutNum, LPTSTR szLCID, SIZE_T LCIDLength)
Definition: kbswitch.c:155
#define StringCchCopy
Definition: strsafe.h:139
UINT uCallbackMessage
Definition: shellapi.h:227
#define NIM_ADD
Definition: shellapi.h:91
static const WCHAR szName[]
Definition: msipriv.h:1194
#define Shell_NotifyIcon
Definition: shellapi.h:677
#define memset(x, y, z)
Definition: compat.h:39

◆ BuildLeftPopupMenu()

static HMENU BuildLeftPopupMenu ( VOID  )
static

Definition at line 309 of file kbswitch.c.

Referenced by WndProc().

310 {
311  HMENU hMenu;
312  HKEY hKey;
313  DWORD dwIndex, dwSize;
314  TCHAR szLayoutNum[CCH_ULONG_DEC + 1];
316 
317  hMenu = CreatePopupMenu();
318 
319  // Add the keyboard layouts to the popup menu
320  if (RegOpenKeyEx(HKEY_CURRENT_USER, _T("Keyboard Layout\\Preload"), 0, KEY_QUERY_VALUE, &hKey) == ERROR_SUCCESS)
321  {
322  for (dwIndex = 0; ; dwIndex++)
323  {
324  dwSize = sizeof(szLayoutNum);
325  if (RegEnumValue(hKey, dwIndex, szLayoutNum, &dwSize, NULL, NULL, NULL, NULL) != ERROR_SUCCESS)
326  break;
327 
328  if (!GetLayoutName(szLayoutNum, szName, ARRAYSIZE(szName)))
329  break;
330 
331  AppendMenu(hMenu, MF_STRING, _ttoi(szLayoutNum), szName);
332  }
333 
335 
336  RegCloseKey(hKey);
337  }
338 
339  return hMenu;
340 }
#define ERROR_SUCCESS
Definition: deptool.c:10
#define HKEY_CURRENT_USER
Definition: winreg.h:11
#define MF_STRING
Definition: winuser.h:138
#define ARRAYSIZE(array)
Definition: filtermapper.c:47
#define CCH_ULONG_DEC
Definition: kbswitch.h:20
LONG WINAPI RegCloseKey(HKEY hKey)
Definition: reg.c:423
smooth NULL
Definition: ftsmooth.c:416
#define MF_CHECKED
Definition: winuser.h:132
char TCHAR
Definition: xmlstorage.h:189
#define _T(x)
Definition: vfdio.h:22
#define AppendMenu
Definition: winuser.h:5597
static BOOL GetLayoutName(LPTSTR szLayoutNum, LPTSTR szName, SIZE_T NameLength)
Definition: kbswitch.c:210
#define MAX_PATH
Definition: compat.h:26
unsigned long DWORD
Definition: ntddk_ex.h:95
DWORD WINAPI CheckMenuItem(_In_ HMENU, _In_ UINT, _In_ UINT)
ULONG ulCurrentLayoutNum
Definition: kbswitch.c:27
#define RegOpenKeyEx
Definition: winreg.h:520
#define KEY_QUERY_VALUE
Definition: nt_native.h:1016
int CDECL _ttoi(const _TCHAR *str)
Definition: atoi.c:10
HMENU WINAPI CreatePopupMenu(void)
Definition: menu.c:846
static const WCHAR szName[]
Definition: msipriv.h:1194
LONG RegEnumValue(HKEY Key, ULONG Index, PWCHAR ValueName, ULONG *NameSize, ULONG *Type, PUCHAR Data, ULONG *DataSize)
static const CLSID *static CLSID *static const GUID VARIANT VARIANT *static IServiceProvider DWORD *static HMENU
Definition: ordinal.c:60
PSDBQUERYRESULT_VISTA PVOID DWORD * dwSize
Definition: env.c:54

◆ CreateTrayIcon()

static HICON CreateTrayIcon ( LPTSTR  szLCID)
static

Definition at line 30 of file kbswitch.c.

Referenced by AddTrayIcon(), and UpdateTrayIcon().

31 {
32  LANGID lId;
33  TCHAR szBuf[3];
34  HDC hdc, hdcsrc;
35  HBITMAP hBitmap, hBmpNew, hBmpOld;
36  RECT rect;
37  HFONT hFontOld, hFont = NULL;
39  HICON hIcon = NULL;
40 
41  lId = (LANGID)_tcstoul(szLCID, NULL, 16);
42  if (GetLocaleInfo(lId,
44  szBuf,
45  ARRAYSIZE(szBuf)) == 0)
46  {
47  StringCchCopy(szBuf, ARRAYSIZE(szBuf), _T("??"));
48  }
49 
50  hdcsrc = GetDC(NULL);
51  hdc = CreateCompatibleDC(hdcsrc);
52  hBitmap = CreateCompatibleBitmap(hdcsrc, 16, 16);
53  ReleaseDC(NULL, hdcsrc);
54 
55  if (hdc && hBitmap)
56  {
57  hBmpNew = CreateBitmap(16, 16, 1, 1, NULL);
58  if (hBmpNew)
59  {
60  hBmpOld = SelectObject(hdc, hBitmap);
61  rect.right = 16;
62  rect.left = 0;
63  rect.bottom = 16;
64  rect.top = 0;
65 
68 
69  ExtTextOut(hdc, rect.left, rect.top, ETO_OPAQUE, &rect, _T(""), 0, NULL);
70 
71  hFont = CreateFont(-11, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
73  DEFAULT_QUALITY, FF_DONTCARE, _T("Tahoma"));
74 
75  hFontOld = SelectObject(hdc, hFont);
76  DrawText(hdc, _tcsupr(szBuf), 2, &rect, DT_SINGLELINE|DT_CENTER|DT_VCENTER);
77  SelectObject(hdc, hBmpNew);
78  PatBlt(hdc, 0, 0, 16, 16, BLACKNESS);
79  SelectObject(hdc, hBmpOld);
80  SelectObject(hdc, hFontOld);
81 
82  IconInfo.hbmColor = hBitmap;
83  IconInfo.hbmMask = hBmpNew;
84  IconInfo.fIcon = TRUE;
85 
86  hIcon = CreateIconIndirect(&IconInfo);
87 
88  DeleteObject(hBmpNew);
89  DeleteObject(hBmpOld);
90  DeleteObject(hFont);
91  }
92  }
93 
94  DeleteDC(hdc);
95  DeleteObject(hBitmap);
96 
97  return hIcon;
98 }
#define HDC
Definition: msvc.h:22
static HICON
Definition: imagelist.c:84
#define TRUE
Definition: types.h:120
#define COLOR_HIGHLIGHT
Definition: winuser.h:916
#define HBITMAP
Definition: msvc.h:28
#define DEFAULT_QUALITY
Definition: wingdi.h:434
#define LOCALE_SISO639LANGNAME
Definition: winnls.h:127
#define FF_DONTCARE
Definition: wingdi.h:446
HDC WINAPI GetDC(_In_opt_ HWND)
HBITMAP WINAPI CreateCompatibleBitmap(_In_ HDC hdc, _In_ INT cx, _In_ INT cy)
#define GetLocaleInfo
Definition: winnls.h:1154
LONG top
Definition: windef.h:297
#define ARRAYSIZE(array)
Definition: filtermapper.c:47
HGDIOBJ WINAPI SelectObject(_In_ HDC, _In_ HGDIOBJ)
Definition: dc.c:1497
BOOL WINAPI DeleteObject(_In_ HGDIOBJ)
HDC WINAPI CreateCompatibleDC(_In_opt_ HDC hdc)
WORD LANGID
Definition: typedefs.h:79
LONG left
Definition: windef.h:296
LONG right
Definition: windef.h:298
DWORD WINAPI GetSysColor(_In_ int)
& rect
Definition: startmenu.cpp:1413
HFONT hFont
Definition: main.c:53
#define DrawText
Definition: winuser.h:5637
COLORREF WINAPI SetBkColor(_In_ HDC, _In_ COLORREF)
Definition: dc.c:975
BOOL WINAPI PatBlt(_In_ HDC, _In_ int, _In_ int, _In_ int, _In_ int, _In_ DWORD)
#define ETO_OPAQUE
Definition: wingdi.h:645
HBITMAP hbmMask
Definition: winuser.h:3079
#define CLIP_DEFAULT_PRECIS
Definition: wingdi.h:424
int WINAPI ReleaseDC(_In_opt_ HWND, _In_ HDC)
#define CreateFont
Definition: wingdi.h:4420
HDC hdc
Definition: msvc.h:53
smooth NULL
Definition: ftsmooth.c:416
HBITMAP hbmColor
Definition: winuser.h:3080
#define DT_VCENTER
Definition: winuser.h:543
#define COLOR_HIGHLIGHTTEXT
Definition: winuser.h:917
char TCHAR
Definition: xmlstorage.h:189
BOOL fIcon
Definition: winuser.h:3076
#define _T(x)
Definition: vfdio.h:22
HICON WINAPI CreateIconIndirect(_In_ PICONINFO)
Definition: cursoricon.c:2546
#define OUT_DEFAULT_PRECIS
Definition: wingdi.h:413
#define ExtTextOut
Definition: wingdi.h:4431
#define _tcstoul
Definition: tchar.h:595
#define StringCchCopy
Definition: strsafe.h:139
#define _tcsupr
Definition: tchar.h:1467
COLORREF WINAPI SetTextColor(_In_ HDC, _In_ COLORREF)
Definition: text.c:784
#define DT_SINGLELINE
Definition: winuser.h:540
#define BLACKNESS
Definition: wingdi.h:321
BOOL WINAPI DeleteDC(_In_ HDC)
HICON hIcon
Definition: msconfig.c:44
#define FW_NORMAL
Definition: wingdi.h:371
static DWORD *static HFONT(WINAPI *pCreateFontIndirectExA)(const ENUMLOGFONTEXDVA *)
LONG bottom
Definition: windef.h:299
#define DT_CENTER
Definition: winuser.h:527
#define ANSI_CHARSET
Definition: wingdi.h:381
_Out_opt_ PICONINFO IconInfo
Definition: ntuser.h:2267
static HBITMAP hBitmap
Definition: timezone.c:34
HBITMAP WINAPI CreateBitmap(_In_ INT cx, _In_ INT cy, _In_ UINT cPlanes, _In_ UINT cBitsPerPel, _In_opt_ const VOID *pvBits)

◆ DeleteHooks()

VOID DeleteHooks ( VOID  )

Definition at line 363 of file kbswitch.c.

Referenced by WndProc().

364 {
367 }
PKBSWITCHDELETEHOOKS KbSwitchDeleteHooks
Definition: kbswitch.c:14
#define FreeLibrary(x)
Definition: compat.h:405
HMODULE hDllLib
Definition: kbswitch.c:26

◆ DelTrayIcon()

static VOID DelTrayIcon ( HWND  hwnd)
static

Definition at line 124 of file kbswitch.c.

Referenced by WndProc().

125 {
126  NOTIFYICONDATA tnid;
127 
128  memset(&tnid, 0, sizeof(tnid));
129  tnid.cbSize = sizeof(NOTIFYICONDATA);
130  tnid.hWnd = hwnd;
131  tnid.uID = 1;
132 
134 }
const DOCKBAR PVOID HWND HWND * hwnd
Definition: tooldock.h:22
NOTIFYICONDATAA NOTIFYICONDATA
Definition: shellapi.h:665
#define NIM_DELETE
Definition: shellapi.h:93
#define Shell_NotifyIcon
Definition: shellapi.h:677
#define memset(x, y, z)
Definition: compat.h:39

◆ EnumWindowsProc()

BOOL CALLBACK EnumWindowsProc ( HWND  hwnd,
LPARAM  lParam 
)

Definition at line 281 of file kbswitch.c.

Referenced by ActivateLayout().

282 {
283  PostMessage(hwnd, WM_INPUTLANGCHANGEREQUEST, 0, lParam);
284  return TRUE;
285 }
#define TRUE
Definition: types.h:120
#define PostMessage
Definition: winuser.h:5698
LPARAM lParam
Definition: combotst.c:139

◆ GetLayoutID()

static BOOL GetLayoutID ( LPTSTR  szLayoutNum,
LPTSTR  szLCID,
SIZE_T  LCIDLength 
)
static

Definition at line 155 of file kbswitch.c.

Referenced by ActivateLayout(), AddTrayIcon(), GetLayoutName(), and GetNextLayout().

156 {
157  DWORD dwBufLen;
158  DWORD dwRes;
159  HKEY hKey;
160  TCHAR szTempLCID[CCH_LAYOUT_ID + 1];
161 
162  // Get the Layout ID
163  if (RegOpenKeyEx(HKEY_CURRENT_USER, _T("Keyboard Layout\\Preload"), 0, KEY_QUERY_VALUE, &hKey) == ERROR_SUCCESS)
164  {
165  dwBufLen = sizeof(szTempLCID);
166  dwRes = RegQueryValueEx(hKey, szLayoutNum, NULL, NULL, (LPBYTE)szTempLCID, &dwBufLen);
167 
168  if (dwRes != ERROR_SUCCESS)
169  {
170  RegCloseKey(hKey);
171  return FALSE;
172  }
173 
174  RegCloseKey(hKey);
175  }
176 
177  // Look for a substitute of this layout
178  if (RegOpenKeyEx(HKEY_CURRENT_USER, _T("Keyboard Layout\\Substitutes"), 0, KEY_QUERY_VALUE, &hKey) == ERROR_SUCCESS)
179  {
180  dwBufLen = sizeof(szTempLCID);
181 
182  if (RegQueryValueEx(hKey, szTempLCID, NULL, NULL, (LPBYTE)szLCID, &dwBufLen) != ERROR_SUCCESS)
183  {
184  // No substitute found, then use the old LCID
185  StringCchCopy(szLCID, LCIDLength, szTempLCID);
186  }
187 
188  RegCloseKey(hKey);
189  }
190  else
191  {
192  // Substitutes key couldn't be opened, so use the old LCID
193  StringCchCopy(szLCID, LCIDLength, szTempLCID);
194  }
195 
196  return TRUE;
197 }
#define RegQueryValueEx
Definition: winreg.h:524
#define TRUE
Definition: types.h:120
#define ERROR_SUCCESS
Definition: deptool.c:10
#define CCH_LAYOUT_ID
Definition: kbswitch.h:17
#define HKEY_CURRENT_USER
Definition: winreg.h:11
_In_ HCRYPTHASH _In_ BOOL _In_ DWORD _Inout_ DWORD _In_ DWORD dwBufLen
Definition: wincrypt.h:4243
LONG WINAPI RegCloseKey(HKEY hKey)
Definition: reg.c:423
unsigned char * LPBYTE
Definition: typedefs.h:52
smooth NULL
Definition: ftsmooth.c:416
char TCHAR
Definition: xmlstorage.h:189
#define _T(x)
Definition: vfdio.h:22
unsigned long DWORD
Definition: ntddk_ex.h:95
#define StringCchCopy
Definition: strsafe.h:139
#define RegOpenKeyEx
Definition: winreg.h:520
#define KEY_QUERY_VALUE
Definition: nt_native.h:1016

◆ GetLayoutIDByHkl()

VOID GetLayoutIDByHkl ( HKL  hKl,
LPTSTR  szLayoutID,
SIZE_T  LayoutIDLength 
)

Definition at line 200 of file kbswitch.c.

Referenced by UpdateLanguageDisplay().

201 {
202  /*
203  FIXME!!! This way of getting layout ID incorrect!
204  This will not work correctly for 0001040a, 00010410, etc
205  */
206  StringCchPrintf(szLayoutID, LayoutIDLength, _T("%08x"), LOWORD(hKl));
207 }
#define StringCchPrintf
Definition: strsafe.h:517
#define _T(x)
Definition: vfdio.h:22
#define LOWORD(l)
Definition: pedump.c:82

◆ GetLayoutName()

static BOOL GetLayoutName ( LPTSTR  szLayoutNum,
LPTSTR  szName,
SIZE_T  NameLength 
)
static

Definition at line 210 of file kbswitch.c.

Referenced by AddTrayIcon(), and BuildLeftPopupMenu().

211 {
212  HKEY hKey;
213  DWORD dwBufLen;
214  TCHAR szBuf[MAX_PATH], szDispName[MAX_PATH], szIndex[MAX_PATH], szPath[MAX_PATH];
215  TCHAR szLCID[CCH_LAYOUT_ID + 1];
216  HANDLE hLib;
217  UINT i, j, k;
218 
219  if (!GetLayoutID(szLayoutNum, szLCID, ARRAYSIZE(szLCID)))
220  return FALSE;
221 
222  StringCchPrintf(szBuf, ARRAYSIZE(szBuf), _T("SYSTEM\\CurrentControlSet\\Control\\Keyboard Layouts\\%s"), szLCID);
223 
225  {
226  dwBufLen = sizeof(szDispName);
227 
228  if (RegQueryValueEx(hKey, _T("Layout Display Name"), NULL, NULL, (LPBYTE)szDispName, &dwBufLen) == ERROR_SUCCESS)
229  {
230  if (szDispName[0] == '@')
231  {
232  size_t len = _tcslen(szDispName);
233 
234  for (i = 0; i < len; i++)
235  {
236  if ((szDispName[i] == ',') && (szDispName[i + 1] == '-'))
237  {
238  for (j = i + 2, k = 0; j < _tcslen(szDispName)+1; j++, k++)
239  {
240  szIndex[k] = szDispName[j];
241  }
242  szDispName[i - 1] = '\0';
243  break;
244  }
245  else szDispName[i] = szDispName[i + 1];
246  }
247 
248  if (ExpandEnvironmentStrings(szDispName, szPath, ARRAYSIZE(szPath)))
249  {
250  hLib = LoadLibrary(szPath);
251  if (hLib)
252  {
253  if (LoadString(hLib, _ttoi(szIndex), szPath, ARRAYSIZE(szPath)) != 0)
254  {
255  StringCchCopy(szName, NameLength, szPath);
256  RegCloseKey(hKey);
257  FreeLibrary(hLib);
258  return TRUE;
259  }
260  FreeLibrary(hLib);
261  }
262  }
263  }
264  }
265 
266  dwBufLen = NameLength * sizeof(TCHAR);
267 
268  if (RegQueryValueEx(hKey, _T("Layout Text"), NULL, NULL, (LPBYTE)szName, &dwBufLen) == ERROR_SUCCESS)
269  {
270  RegCloseKey(hKey);
271  return TRUE;
272  }
273 
274  RegCloseKey(hKey);
275  }
276 
277  return FALSE;
278 }
#define RegQueryValueEx
Definition: winreg.h:524
GLenum GLclampf GLint GLenum GLuint GLenum GLenum GLsizei GLenum const GLvoid GLfloat GLfloat GLfloat GLfloat GLclampd GLint GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean GLboolean GLboolean GLboolean GLint GLenum GLsizei const GLvoid GLenum GLint GLenum GLint GLint GLsizei GLint GLenum GLint GLint GLint GLint GLsizei GLenum GLsizei const GLuint GLboolean GLenum GLenum GLint GLsizei GLenum GLsizei GLenum const GLvoid GLboolean const GLboolean GLenum const GLdouble const GLfloat const GLdouble const GLfloat GLenum GLint GLint GLint GLint GLint GLint j
Definition: glfuncs.h:98
#define TRUE
Definition: types.h:120
const CHAR * LPCTSTR
Definition: xmlstorage.h:193
#define ERROR_SUCCESS
Definition: deptool.c:10
#define CCH_LAYOUT_ID
Definition: kbswitch.h:17
#define LoadLibrary
Definition: winbase.h:3676
#define ExpandEnvironmentStrings
Definition: winbase.h:3588
#define ARRAYSIZE(array)
Definition: filtermapper.c:47
_In_ HCRYPTHASH _In_ BOOL _In_ DWORD _Inout_ DWORD _In_ DWORD dwBufLen
Definition: wincrypt.h:4243
GLenum GLclampf GLint i
Definition: glfuncs.h:14
LONG WINAPI RegCloseKey(HKEY hKey)
Definition: reg.c:423
unsigned char * LPBYTE
Definition: typedefs.h:52
#define StringCchPrintf
Definition: strsafe.h:517
size_t __cdecl _tcslen(const _TCHAR *str)
Definition: tcslen.h:9
smooth NULL
Definition: ftsmooth.c:416
char TCHAR
Definition: xmlstorage.h:189
#define _T(x)
Definition: vfdio.h:22
#define FreeLibrary(x)
Definition: compat.h:405
#define MAX_PATH
Definition: compat.h:26
unsigned int UINT
Definition: ndis.h:50
unsigned long DWORD
Definition: ntddk_ex.h:95
static BOOL GetLayoutID(LPTSTR szLayoutNum, LPTSTR szLCID, SIZE_T LCIDLength)
Definition: kbswitch.c:155
#define StringCchCopy
Definition: strsafe.h:139
GLenum GLsizei len
Definition: glext.h:6722
#define RegOpenKeyEx
Definition: winreg.h:520
LPCWSTR szPath
Definition: env.c:35
#define KEY_QUERY_VALUE
Definition: nt_native.h:1016
int CDECL _ttoi(const _TCHAR *str)
Definition: atoi.c:10
static const WCHAR szName[]
Definition: msipriv.h:1194
int k
Definition: mpi.c:3369
#define LoadString
Definition: winuser.h:5685
#define HKEY_LOCAL_MACHINE
Definition: winreg.h:12

◆ GetNextLayout()

ULONG GetNextLayout ( VOID  )

Definition at line 370 of file kbswitch.c.

Referenced by WndProc().

371 {
372  TCHAR szLayoutNum[3 + 1], szLayoutID[CCH_LAYOUT_ID + 1];
374 
375  _ultot(ulCurrentLayoutNum, szLayoutNum, 10);
376  if (!GetLayoutID(szLayoutNum, szLayoutID, ARRAYSIZE(szLayoutID)))
377  {
378  return -1;
379  }
380 
381  _ultot(Ret + 1, szLayoutNum, 10);
382 
383  if (GetLayoutID(szLayoutNum, szLayoutID, ARRAYSIZE(szLayoutID)))
384  {
385  return (Ret + 1);
386  }
387  else
388  {
389  _ultot(Ret - 1, szLayoutNum, 10);
390  if (GetLayoutID(szLayoutNum, szLayoutID, ARRAYSIZE(szLayoutID)))
391  return (Ret - 1);
392  else
393  return -1;
394  }
395 
396  return -1;
397 }
#define CCH_LAYOUT_ID
Definition: kbswitch.h:17
#define ARRAYSIZE(array)
Definition: filtermapper.c:47
char TCHAR
Definition: xmlstorage.h:189
static BOOL GetLayoutID(LPTSTR szLayoutNum, LPTSTR szLCID, SIZE_T LCIDLength)
Definition: kbswitch.c:155
ULONG ulCurrentLayoutNum
Definition: kbswitch.c:27
#define _ultot
Definition: tchar.h:610
unsigned int ULONG
Definition: retypes.h:1

◆ SetHooks()

BOOL SetHooks ( VOID  )

Definition at line 343 of file kbswitch.c.

Referenced by WndProc().

344 {
345  hDllLib = LoadLibrary(_T("kbsdll.dll"));
346  if (!hDllLib)
347  {
348  return FALSE;
349  }
350 
351  KbSwitchSetHooks = (PKBSWITCHSETHOOKS) GetProcAddress(hDllLib, "KbSwitchSetHooks");
353 
355  {
356  return FALSE;
357  }
358 
359  return KbSwitchSetHooks();
360 }
#define LoadLibrary
Definition: winbase.h:3676
BOOL(WINAPI * PKBSWITCHSETHOOKS)(VOID)
Definition: kbswitch.h:27
PKBSWITCHDELETEHOOKS KbSwitchDeleteHooks
Definition: kbswitch.c:14
smooth NULL
Definition: ftsmooth.c:416
VOID(WINAPI * PKBSWITCHDELETEHOOKS)(VOID)
Definition: kbswitch.h:28
#define _T(x)
Definition: vfdio.h:22
HMODULE hDllLib
Definition: kbswitch.c:26
PKBSWITCHSETHOOKS KbSwitchSetHooks
Definition: kbswitch.c:13
#define GetProcAddress(x, y)
Definition: compat.h:410

◆ UpdateLanguageDisplay()

LRESULT UpdateLanguageDisplay ( HWND  hwnd,
HKL  hKl 
)

Definition at line 400 of file kbswitch.c.

Referenced by UpdateLanguageDisplayCurrent(), and WndProc().

401 {
402  static TCHAR szLCID[MAX_PATH], szLangName[MAX_PATH];
403 
404  GetLayoutIDByHkl(hKl, szLCID, ARRAYSIZE(szLCID));
405  GetLocaleInfo((LANGID)_tcstoul(szLCID, NULL, 16), LOCALE_SLANGUAGE, (LPTSTR)szLangName, ARRAYSIZE(szLangName));
406  UpdateTrayIcon(hwnd, szLCID, szLangName);
407 
408  return 0;
409 }
#define LOCALE_SLANGUAGE
Definition: winnls.h:26
#define GetLocaleInfo
Definition: winnls.h:1154
#define ARRAYSIZE(array)
Definition: filtermapper.c:47
WORD LANGID
Definition: typedefs.h:79
CHAR * LPTSTR
Definition: xmlstorage.h:192
smooth NULL
Definition: ftsmooth.c:416
char TCHAR
Definition: xmlstorage.h:189
static VOID UpdateTrayIcon(HWND hwnd, LPTSTR szLCID, LPTSTR szName)
Definition: kbswitch.c:137
#define MAX_PATH
Definition: compat.h:26
#define _tcstoul
Definition: tchar.h:595
VOID GetLayoutIDByHkl(HKL hKl, LPTSTR szLayoutID, SIZE_T LayoutIDLength)
Definition: kbswitch.c:200

◆ UpdateLanguageDisplayCurrent()

LRESULT UpdateLanguageDisplayCurrent ( HWND  hwnd,
WPARAM  wParam 
)

Definition at line 412 of file kbswitch.c.

Referenced by WndProc().

413 {
415 }
WPARAM wParam
Definition: combotst.c:138
DWORD WINAPI GetWindowThreadProcessId(HWND, PDWORD)
PKEYBOARD_LAYOUT GetKeyboardLayout()
Definition: utils.c:194
LRESULT UpdateLanguageDisplay(HWND hwnd, HKL hKl)
Definition: kbswitch.c:400

◆ UpdateTrayIcon()

static VOID UpdateTrayIcon ( HWND  hwnd,
LPTSTR  szLCID,
LPTSTR  szName 
)
static

Definition at line 137 of file kbswitch.c.

Referenced by ActivateLayout(), and UpdateLanguageDisplay().

138 {
139  NOTIFYICONDATA tnid;
140 
141  memset(&tnid, 0, sizeof(tnid));
142  tnid.cbSize = sizeof(NOTIFYICONDATA);
143  tnid.hWnd = hwnd;
144  tnid.uID = 1;
145  tnid.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP;
147  tnid.hIcon = CreateTrayIcon(szLCID);
148 
149  StringCchCopy(tnid.szTip, ARRAYSIZE(tnid.szTip), szName);
150 
152 }
static HICON CreateTrayIcon(LPTSTR szLCID)
Definition: kbswitch.c:30
const DOCKBAR PVOID HWND HWND * hwnd
Definition: tooldock.h:22
#define NIF_MESSAGE
Definition: shellapi.h:102
#define ARRAYSIZE(array)
Definition: filtermapper.c:47
#define WM_NOTIFYICONMSG
Definition: kbswitch.c:11
CHAR szTip[128]
Definition: shellapi.h:233
#define NIF_TIP
Definition: shellapi.h:104
NOTIFYICONDATAA NOTIFYICONDATA
Definition: shellapi.h:665
#define NIF_ICON
Definition: shellapi.h:103
#define StringCchCopy
Definition: strsafe.h:139
UINT uCallbackMessage
Definition: shellapi.h:227
static const WCHAR szName[]
Definition: msipriv.h:1194
#define Shell_NotifyIcon
Definition: shellapi.h:677
#define memset(x, y, z)
Definition: compat.h:39
#define NIM_MODIFY
Definition: shellapi.h:92

◆ WndProc()

LRESULT CALLBACK WndProc ( HWND  hwnd,
UINT  Message,
WPARAM  wParam,
LPARAM  lParam 
)

Definition at line 418 of file kbswitch.c.

Referenced by _tWinMain().

419 {
420  static HMENU hRightPopupMenu;
421  static UINT s_uTaskbarRestart;
422 
423  switch (Message)
424  {
425  case WM_CREATE:
426  {
427  SetHooks();
428  AddTrayIcon(hwnd);
429  hRightPopupMenu = GetSubMenu(LoadMenu(hInst, MAKEINTRESOURCE(IDR_POPUP)), 0);
430 
432  s_uTaskbarRestart = RegisterWindowMessage(TEXT("TaskbarCreated"));
433 
434  return 0;
435  }
436 
437  case WM_LANG_CHANGED:
438  {
439  return UpdateLanguageDisplay(hwnd, (HKL)lParam);
440  }
441 
442  case WM_LOAD_LAYOUT:
443  {
444  ActivateLayout(hwnd, GetNextLayout());
445 
446  return 0;
447  }
448 
449  case WM_WINDOW_ACTIVATE:
450  {
451  return UpdateLanguageDisplayCurrent(hwnd, wParam);
452  }
453 
454  case WM_NOTIFYICONMSG:
455  switch (lParam)
456  {
457  case WM_RBUTTONUP:
458  case WM_LBUTTONUP:
459  {
460  POINT pt;
461 
462  GetCursorPos(&pt);
463  SetForegroundWindow(hwnd);
464 
465  if (lParam == WM_LBUTTONUP)
466  {
467  HMENU hLeftPopupMenu;
468  /* Rebuild the left popup menu on every click to take care of keyboard layout changes */
469  hLeftPopupMenu = BuildLeftPopupMenu();
470  TrackPopupMenu(hLeftPopupMenu, 0, pt.x, pt.y, 0, hwnd, NULL);
471  DestroyMenu(hLeftPopupMenu);
472  }
473  else
474  {
475  TrackPopupMenu(hRightPopupMenu, 0, pt.x, pt.y, 0, hwnd, NULL);
476  }
477 
478  PostMessage(hwnd, WM_NULL, 0, 0);
479 
480  return 0;
481  }
482  }
483  break;
484 
485  case WM_COMMAND:
486  switch (LOWORD(wParam))
487  {
488  case ID_EXIT:
489  SendMessage(hwnd, WM_CLOSE, 0, 0);
490  return 0;
491 
492  case ID_PREFERENCES:
493  {
494  SHELLEXECUTEINFO shInputDll = {0};
495 
496  shInputDll.cbSize = sizeof(shInputDll);
497  shInputDll.hwnd = hwnd;
498  shInputDll.lpVerb = _T("open");
499  shInputDll.lpFile = _T("rundll32.exe");
500  shInputDll.lpParameters = _T("shell32.dll,Control_RunDLL input.dll");
501 
502  if (!ShellExecuteEx(&shInputDll))
503  MessageBox(hwnd, _T("Can't start input.dll"), NULL, MB_OK | MB_ICONERROR);
504 
505  return 0;
506  }
507 
508  default:
509  ActivateLayout(hwnd, LOWORD(wParam));
510  return 0;
511  }
512  break;
513 
514  case WM_SETTINGCHANGE:
515  {
516  if (wParam == SPI_SETDEFAULTINPUTLANG)
517  {
518  //FIXME: Should detect default language changes by CPL applet or by other tools and update UI
519  }
520  if (wParam == SPI_SETNONCLIENTMETRICS)
521  {
522  return UpdateLanguageDisplayCurrent(hwnd, wParam);
523  }
524  }
525  break;
526 
527  case WM_DESTROY:
528  {
529  DeleteHooks();
530  DestroyMenu(hRightPopupMenu);
531  DelTrayIcon(hwnd);
532  PostQuitMessage(0);
533 
534  return 0;
535  }
536 
537  default:
538  if(Message == s_uTaskbarRestart)
539  AddTrayIcon(hwnd);
540  break;
541  }
542 
543  if (Message == ShellHookMessage && wParam == HSHELL_LANGUAGE)
544  {
546  return 0;
547  }
548 
549  return DefWindowProc(hwnd, Message, wParam, lParam);
550 }
#define WM_NULL
Definition: winuser.h:1589
#define ShellExecuteEx
Definition: shellapi.h:680
const DOCKBAR PVOID HWND HWND * hwnd
Definition: tooldock.h:22
#define MAKEINTRESOURCE
Definition: winuser.h:591
long y
Definition: polytest.cpp:48
long x
Definition: polytest.cpp:48
#define pt(x, y)
Definition: drawing.c:79
LRESULT UpdateLanguageDisplayCurrent(HWND hwnd, WPARAM wParam)
Definition: kbswitch.c:412
static VOID AddTrayIcon(HWND hwnd)
Definition: kbswitch.c:101
BOOL WINAPI GetCursorPos(_Out_ LPPOINT)
Definition: cursoricon.c:2635
WPARAM wParam
Definition: combotst.c:138
#define WM_SETTINGCHANGE
Definition: winuser.h:1611
#define WM_NOTIFYICONMSG
Definition: kbswitch.c:11
#define IDR_POPUP
Definition: resource.h:7
smooth NULL
Definition: ftsmooth.c:416
#define WM_LANG_CHANGED
Definition: kbswitch.h:23
#define DefWindowProc
Definition: ros2win.h:31
HINSTANCE hInst
Definition: kbswitch.c:24
#define WM_DESTROY
Definition: winuser.h:1591
#define PostMessage
Definition: winuser.h:5698
VOID DeleteHooks(VOID)
Definition: kbswitch.c:363
#define _T(x)
Definition: vfdio.h:22
LPCSTR lpParameters
Definition: shellapi.h:312
#define WM_CLOSE
Definition: winuser.h:1603
#define WM_WINDOW_ACTIVATE
Definition: kbswitch.h:24
unsigned int UINT
Definition: ndis.h:50
#define WM_RBUTTONUP
Definition: winuser.h:1756
CHAR Message[80]
Definition: alive.c:5
#define MB_ICONERROR
Definition: winuser.h:781
#define MessageBox
Definition: winuser.h:5688
HMENU WINAPI GetSubMenu(_In_ HMENU, _In_ int)
#define WM_COMMAND
Definition: winuser.h:1716
UINT_PTR HKL
Definition: msctf.idl:101
#define ID_EXIT
Definition: resource.h:10
BOOL WINAPI DestroyMenu(_In_ HMENU)
#define RegisterWindowMessage
Definition: winuser.h:5706
static VOID ActivateLayout(HWND hwnd, ULONG uLayoutNum)
Definition: kbswitch.c:288
ULONG ulCurrentLayoutNum
Definition: kbswitch.c:27
UINT ShellHookMessage
Definition: kbswitch.c:15
#define TEXT(s)
Definition: k32.h:26
#define LoadMenu
Definition: winuser.h:5683
#define WM_LBUTTONUP
Definition: winuser.h:1753
#define MB_OK
Definition: winuser.h:784
static HMENU BuildLeftPopupMenu(VOID)
Definition: kbswitch.c:309
#define SendMessage
Definition: winuser.h:5709
#define WM_CREATE
Definition: winuser.h:1590
BOOL WINAPI SetForegroundWindow(_In_ HWND)
#define WM_LOAD_LAYOUT
Definition: kbswitch.h:25
static VOID DelTrayIcon(HWND hwnd)
Definition: kbswitch.c:124
BOOL SetHooks(VOID)
Definition: kbswitch.c:343
#define ID_PREFERENCES
Definition: resource.h:11
static const CLSID *static CLSID *static const GUID VARIANT VARIANT *static IServiceProvider DWORD *static HMENU
Definition: ordinal.c:60
LPARAM lParam
Definition: combotst.c:139
BOOL WINAPI TrackPopupMenu(_In_ HMENU, _In_ UINT, _In_ int, _In_ int, _Reserved_ int, _In_ HWND, _Reserved_ LPCRECT)
#define LOWORD(l)
Definition: pedump.c:82
__analysis_noreturn void WINAPI PostQuitMessage(_In_ int)
LRESULT UpdateLanguageDisplay(HWND hwnd, HKL hKl)
Definition: kbswitch.c:400
ULONG GetNextLayout(VOID)
Definition: kbswitch.c:370

Variable Documentation

◆ hDllLib

HMODULE hDllLib

Definition at line 26 of file kbswitch.c.

◆ hInst

HINSTANCE hInst

Definition at line 24 of file kbswitch.c.

◆ hProcessHeap

◆ KbSwitchDeleteHooks

PKBSWITCHDELETEHOOKS KbSwitchDeleteHooks = NULL

Definition at line 14 of file kbswitch.c.

Referenced by DeleteHooks(), and SetHooks().

◆ KbSwitchSetHooks

PKBSWITCHSETHOOKS KbSwitchSetHooks = NULL

Definition at line 13 of file kbswitch.c.

Referenced by SetHooks().

◆ ShellHookMessage

UINT ShellHookMessage = 0

Definition at line 15 of file kbswitch.c.

Referenced by _tWinMain(), and WndProc().

◆ ulCurrentLayoutNum

ULONG ulCurrentLayoutNum = 1

Definition at line 27 of file kbswitch.c.

Referenced by ActivateLayout(), BuildLeftPopupMenu(), GetNextLayout(), and WndProc().