1d05285ac23ea598b6ea80a9dc0b5a66b7dca620
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
);
43 if (hIcon
== NULL
) return FALSE
;
45 hWndItem
= GetDlgItem(Globals
.hMainWnd
, IdDlgItem
);
46 if (hWndItem
== NULL
) return FALSE
;
48 SendMessage(hWndItem
, BM_SETIMAGE
, (WPARAM
)IMAGE_ICON
, (LPARAM
)hIcon
);
50 /* The system automatically deletes these resources when the process that created them terminates (MSDN) */
56 /***********************************************************************
60 * Handling of WM_INITDIALOG
62 int OSK_DlgInitDialog(HWND hDlg
)
70 Globals
.hMainWnd
= hDlg
;
73 memset(&Pt
, 0, sizeof(Pt
));
74 monitor
= MonitorFromPoint(Pt
, MONITOR_DEFAULTTOPRIMARY
);
75 info
.cbSize
= sizeof(info
);
76 GetMonitorInfoW(monitor
, &info
);
78 /* Move the dialog on the bottom of main screen */
79 GetWindowRect(hDlg
, &rcWindow
);
81 (info
.rcMonitor
.left
+ info
.rcMonitor
.right
) / 2 - // Center of screen
82 (rcWindow
.right
- rcWindow
.left
) / 2, // - half size of dialog
83 info
.rcMonitor
.bottom
- // Bottom of screen
84 (rcWindow
.bottom
- rcWindow
.top
), // - size of window
85 rcWindow
.right
- rcWindow
.left
, // Width
86 rcWindow
.bottom
- rcWindow
.top
, // Height
89 /* Set icon on visual buttons */
90 OSK_SetImage(SCAN_CODE_15
, IDI_BACK
);
91 OSK_SetImage(SCAN_CODE_16
, IDI_TAB
);
92 OSK_SetImage(SCAN_CODE_30
, IDI_CAPS_LOCK
);
93 OSK_SetImage(SCAN_CODE_43
, IDI_RETURN
);
94 OSK_SetImage(SCAN_CODE_44
, IDI_SHIFT
);
95 OSK_SetImage(SCAN_CODE_57
, IDI_SHIFT
);
96 OSK_SetImage(SCAN_CODE_127
, IDI_REACTOS
);
97 OSK_SetImage(SCAN_CODE_128
, IDI_REACTOS
);
98 OSK_SetImage(SCAN_CODE_129
, IDI_MENU
);
99 OSK_SetImage(SCAN_CODE_80
, IDI_HOME
);
100 OSK_SetImage(SCAN_CODE_85
, IDI_PG_UP
);
101 OSK_SetImage(SCAN_CODE_86
, IDI_PG_DOWN
);
102 OSK_SetImage(SCAN_CODE_79
, IDI_LEFT
);
103 OSK_SetImage(SCAN_CODE_83
, IDI_TOP
);
104 OSK_SetImage(SCAN_CODE_84
, IDI_BOTTOM
);
105 OSK_SetImage(SCAN_CODE_89
, IDI_RIGHT
);
107 /* Create a green brush for leds */
108 Globals
.hBrushGreenLed
= CreateSolidBrush(RGB(0, 255, 0));
110 /* Set a timer for periodics tasks */
111 Globals
.iTimer
= SetTimer(hDlg
, 0, 200, NULL
);
116 /***********************************************************************
120 * Handling of WM_CLOSE
122 int OSK_DlgClose(void)
124 KillTimer(Globals
.hMainWnd
, Globals
.iTimer
);
126 /* Release Ctrl, Shift, Alt keys */
127 OSK_ReleaseKey(SCAN_CODE_44
); // Left shift
128 OSK_ReleaseKey(SCAN_CODE_57
); // Right shift
129 OSK_ReleaseKey(SCAN_CODE_58
); // Left ctrl
130 OSK_ReleaseKey(SCAN_CODE_60
); // Left alt
131 OSK_ReleaseKey(SCAN_CODE_62
); // Right alt
132 OSK_ReleaseKey(SCAN_CODE_64
); // Right ctrl
134 /* delete GDI objects */
135 if (Globals
.hBrushGreenLed
) DeleteObject(Globals
.hBrushGreenLed
);
140 /***********************************************************************
144 * Handling of WM_TIMER
146 int OSK_DlgTimer(void)
148 /* FIXME: To be deleted when Reactos will support WS_EX_NOACTIVATE */
149 HWND hWndActiveWindow
;
151 hWndActiveWindow
= GetForegroundWindow();
152 if (hWndActiveWindow
!= NULL
&& hWndActiveWindow
!= Globals
.hMainWnd
)
154 Globals
.hActiveWnd
= hWndActiveWindow
;
157 /* Always redraw leds because it can be changed by the real keyboard) */
158 InvalidateRect(GetDlgItem(Globals
.hMainWnd
, IDC_LED_NUM
), NULL
, TRUE
);
159 InvalidateRect(GetDlgItem(Globals
.hMainWnd
, IDC_LED_CAPS
), NULL
, TRUE
);
160 InvalidateRect(GetDlgItem(Globals
.hMainWnd
, IDC_LED_SCROLL
), NULL
, TRUE
);
165 /***********************************************************************
169 * All handling of dialog command
171 BOOL
OSK_DlgCommand(WPARAM wCommand
, HWND hWndControl
)
180 /* FIXME: To be deleted when Reactos will support WS_EX_NOACTIVATE */
181 if (Globals
.hActiveWnd
)
185 SetForegroundWindow(Globals
.hActiveWnd
);
186 while (PeekMessage(&msg
, 0, 0, 0, PM_REMOVE
))
188 TranslateMessage(&msg
);
189 DispatchMessage(&msg
);
193 /* KeyDown and/or KeyUp ? */
194 WindowStyle
= GetWindowLong(hWndControl
, GWL_STYLE
);
195 if ((WindowStyle
& BS_AUTOCHECKBOX
) == BS_AUTOCHECKBOX
)
197 /* 2-states key like Shift, Alt, Ctrl, ... */
198 if (SendMessage(hWndControl
, BM_GETCHECK
, 0, 0) == BST_CHECKED
)
218 if (ScanCode
& 0x0200)
221 bExtendedKey
= FALSE
;
224 /* Press and release the key */
227 Input
.type
= INPUT_KEYBOARD
;
229 Input
.ki
.wScan
= ScanCode
;
230 Input
.ki
.time
= GetTickCount();
231 Input
.ki
.dwExtraInfo
= GetMessageExtraInfo();
232 Input
.ki
.dwFlags
= KEYEVENTF_SCANCODE
;
233 if (bExtendedKey
) Input
.ki
.dwFlags
|= KEYEVENTF_EXTENDEDKEY
;
234 SendInput(1, &Input
, sizeof(Input
));
239 Input
.type
= INPUT_KEYBOARD
;
241 Input
.ki
.wScan
= ScanCode
;
242 Input
.ki
.time
= GetTickCount();
243 Input
.ki
.dwExtraInfo
= GetMessageExtraInfo();
244 Input
.ki
.dwFlags
= KEYEVENTF_SCANCODE
| KEYEVENTF_KEYUP
;
245 if (bExtendedKey
) Input
.ki
.dwFlags
|= KEYEVENTF_EXTENDEDKEY
;
246 SendInput(1, &Input
, sizeof(Input
));
252 /***********************************************************************
256 * Release the key of ID wCommand
258 BOOL
OSK_ReleaseKey(WORD ScanCode
)
265 /* Is it a 2-states key ? */
266 hWndControl
= GetDlgItem(Globals
.hMainWnd
, ScanCode
);
267 WindowStyle
= GetWindowLong(hWndControl
, GWL_STYLE
);
268 if ((WindowStyle
& BS_AUTOCHECKBOX
) != BS_AUTOCHECKBOX
) return FALSE
;
270 /* Is the key down ? */
271 if (SendMessage(hWndControl
, BM_GETCHECK
, 0, 0) != BST_CHECKED
) return TRUE
;
274 if (ScanCode
& 0x0200)
277 bExtendedKey
= FALSE
;
280 /* Release the key */
281 Input
.type
= INPUT_KEYBOARD
;
283 Input
.ki
.wScan
= ScanCode
;
284 Input
.ki
.time
= GetTickCount();
285 Input
.ki
.dwExtraInfo
= GetMessageExtraInfo();
286 Input
.ki
.dwFlags
= KEYEVENTF_SCANCODE
| KEYEVENTF_KEYUP
;
287 if (bExtendedKey
) Input
.ki
.dwFlags
|= KEYEVENTF_EXTENDEDKEY
;
288 SendInput(1, &Input
, sizeof(Input
));
293 /***********************************************************************
297 INT_PTR APIENTRY
OSK_DlgProc(HWND hDlg
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
302 OSK_DlgInitDialog(hDlg
);
309 case WM_CTLCOLORSTATIC
:
310 if ((HWND
)lParam
== GetDlgItem(hDlg
, IDC_LED_NUM
))
312 if (GetKeyState(VK_NUMLOCK
) & 0x0001)
313 return (INT_PTR
)Globals
.hBrushGreenLed
;
315 return (INT_PTR
)GetStockObject(BLACK_BRUSH
);
317 if ((HWND
)lParam
== GetDlgItem(hDlg
, IDC_LED_CAPS
))
319 if (GetKeyState(VK_CAPITAL
) & 0x0001)
320 return (INT_PTR
)Globals
.hBrushGreenLed
;
322 return (INT_PTR
)GetStockObject(BLACK_BRUSH
);
324 if ((HWND
)lParam
== GetDlgItem(hDlg
, IDC_LED_SCROLL
))
326 if (GetKeyState(VK_SCROLL
) & 0x0001)
327 return (INT_PTR
)Globals
.hBrushGreenLed
;
329 return (INT_PTR
)GetStockObject(BLACK_BRUSH
);
334 if (wParam
== IDCANCEL
)
335 EndDialog(hDlg
, FALSE
);
336 else if (wParam
!= IDC_STATIC
)
337 OSK_DlgCommand(wParam
, (HWND
) lParam
);
348 /***********************************************************************
352 int WINAPI
_tWinMain(HINSTANCE hInstance
,
359 UNREFERENCED_PARAMETER(prev
);
360 UNREFERENCED_PARAMETER(cmdline
);
361 UNREFERENCED_PARAMETER(show
);
363 ZeroMemory(&Globals
, sizeof(Globals
));
364 Globals
.hInstance
= hInstance
;
366 /* Rry to open a mutex for a single instance */
367 hMutex
= OpenMutexA(MUTEX_ALL_ACCESS
, FALSE
, "osk");
371 /* Mutex doesn\92t exist. This is the first instance so create the mutex. */
372 hMutex
= CreateMutexA(NULL
, FALSE
, "osk");
375 MAKEINTRESOURCE(MAIN_DIALOG
),
379 /* Delete the mutex */
380 if (hMutex
) CloseHandle(hMutex
);
384 /* Programme already launched */
386 /* Delete the mutex */