1 /*
2  * PROJECT:         ReactOS
3  * LICENSE:         GPL - See COPYING in the top level directory
4  * FILE:            base/applications/testset/user32/kbdlayout/kbdlayout.c
5  * PURPOSE:         Keyboard layout testapp
6  * COPYRIGHT:       Copyright 2007 Saveliy Tretiakov
7  */
8 
9 #define UNICODE
10 #include<wchar.h>
11 #include <windows.h>
12 #include "resource.h"
13 
14 
15 
16 LRESULT MainDialogProc(HWND hDlg, UINT Msg, WPARAM wParam, LPARAM lParam);
17 
18 
19 HINSTANCE hInst;
20 HWND hMainDlg;
21 
22 
23 typedef struct {
24 	WNDPROC OrigProc;
25 	WCHAR WndName[25];
26 } WND_DATA;
27 
28 DWORD WINAPI ThreadProc(LPVOID lpParam)
29 {
30 
31 	DialogBoxParam(hInst,
32 		MAKEINTRESOURCE(IDD_MAINDIALOG),
33 		NULL,
34 		(DLGPROC)MainDialogProc,
35 		(LPARAM)NULL);
36 
37 	return 0;
38 }
39 
40 INT WINAPI WinMain(HINSTANCE hInstance,
41     HINSTANCE hPrevInstance,
42     LPSTR lpCmdLine,
43     int nCmdShow)
44 {
45 
46 
47 	hInst = hInstance;
48 
49 	ThreadProc(0);
50 
51 	return 0;
52 }
53 
54 
55 int GetKlList(HKL **list)
56 {
57 	HKL *ret;
58 	int n;
59 
60 	n = GetKeyboardLayoutList(0, NULL);
61 	ret = HeapAlloc(GetProcessHeap(), 0, sizeof(HKL)*n);
62 	GetKeyboardLayoutList(n, ret);
63 	*list = ret;
64 	return n;
65 }
66 
67 void FreeKlList(HKL *list)
68 {
69 	HeapFree(GetProcessHeap(), 0, list);
70 }
71 
72 
73 void UpdateData(HWND hDlg)
74 {
75 	WCHAR buf[KL_NAMELENGTH];
76 	WCHAR buf2[512];
77 
78 	HWND hList;
79 	HKL *klList, hKl;
80 	int n, i,j;
81 
82 	GetKeyboardLayoutName(buf);
83 	swprintf(buf2, L"Active: %s (%x)", buf, GetKeyboardLayout(0));
84 	SetWindowText(GetDlgItem(hDlg, IDC_ACTIVE), buf2);
85 
86 	hList = GetDlgItem(hDlg, IDC_LIST);
87 	SendMessage(hList, LB_RESETCONTENT, 0, 0);
88 
89 	n = GetKlList(&klList);
90 	hKl = GetKeyboardLayout(0);
91 	for(i = 0; i < n; i++)
92 	{
93 		swprintf(buf, L"%x", klList[i] );
94 		j = SendMessage(hList, LB_ADDSTRING, 0, (LPARAM) buf);
95 		SendMessage(hList, LB_SETITEMDATA, j, (LPARAM) klList[i]);
96 		if(klList[i] == hKl) SendMessage(hList, LB_SETCURSEL, j, 0);
97 	}
98 
99 	FreeKlList(klList);
100 }
101 
102 void FormatMsg(WCHAR *format, ...)
103 {
104 	WCHAR buf[255];
105 	va_list argptr;
106 	va_start(argptr, format);
107 	_vsnwprintf(buf, sizeof(buf)-1, format, argptr);
108 	MessageBox(0, buf, L"msg", 0);
109 	va_end(argptr);
110 }
111 
112 void FormatBox(HWND hWnd, DWORD Flags, WCHAR *Caption, WCHAR *Format, ...)
113 {
114 	WCHAR buf[255];
115 	va_list argptr;
116 	va_start(argptr, Format);
117 	_vsnwprintf(buf, sizeof(buf)-1, Format, argptr);
118 	MessageBox(hWnd, buf, Caption, Flags);
119 	va_end(argptr);
120 }
121 
122 
123 LRESULT CALLBACK WndSubclassProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
124 {
125 	WND_DATA *data = (WND_DATA*)GetWindowLongPtr(hwnd, GWL_USERDATA);
126 
127 	if(uMsg == WM_INPUTLANGCHANGE)
128 	{
129 		FormatMsg(L"%s: WM_INPUTLANGCHANGE lParam=%x wParam=%x\n", data->WndName, lParam, wParam);
130 		UpdateData(hMainDlg);
131 		//Pass message to defwindowproc
132 	}
133 	else if(uMsg == WM_INPUTLANGCHANGEREQUEST)
134 	{
135 		FormatMsg(L"%s: WM_INPUTLANGCHANGEREQUEST lParam=%x wParam=%x\n", data->WndName, lParam, wParam);
136 		UpdateData(hMainDlg);
137 		//Pass message to defwindowproc
138 	}
139 
140 	return ( CallWindowProc( data->OrigProc, hwnd, uMsg, wParam, lParam) );
141 }
142 
143 void SubclassWnd(HWND hWnd, WCHAR* Name)
144 {
145 	WND_DATA *data = HeapAlloc(GetProcessHeap(), 0, sizeof(WND_DATA));
146 	data->OrigProc = (WNDPROC)SetWindowLongPtr( hWnd, GWL_WNDPROC, (LONG_PTR)WndSubclassProc);
147 	wcsncpy(data->WndName, Name, 25);
148 	SetWindowLongPtr(hWnd, GWL_USERDATA, (LONG_PTR)data);
149 	return;
150 }
151 
152 DWORD GetActivateFlags(HWND hDlg)
153 {
154 	DWORD ret = 0;
155 
156 	if(IsDlgButtonChecked(hDlg, IDC_KLF_REORDER))
157 		ret |= KLF_REORDER;
158 
159 	if(IsDlgButtonChecked(hDlg, IDC_KLF_RESET))
160 		ret |= KLF_RESET;
161 
162 	if(IsDlgButtonChecked(hDlg, IDC_KLF_SHIFTLOCK))
163 		ret |= KLF_SHIFTLOCK;
164 
165 	if(IsDlgButtonChecked(hDlg, IDC_KLF_SETFORPROCESS))
166 		ret |= KLF_SETFORPROCESS;
167 
168 	return ret;
169 
170 }
171 
172 DWORD GetLoadFlags(HWND hDlg)
173 {
174 	DWORD ret = 0;
175 
176 	if(IsDlgButtonChecked(hDlg, IDL_KLF_ACTIVATE))
177 		ret |= KLF_ACTIVATE;
178 
179 	if(IsDlgButtonChecked(hDlg, IDL_KLF_NOTELLSHELL))
180 		ret |= KLF_NOTELLSHELL;
181 
182 	if(IsDlgButtonChecked(hDlg, IDL_KLF_REORDER))
183 		ret |= KLF_REORDER;
184 
185 	if(IsDlgButtonChecked(hDlg, IDL_KLF_REPLACELANG))
186 		ret |= KLF_REPLACELANG;
187 
188 	if(IsDlgButtonChecked(hDlg, IDL_KLF_SUBSTITUTE_OK))
189 		ret |= KLF_SUBSTITUTE_OK;
190 
191 	if(IsDlgButtonChecked(hDlg, IDL_KLF_SETFORPROCESS))
192 		ret |= KLF_SETFORPROCESS;
193 
194 	return ret;
195 }
196 
197 UINT GetDelayMilliseconds(HWND hDlg)
198 {
199 	WCHAR Buf[255];
200 	UINT ret;
201 
202 	GetWindowText(GetDlgItem(hDlg, IDC_DELAY), Buf, sizeof(Buf));
203 
204 	swscanf(Buf, L"%d", &ret);
205 
206 	return ret*1000;
207 }
208 
209 HKL GetSelectedLayout(HWND hDlg)
210 {
211 	int n;
212 	HWND hList;
213 	hList = GetDlgItem(hDlg, IDC_LIST);
214 	if((n = SendMessage(hList, LB_GETCURSEL, 0, 0)) != LB_ERR)
215 		return (HKL) SendMessage(hList, LB_GETITEMDATA, n, 0);
216 	else return INVALID_HANDLE_VALUE;
217 }
218 
219 HKL GetActivateHandle(HWND hDlg)
220 {
221 
222 	if(IsDlgButtonChecked(hDlg, IDC_FROMLIST))
223 		return GetSelectedLayout(hDlg);
224 	else if(IsDlgButtonChecked(hDlg, IDC_HKL_NEXT))
225 		return (HKL)HKL_NEXT;
226 
227 	return (HKL)HKL_PREV;
228 
229 }
230 
231 
232 /***************************************************
233  * MainDialogProc                                  *
234  ***************************************************/
235 
236 LRESULT MainDialogProc(HWND hDlg,
237 	UINT Msg,
238 	WPARAM wParam,
239 	LPARAM lParam)
240 {
241 	HKL hKl;
242 
243 	switch (Msg)
244 	{
245 		case WM_INITDIALOG:
246 		{
247 			WCHAR Buf[255];
248 			UpdateData(hDlg);
249 			hMainDlg = hDlg;
250 
251 			SubclassWnd(GetDlgItem(hDlg, IDC_LIST), L"List");
252 			SubclassWnd(GetDlgItem(hDlg, IDC_EDIT1), L"Edit1");
253 			SubclassWnd(GetDlgItem(hDlg, IDC_KLID), L"Klid");
254 			SubclassWnd(GetDlgItem(hDlg, ID_CANCEL), L"CancelB");
255 			SubclassWnd(GetDlgItem(hDlg, IDC_ACTIVATE), L"ActivateB");
256 			SubclassWnd(GetDlgItem(hDlg, IDC_REFRESH), L"RefreshB");
257 			SubclassWnd(GetDlgItem(hDlg, IDC_UNLOAD), L"UnloadB");
258 			SubclassWnd(GetDlgItem(hDlg, IDC_LOAD), L"LoadB");
259 
260 			CheckRadioButton(hDlg, IDC_FROMLIST, IDC_FROMEDIT, IDC_FROMLIST);
261 			SetWindowText(GetDlgItem(hDlg, IDC_KLID), L"00000419");
262 
263 			swprintf(Buf, L"Current thread id: %d", GetCurrentThreadId());
264 			SetWindowText(GetDlgItem(hDlg, IDC_CURTHREAD), Buf);
265 
266 			SetWindowText(GetDlgItem(hDlg, IDC_DELAY), L"0");
267 
268 			return 0;
269 		} /* WM_INITDIALOG */
270 
271 		case WM_COMMAND:
272 		{
273 			switch(LOWORD(wParam))
274 			{
275 				case ID_CANCEL:
276 				{
277 					EndDialog(hDlg, ERROR_CANCELLED);
278 					break;
279 				}
280 
281 				case IDC_ACTIVATE:
282 				{
283 					if((hKl = GetActivateHandle(hDlg)) != INVALID_HANDLE_VALUE)
284 					{
285 						Sleep(GetDelayMilliseconds(hDlg));
286 						if(!(hKl = ActivateKeyboardLayout(hKl, GetActivateFlags(hDlg))))
287 							FormatBox(hDlg, MB_ICONERROR, L"Error",
288 								L"ActivateKeyboardLayout() failed. %d", GetLastError());
289 						else UpdateData(hDlg);
290 						//FormatBox(hDlg, 0, L"Activated", L"Prev - %x, err - %d.", hKl,
291 						// GetLastError());
292 					}
293 					else MessageBox(hDlg, L"No item selected", L"Error", MB_ICONERROR);
294 					break;
295 				}
296 
297 				case IDC_UNLOAD:
298 				{
299 					if((hKl = GetSelectedLayout(hDlg)) != INVALID_HANDLE_VALUE)
300 					{
301 						Sleep(GetDelayMilliseconds(hDlg));
302 						if(!UnloadKeyboardLayout(hKl))
303 							FormatBox(hDlg, MB_ICONERROR, L"Error",
304 								L"UnloadKeyboardLayout() failed. %d",
305 								GetLastError());
306 						else UpdateData(hDlg);
307 					}
308 					else MessageBox(hDlg,  L"No item selected", L"Error", MB_ICONERROR);
309 					break;
310 				}
311 
312 				case IDC_LOAD:
313 				{
314 					WCHAR buf[255];
315 					GetWindowText(GetDlgItem(hDlg, IDC_KLID), buf, sizeof(buf));
316 					Sleep(GetDelayMilliseconds(hDlg));
317 					if(!LoadKeyboardLayout(buf, GetLoadFlags(hDlg)))
318 						FormatBox(hDlg, MB_ICONERROR, L"Error",
319 							L"LoadKeyboardLayout() failed. %d",
320 							GetLastError());
321 					else UpdateData(hDlg);
322 					break;
323 				}
324 
325 				case IDC_REFRESH:
326 				{
327 					UpdateData(hDlg);
328 					break;
329 				}
330 
331 				case IDC_NEWTHREAD:
332 				{
333 					if(!CreateThread(NULL, 0, ThreadProc, NULL, 0, NULL))
334 					{
335 						FormatBox(hDlg, MB_ICONERROR, L"Error!",
336 							L"Can not create thread (%d).", GetLastError());
337 					}
338 				}
339 
340 				case IDC_LIST:
341 				{
342 					if(HIWORD(wParam) == LBN_SELCHANGE)
343 					{
344 						WCHAR buf[25];
345 						if((hKl = GetSelectedLayout(hDlg)) != NULL)
346 						{
347 							swprintf(buf, L"%x", hKl);
348 							SetWindowText(GetDlgItem(hDlg, IDC_HANDLE), buf);
349 						}
350 					}
351 					break;
352 				}
353 
354 			}
355 
356 			return TRUE;
357 		} /* WM_COMMAND */
358 
359 
360 		case WM_INPUTLANGCHANGE:
361 		{
362 			FormatMsg(L"dlg WM_INPUTLANGCHANGE lParam=%x wParam=%x\n", lParam, wParam);
363 			return FALSE;
364 		}
365 
366 		case WM_INPUTLANGCHANGEREQUEST:
367 		{
368 			FormatMsg(L"dlg WM_INPUTLANGCHANGEREQUEST lParam=%x wParam=%x\n", lParam, wParam);
369 			UpdateData(hDlg);
370 			return FALSE;
371 		}
372 
373 		case WM_CLOSE:
374 		{
375 			EndDialog(hDlg, ERROR_CANCELLED);
376 			return TRUE;
377 		} /* WM_CLOSE */
378 
379 		default:
380 			return FALSE;
381 	}
382 
383 }
384 
385 
386 
387 
388