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 *******************************************************************/
13 /* GLOBALS ********************************************************************/
18 int OSK_SetImage(int IdDlgItem
, int IdResource
);
19 int OSK_DlgInitDialog(HWND hDlg
);
20 int OSK_DlgClose(void);
21 int OSK_DlgTimer(void);
22 BOOL
OSK_DlgCommand(WPARAM wCommand
, HWND hWndControl
);
23 BOOL
OSK_ReleaseKey(WORD ScanCode
);
25 INT_PTR APIENTRY
OSK_DlgProc(HWND hDlg
, UINT msg
, WPARAM wParam
, LPARAM lParam
);
26 int WINAPI
_tWinMain(HINSTANCE
, HINSTANCE
, LPTSTR
, int);
28 /* FUNCTIONS ******************************************************************/
30 /***********************************************************************
34 * Set an image on a button
36 int OSK_SetImage(int IdDlgItem
, int IdResource
)
41 hIcon
= (HICON
)LoadImage(Globals
.hInstance
, MAKEINTRESOURCE(IdResource
),
42 IMAGE_ICON
, 16, 16, LR_DEFAULTCOLOR
);
46 hWndItem
= GetDlgItem(Globals
.hMainWnd
, IdDlgItem
);
53 SendMessage(hWndItem
, BM_SETIMAGE
, (WPARAM
)IMAGE_ICON
, (LPARAM
)hIcon
);
55 /* The system automatically deletes these resources when the process that created them terminates (MSDN) */
61 /***********************************************************************
65 * Handling of WM_INITDIALOG
67 int OSK_DlgInitDialog(HWND hDlg
)
75 Globals
.hMainWnd
= hDlg
;
78 memset(&Pt
, 0, sizeof(Pt
));
79 monitor
= MonitorFromPoint(Pt
, MONITOR_DEFAULTTOPRIMARY
);
80 info
.cbSize
= sizeof(info
);
81 GetMonitorInfoW(monitor
, &info
);
83 /* Move the dialog on the bottom of main screen */
84 GetWindowRect(hDlg
, &rcWindow
);
86 (info
.rcMonitor
.left
+ info
.rcMonitor
.right
) / 2 - // Center of screen
87 (rcWindow
.right
- rcWindow
.left
) / 2, // - half size of dialog
88 info
.rcMonitor
.bottom
- // Bottom of screen
89 (rcWindow
.bottom
- rcWindow
.top
), // - size of window
90 rcWindow
.right
- rcWindow
.left
, // Width
91 rcWindow
.bottom
- rcWindow
.top
, // Height
94 /* Set icon on visual buttons */
95 OSK_SetImage(SCAN_CODE_15
, IDI_BACK
);
96 OSK_SetImage(SCAN_CODE_16
, IDI_TAB
);
97 OSK_SetImage(SCAN_CODE_30
, IDI_CAPS_LOCK
);
98 OSK_SetImage(SCAN_CODE_43
, IDI_RETURN
);
99 OSK_SetImage(SCAN_CODE_44
, IDI_SHIFT
);
100 OSK_SetImage(SCAN_CODE_57
, IDI_SHIFT
);
101 OSK_SetImage(SCAN_CODE_127
, IDI_REACTOS
);
102 OSK_SetImage(SCAN_CODE_128
, IDI_REACTOS
);
103 OSK_SetImage(SCAN_CODE_129
, IDI_MENU
);
104 OSK_SetImage(SCAN_CODE_80
, IDI_HOME
);
105 OSK_SetImage(SCAN_CODE_85
, IDI_PG_UP
);
106 OSK_SetImage(SCAN_CODE_86
, IDI_PG_DOWN
);
107 OSK_SetImage(SCAN_CODE_79
, IDI_LEFT
);
108 OSK_SetImage(SCAN_CODE_83
, IDI_TOP
);
109 OSK_SetImage(SCAN_CODE_84
, IDI_BOTTOM
);
110 OSK_SetImage(SCAN_CODE_89
, IDI_RIGHT
);
112 /* Create a green brush for leds */
113 Globals
.hBrushGreenLed
= CreateSolidBrush(RGB(0, 255, 0));
115 /* Set a timer for periodics tasks */
116 Globals
.iTimer
= SetTimer(hDlg
, 0, 200, NULL
);
121 /***********************************************************************
125 * Handling of WM_CLOSE
127 int OSK_DlgClose(void)
129 KillTimer(Globals
.hMainWnd
, Globals
.iTimer
);
131 /* Release Ctrl, Shift, Alt keys */
132 OSK_ReleaseKey(SCAN_CODE_44
); // Left shift
133 OSK_ReleaseKey(SCAN_CODE_57
); // Right shift
134 OSK_ReleaseKey(SCAN_CODE_58
); // Left ctrl
135 OSK_ReleaseKey(SCAN_CODE_60
); // Left alt
136 OSK_ReleaseKey(SCAN_CODE_62
); // Right alt
137 OSK_ReleaseKey(SCAN_CODE_64
); // Right ctrl
139 /* delete GDI objects */
140 if (Globals
.hBrushGreenLed
) DeleteObject(Globals
.hBrushGreenLed
);
145 /***********************************************************************
149 * Handling of WM_TIMER
151 int OSK_DlgTimer(void)
153 /* FIXME: To be deleted when ReactOS will support WS_EX_NOACTIVATE */
154 HWND hWndActiveWindow
;
156 hWndActiveWindow
= GetForegroundWindow();
157 if (hWndActiveWindow
!= NULL
&& hWndActiveWindow
!= Globals
.hMainWnd
)
159 Globals
.hActiveWnd
= hWndActiveWindow
;
162 /* Always redraw leds because it can be changed by the real keyboard) */
163 InvalidateRect(GetDlgItem(Globals
.hMainWnd
, IDC_LED_NUM
), NULL
, TRUE
);
164 InvalidateRect(GetDlgItem(Globals
.hMainWnd
, IDC_LED_CAPS
), NULL
, TRUE
);
165 InvalidateRect(GetDlgItem(Globals
.hMainWnd
, IDC_LED_SCROLL
), NULL
, TRUE
);
170 /***********************************************************************
174 * All handling of dialog command
176 BOOL
OSK_DlgCommand(WPARAM wCommand
, HWND hWndControl
)
185 /* FIXME: To be deleted when ReactOS will support WS_EX_NOACTIVATE */
186 if (Globals
.hActiveWnd
)
190 SetForegroundWindow(Globals
.hActiveWnd
);
191 while (PeekMessage(&msg
, 0, 0, 0, PM_REMOVE
))
193 TranslateMessage(&msg
);
194 DispatchMessage(&msg
);
198 /* KeyDown and/or KeyUp ? */
199 WindowStyle
= GetWindowLong(hWndControl
, GWL_STYLE
);
200 if ((WindowStyle
& BS_AUTOCHECKBOX
) == BS_AUTOCHECKBOX
)
202 /* 2-states key like Shift, Alt, Ctrl, ... */
203 if (SendMessage(hWndControl
, BM_GETCHECK
, 0, 0) == BST_CHECKED
)
223 if (ScanCode
& 0x0200)
226 bExtendedKey
= FALSE
;
229 /* Press and release the key */
232 Input
.type
= INPUT_KEYBOARD
;
234 Input
.ki
.wScan
= ScanCode
;
235 Input
.ki
.time
= GetTickCount();
236 Input
.ki
.dwExtraInfo
= GetMessageExtraInfo();
237 Input
.ki
.dwFlags
= KEYEVENTF_SCANCODE
;
238 if (bExtendedKey
) Input
.ki
.dwFlags
|= KEYEVENTF_EXTENDEDKEY
;
239 SendInput(1, &Input
, sizeof(Input
));
244 Input
.type
= INPUT_KEYBOARD
;
246 Input
.ki
.wScan
= ScanCode
;
247 Input
.ki
.time
= GetTickCount();
248 Input
.ki
.dwExtraInfo
= GetMessageExtraInfo();
249 Input
.ki
.dwFlags
= KEYEVENTF_SCANCODE
| KEYEVENTF_KEYUP
;
250 if (bExtendedKey
) Input
.ki
.dwFlags
|= KEYEVENTF_EXTENDEDKEY
;
251 SendInput(1, &Input
, sizeof(Input
));
257 /***********************************************************************
261 * Release the key of ID wCommand
263 BOOL
OSK_ReleaseKey(WORD ScanCode
)
270 /* Is it a 2-states key ? */
271 hWndControl
= GetDlgItem(Globals
.hMainWnd
, ScanCode
);
272 WindowStyle
= GetWindowLong(hWndControl
, GWL_STYLE
);
273 if ((WindowStyle
& BS_AUTOCHECKBOX
) != BS_AUTOCHECKBOX
) return FALSE
;
275 /* Is the key down ? */
276 if (SendMessage(hWndControl
, BM_GETCHECK
, 0, 0) != BST_CHECKED
) return TRUE
;
279 if (ScanCode
& 0x0200)
282 bExtendedKey
= FALSE
;
285 /* Release the key */
286 Input
.type
= INPUT_KEYBOARD
;
288 Input
.ki
.wScan
= ScanCode
;
289 Input
.ki
.time
= GetTickCount();
290 Input
.ki
.dwExtraInfo
= GetMessageExtraInfo();
291 Input
.ki
.dwFlags
= KEYEVENTF_SCANCODE
| KEYEVENTF_KEYUP
;
292 if (bExtendedKey
) Input
.ki
.dwFlags
|= KEYEVENTF_EXTENDEDKEY
;
293 SendInput(1, &Input
, sizeof(Input
));
298 /***********************************************************************
302 INT_PTR APIENTRY
OSK_DlgProc(HWND hDlg
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
307 OSK_DlgInitDialog(hDlg
);
314 case WM_CTLCOLORSTATIC
:
315 if ((HWND
)lParam
== GetDlgItem(hDlg
, IDC_LED_NUM
))
317 if (GetKeyState(VK_NUMLOCK
) & 0x0001)
318 return (INT_PTR
)Globals
.hBrushGreenLed
;
320 return (INT_PTR
)GetStockObject(BLACK_BRUSH
);
322 if ((HWND
)lParam
== GetDlgItem(hDlg
, IDC_LED_CAPS
))
324 if (GetKeyState(VK_CAPITAL
) & 0x0001)
325 return (INT_PTR
)Globals
.hBrushGreenLed
;
327 return (INT_PTR
)GetStockObject(BLACK_BRUSH
);
329 if ((HWND
)lParam
== GetDlgItem(hDlg
, IDC_LED_SCROLL
))
331 if (GetKeyState(VK_SCROLL
) & 0x0001)
332 return (INT_PTR
)Globals
.hBrushGreenLed
;
334 return (INT_PTR
)GetStockObject(BLACK_BRUSH
);
339 if (wParam
== IDCANCEL
)
340 EndDialog(hDlg
, FALSE
);
341 else if (wParam
!= IDC_STATIC
)
342 OSK_DlgCommand(wParam
, (HWND
) lParam
);
353 /***********************************************************************
357 int WINAPI
_tWinMain(HINSTANCE hInstance
,
364 UNREFERENCED_PARAMETER(prev
);
365 UNREFERENCED_PARAMETER(cmdline
);
366 UNREFERENCED_PARAMETER(show
);
368 ZeroMemory(&Globals
, sizeof(Globals
));
369 Globals
.hInstance
= hInstance
;
371 /* Rry to open a mutex for a single instance */
372 hMutex
= OpenMutexA(MUTEX_ALL_ACCESS
, FALSE
, "osk");
376 /* Mutex doesn\92t exist. This is the first instance so create the mutex. */
377 hMutex
= CreateMutexA(NULL
, FALSE
, "osk");
380 MAKEINTRESOURCE(MAIN_DIALOG
),
384 /* Delete the mutex */
385 if (hMutex
) CloseHandle(hMutex
);
389 /* Programme already launched */
391 /* Delete the mutex */