2 * PROJECT: ReactOS On-Screen Keyboard
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: base/applications/osk/main.c
5 * PURPOSE: On-screen keyboard.
6 * PROGRAMMERS: Denis ROBERT
9 /* INCLUDES *******************************************************************/
14 /* GLOBALS ********************************************************************/
19 int OSK_SetImage(int IdDlgItem
, int IdResource
);
20 int OSK_DlgInitDialog(HWND hDlg
);
21 int OSK_DlgClose(void);
22 int OSK_DlgTimer(void);
23 BOOL
OSK_DlgCommand(WPARAM wCommand
, HWND hWndControl
);
24 BOOL
OSK_ReleaseKey(WORD ScanCode
);
26 INT_PTR APIENTRY
OSK_DlgProc(HWND hDlg
, UINT msg
, WPARAM wParam
, LPARAM lParam
);
27 int WINAPI
wWinMain(HINSTANCE
, HINSTANCE
, LPWSTR
, int);
29 /* FUNCTIONS ******************************************************************/
31 /***********************************************************************
35 * Set an image on a button
37 int OSK_SetImage(int IdDlgItem
, int IdResource
)
42 hIcon
= (HICON
)LoadImageW(Globals
.hInstance
, MAKEINTRESOURCEW(IdResource
),
43 IMAGE_ICON
, 16, 16, LR_DEFAULTCOLOR
);
47 hWndItem
= GetDlgItem(Globals
.hMainWnd
, IdDlgItem
);
54 SendMessageW(hWndItem
, BM_SETIMAGE
, (WPARAM
)IMAGE_ICON
, (LPARAM
)hIcon
);
56 /* The system automatically deletes these resources when the process that created them terminates (MSDN) */
61 /***********************************************************************
65 * Function handler for the warning dialog box on startup
67 INT_PTR CALLBACK
OSK_WarningProc(HWND hDlg
, UINT Msg
, WPARAM wParam
, LPARAM lParam
)
69 UNREFERENCED_PARAMETER(lParam
);
80 switch (LOWORD(wParam
))
82 case IDC_SHOWWARNINGCHECK
:
84 Globals
.bShowWarning
= !IsDlgButtonChecked(hDlg
, IDC_SHOWWARNINGCHECK
);
91 EndDialog(hDlg
, LOWORD(wParam
));
102 /***********************************************************************
106 * Initializes the "About" dialog box
110 WCHAR szTitle
[MAX_BUFF
];
111 WCHAR szAuthors
[MAX_BUFF
];
115 OSKIcon
= LoadImageW(Globals
.hInstance
, MAKEINTRESOURCEW(IDI_OSK
), IMAGE_ICON
, 0, 0, LR_DEFAULTSIZE
);
117 /* Load the strings into the "About" dialog */
118 LoadStringW(Globals
.hInstance
, STRING_OSK
, szTitle
, countof(szTitle
));
119 LoadStringW(Globals
.hInstance
, STRING_AUTHORS
, szAuthors
, countof(szAuthors
));
121 /* Finally, execute the "About" dialog by using the Shell routine */
122 ShellAboutW(Globals
.hMainWnd
, szTitle
, szAuthors
, OSKIcon
);
124 /* Once done, destroy the icon */
125 DestroyIcon(OSKIcon
);
129 /***********************************************************************
133 * Handling of WM_INITDIALOG
135 int OSK_DlgInitDialog(HWND hDlg
)
137 HICON hIcon
, hIconSm
;
144 Globals
.hMainWnd
= hDlg
;
146 /* Check the checked menu item before displaying the modal box */
147 if (Globals
.bIsEnhancedKeyboard
)
149 /* Enhanced keyboard dialog chosen, set the respective menu item as checked */
150 CheckMenuItem(GetMenu(hDlg
), IDM_ENHANCED_KB
, MF_BYCOMMAND
| MF_CHECKED
);
151 CheckMenuItem(GetMenu(hDlg
), IDM_STANDARD_KB
, MF_BYCOMMAND
| MF_UNCHECKED
);
155 /* Standard keyboard dialog chosen, set the respective menu item as checked */
156 CheckMenuItem(GetMenu(hDlg
), IDM_STANDARD_KB
, MF_BYCOMMAND
| MF_CHECKED
);
157 CheckMenuItem(GetMenu(hDlg
), IDM_ENHANCED_KB
, MF_BYCOMMAND
| MF_UNCHECKED
);
160 /* Set the application's icon */
161 hIcon
= LoadImageW(Globals
.hInstance
, MAKEINTRESOURCEW(IDI_OSK
), IMAGE_ICON
, 0, 0, LR_SHARED
| LR_DEFAULTSIZE
);
162 hIconSm
= CopyImage(hIcon
, IMAGE_ICON
, GetSystemMetrics(SM_CXSMICON
), GetSystemMetrics(SM_CYSMICON
), LR_COPYFROMRESOURCE
);
163 if (hIcon
|| hIconSm
)
165 /* Set the window icons (they are deleted when the process terminates) */
166 SendMessageW(Globals
.hMainWnd
, WM_SETICON
, ICON_BIG
, (LPARAM
)hIcon
);
167 SendMessageW(Globals
.hMainWnd
, WM_SETICON
, ICON_SMALL
, (LPARAM
)hIconSm
);
170 /* Get screen info */
171 memset(&Pt
, 0, sizeof(Pt
));
172 monitor
= MonitorFromPoint(Pt
, MONITOR_DEFAULTTOPRIMARY
);
173 info
.cbSize
= sizeof(info
);
174 GetMonitorInfoW(monitor
, &info
);
176 /* Move the dialog on the bottom of main screen */
177 GetWindowRect(hDlg
, &rcWindow
);
179 (info
.rcMonitor
.left
+ info
.rcMonitor
.right
) / 2 - // Center of screen
180 (rcWindow
.right
- rcWindow
.left
) / 2, // - half size of dialog
181 info
.rcMonitor
.bottom
- // Bottom of screen
182 (rcWindow
.bottom
- rcWindow
.top
), // - size of window
183 rcWindow
.right
- rcWindow
.left
, // Width
184 rcWindow
.bottom
- rcWindow
.top
, // Height
187 /* Set icon on visual buttons */
188 OSK_SetImage(SCAN_CODE_15
, IDI_BACK
);
189 OSK_SetImage(SCAN_CODE_16
, IDI_TAB
);
190 OSK_SetImage(SCAN_CODE_30
, IDI_CAPS_LOCK
);
191 OSK_SetImage(SCAN_CODE_43
, IDI_RETURN
);
192 OSK_SetImage(SCAN_CODE_44
, IDI_SHIFT
);
193 OSK_SetImage(SCAN_CODE_57
, IDI_SHIFT
);
194 OSK_SetImage(SCAN_CODE_127
, IDI_REACTOS
);
195 OSK_SetImage(SCAN_CODE_128
, IDI_REACTOS
);
196 OSK_SetImage(SCAN_CODE_129
, IDI_MENU
);
197 OSK_SetImage(SCAN_CODE_80
, IDI_HOME
);
198 OSK_SetImage(SCAN_CODE_85
, IDI_PG_UP
);
199 OSK_SetImage(SCAN_CODE_86
, IDI_PG_DOWN
);
200 OSK_SetImage(SCAN_CODE_79
, IDI_LEFT
);
201 OSK_SetImage(SCAN_CODE_83
, IDI_TOP
);
202 OSK_SetImage(SCAN_CODE_84
, IDI_BOTTOM
);
203 OSK_SetImage(SCAN_CODE_89
, IDI_RIGHT
);
205 /* Create a green brush for leds */
206 Globals
.hBrushGreenLed
= CreateSolidBrush(RGB(0, 255, 0));
208 /* Set a timer for periodics tasks */
209 Globals
.iTimer
= SetTimer(hDlg
, 0, 200, NULL
);
214 /***********************************************************************
218 * Handling of WM_CLOSE
220 int OSK_DlgClose(void)
222 KillTimer(Globals
.hMainWnd
, Globals
.iTimer
);
224 /* Release Ctrl, Shift, Alt keys */
225 OSK_ReleaseKey(SCAN_CODE_44
); // Left shift
226 OSK_ReleaseKey(SCAN_CODE_57
); // Right shift
227 OSK_ReleaseKey(SCAN_CODE_58
); // Left ctrl
228 OSK_ReleaseKey(SCAN_CODE_60
); // Left alt
229 OSK_ReleaseKey(SCAN_CODE_62
); // Right alt
230 OSK_ReleaseKey(SCAN_CODE_64
); // Right ctrl
232 /* delete GDI objects */
233 if (Globals
.hBrushGreenLed
) DeleteObject(Globals
.hBrushGreenLed
);
235 /* Save the settings to the registry hive */
236 SaveDataToRegistry();
241 /***********************************************************************
245 * Handling of WM_TIMER
247 int OSK_DlgTimer(void)
249 /* FIXME: To be deleted when ReactOS will support WS_EX_NOACTIVATE */
250 HWND hWndActiveWindow
;
252 hWndActiveWindow
= GetForegroundWindow();
253 if (hWndActiveWindow
!= NULL
&& hWndActiveWindow
!= Globals
.hMainWnd
)
255 Globals
.hActiveWnd
= hWndActiveWindow
;
258 /* Always redraw leds because it can be changed by the real keyboard) */
259 InvalidateRect(GetDlgItem(Globals
.hMainWnd
, IDC_LED_NUM
), NULL
, TRUE
);
260 InvalidateRect(GetDlgItem(Globals
.hMainWnd
, IDC_LED_CAPS
), NULL
, TRUE
);
261 InvalidateRect(GetDlgItem(Globals
.hMainWnd
, IDC_LED_SCROLL
), NULL
, TRUE
);
266 /***********************************************************************
270 * All handling of dialog command
272 BOOL
OSK_DlgCommand(WPARAM wCommand
, HWND hWndControl
)
281 /* FIXME: To be deleted when ReactOS will support WS_EX_NOACTIVATE */
282 if (Globals
.hActiveWnd
)
286 SetForegroundWindow(Globals
.hActiveWnd
);
287 while (PeekMessageW(&msg
, 0, 0, 0, PM_REMOVE
))
289 TranslateMessage(&msg
);
290 DispatchMessageW(&msg
);
294 /* KeyDown and/or KeyUp ? */
295 WindowStyle
= GetWindowLongW(hWndControl
, GWL_STYLE
);
296 if ((WindowStyle
& BS_AUTOCHECKBOX
) == BS_AUTOCHECKBOX
)
298 /* 2-states key like Shift, Alt, Ctrl, ... */
299 if (SendMessageW(hWndControl
, BM_GETCHECK
, 0, 0) == BST_CHECKED
)
319 if (ScanCode
& 0x0200)
322 bExtendedKey
= FALSE
;
325 /* Press and release the key */
328 Input
.type
= INPUT_KEYBOARD
;
330 Input
.ki
.wScan
= ScanCode
;
331 Input
.ki
.time
= GetTickCount();
332 Input
.ki
.dwExtraInfo
= GetMessageExtraInfo();
333 Input
.ki
.dwFlags
= KEYEVENTF_SCANCODE
;
334 if (bExtendedKey
) Input
.ki
.dwFlags
|= KEYEVENTF_EXTENDEDKEY
;
335 SendInput(1, &Input
, sizeof(Input
));
340 Input
.type
= INPUT_KEYBOARD
;
342 Input
.ki
.wScan
= ScanCode
;
343 Input
.ki
.time
= GetTickCount();
344 Input
.ki
.dwExtraInfo
= GetMessageExtraInfo();
345 Input
.ki
.dwFlags
= KEYEVENTF_SCANCODE
| KEYEVENTF_KEYUP
;
346 if (bExtendedKey
) Input
.ki
.dwFlags
|= KEYEVENTF_EXTENDEDKEY
;
347 SendInput(1, &Input
, sizeof(Input
));
353 /***********************************************************************
357 * Release the key of ID wCommand
359 BOOL
OSK_ReleaseKey(WORD ScanCode
)
366 /* Is it a 2-states key ? */
367 hWndControl
= GetDlgItem(Globals
.hMainWnd
, ScanCode
);
368 WindowStyle
= GetWindowLongW(hWndControl
, GWL_STYLE
);
369 if ((WindowStyle
& BS_AUTOCHECKBOX
) != BS_AUTOCHECKBOX
) return FALSE
;
371 /* Is the key down ? */
372 if (SendMessageW(hWndControl
, BM_GETCHECK
, 0, 0) != BST_CHECKED
) return TRUE
;
375 if (ScanCode
& 0x0200)
378 bExtendedKey
= FALSE
;
381 /* Release the key */
382 Input
.type
= INPUT_KEYBOARD
;
384 Input
.ki
.wScan
= ScanCode
;
385 Input
.ki
.time
= GetTickCount();
386 Input
.ki
.dwExtraInfo
= GetMessageExtraInfo();
387 Input
.ki
.dwFlags
= KEYEVENTF_SCANCODE
| KEYEVENTF_KEYUP
;
388 if (bExtendedKey
) Input
.ki
.dwFlags
|= KEYEVENTF_EXTENDEDKEY
;
389 SendInput(1, &Input
, sizeof(Input
));
394 /***********************************************************************
398 INT_PTR APIENTRY
OSK_DlgProc(HWND hDlg
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
403 OSK_DlgInitDialog(hDlg
);
410 case WM_CTLCOLORSTATIC
:
411 if ((HWND
)lParam
== GetDlgItem(hDlg
, IDC_LED_NUM
))
413 if (GetKeyState(VK_NUMLOCK
) & 0x0001)
414 return (INT_PTR
)Globals
.hBrushGreenLed
;
416 return (INT_PTR
)GetStockObject(BLACK_BRUSH
);
418 if ((HWND
)lParam
== GetDlgItem(hDlg
, IDC_LED_CAPS
))
420 if (GetKeyState(VK_CAPITAL
) & 0x0001)
421 return (INT_PTR
)Globals
.hBrushGreenLed
;
423 return (INT_PTR
)GetStockObject(BLACK_BRUSH
);
425 if ((HWND
)lParam
== GetDlgItem(hDlg
, IDC_LED_SCROLL
))
427 if (GetKeyState(VK_SCROLL
) & 0x0001)
428 return (INT_PTR
)Globals
.hBrushGreenLed
;
430 return (INT_PTR
)GetStockObject(BLACK_BRUSH
);
435 switch (LOWORD(wParam
))
439 EndDialog(hDlg
, FALSE
);
445 EndDialog(hDlg
, FALSE
);
449 case IDM_ENHANCED_KB
:
451 if (!Globals
.bIsEnhancedKeyboard
)
454 The user attempted to switch to enhanced keyboard dialog type.
455 Set the member value as TRUE, destroy the dialog and save the data configuration into the registry.
457 Globals
.bIsEnhancedKeyboard
= TRUE
;
458 EndDialog(hDlg
, FALSE
);
459 SaveDataToRegistry();
461 /* Change the condition of enhanced keyboard item menu to checked */
462 CheckMenuItem(GetMenu(hDlg
), IDM_ENHANCED_KB
, MF_BYCOMMAND
| MF_CHECKED
);
463 CheckMenuItem(GetMenu(hDlg
), IDM_STANDARD_KB
, MF_BYCOMMAND
| MF_UNCHECKED
);
465 /* Finally, display the dialog modal box with the enhanced keyboard dialog */
466 DialogBoxW(Globals
.hInstance
,
467 MAKEINTRESOURCEW(MAIN_DIALOG_ENHANCED_KB
),
475 case IDM_STANDARD_KB
:
477 if (Globals
.bIsEnhancedKeyboard
)
480 The user attempted to switch to standard keyboard dialog type.
481 Set the member value as FALSE, destroy the dialog and save the data configuration into the registry.
483 Globals
.bIsEnhancedKeyboard
= FALSE
;
484 EndDialog(hDlg
, FALSE
);
485 SaveDataToRegistry();
487 /* Change the condition of standard keyboard item menu to checked */
488 CheckMenuItem(GetMenu(hDlg
), IDM_ENHANCED_KB
, MF_BYCOMMAND
| MF_UNCHECKED
);
489 CheckMenuItem(GetMenu(hDlg
), IDM_STANDARD_KB
, MF_BYCOMMAND
| MF_CHECKED
);
491 /* Finally, display the dialog modal box with the standard keyboard dialog */
492 DialogBoxW(Globals
.hInstance
,
493 MAKEINTRESOURCEW(MAIN_DIALOG_STANDARD_KB
),
508 OSK_DlgCommand(wParam
, (HWND
)lParam
);
521 /***********************************************************************
525 int WINAPI
wWinMain(HINSTANCE hInstance
,
533 UNREFERENCED_PARAMETER(prev
);
534 UNREFERENCED_PARAMETER(cmdline
);
535 UNREFERENCED_PARAMETER(show
);
537 ZeroMemory(&Globals
, sizeof(Globals
));
538 Globals
.hInstance
= hInstance
;
540 /* Load the settings from the registry hive */
541 LoadDataFromRegistry();
543 /* If the member of the struct (bShowWarning) is set then display the dialog box */
544 if (Globals
.bShowWarning
)
546 DialogBoxW(Globals
.hInstance
, MAKEINTRESOURCEW(IDD_WARNINGDIALOG_OSK
), Globals
.hMainWnd
, OSK_WarningProc
);
549 /* Before initializing the dialog execution, check if the chosen keyboard type is standard or enhanced */
550 if (Globals
.bIsEnhancedKeyboard
)
552 LayoutResource
= MAIN_DIALOG_ENHANCED_KB
;
556 LayoutResource
= MAIN_DIALOG_STANDARD_KB
;
559 /* Rry to open a mutex for a single instance */
560 hMutex
= OpenMutexW(MUTEX_ALL_ACCESS
, FALSE
, L
"osk");
564 /* Mutex doesn\92t exist. This is the first instance so create the mutex. */
565 hMutex
= CreateMutexW(NULL
, FALSE
, L
"osk");
567 /* Create the modal box based on the configuration registry */
568 DialogBoxW(hInstance
,
569 MAKEINTRESOURCEW(LayoutResource
),
573 /* Delete the mutex */
574 if (hMutex
) CloseHandle(hMutex
);
578 /* Programme already launched */
580 /* Delete the mutex */