1 /*
2 * PROJECT: ReactOS Accessibility Control Panel
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: dll/cpl/access/display.c
5 * PURPOSE: Display-related accessibility settings
6 * COPYRIGHT: Copyright 2004 Johannes Anderwald (johannes.anderwald@reactos.org)
7 * Copyright 2007 Eric Kohl
8 */
9
10 #include "access.h"
11
12 #include <wingdi.h>
13
14 #define ID_BLINK_TIMER 346
15
16 static VOID
UpdateCaretBlinkTimeReg(_In_ UINT uCaretBlinkTime)17 UpdateCaretBlinkTimeReg(
18 _In_ UINT uCaretBlinkTime)
19 {
20 HKEY hKey;
21 WCHAR szBuffer[12];
22
23 if (RegOpenKeyExW(HKEY_CURRENT_USER,
24 L"Control Panel\\Desktop",
25 0, KEY_SET_VALUE,
26 &hKey) != ERROR_SUCCESS)
27 {
28 return;
29 }
30
31 wsprintf(szBuffer, L"%d", uCaretBlinkTime);
32
33 RegSetValueExW(hKey, L"CursorBlinkRate",
34 0, REG_SZ,
35 (CONST BYTE*)szBuffer,
36 (wcslen(szBuffer) + 1) * sizeof(WCHAR));
37
38 RegCloseKey(hKey);
39 }
40
41 static VOID
FillColorSchemeComboBox(HWND hwnd)42 FillColorSchemeComboBox(HWND hwnd)
43 {
44 TCHAR szValue[128];
45 DWORD dwDisposition;
46 DWORD dwLength;
47 HKEY hKey;
48 LONG lError;
49 INT i;
50
51 lError = RegCreateKeyEx(HKEY_CURRENT_USER,
52 _T("Control Panel\\Appearance\\Schemes"),
53 0,
54 NULL,
55 REG_OPTION_NON_VOLATILE,
56 KEY_ENUMERATE_SUB_KEYS | KEY_EXECUTE | KEY_QUERY_VALUE,
57 NULL,
58 &hKey,
59 &dwDisposition);
60 if (lError != ERROR_SUCCESS)
61 return;
62
63 for (i = 0; ; i++)
64 {
65 dwLength = 128;
66 lError = RegEnumValue(hKey,
67 i,
68 szValue,
69 &dwLength, NULL, NULL, NULL, NULL);
70 if (lError == ERROR_NO_MORE_ITEMS)
71 break;
72
73 SendMessage(hwnd,
74 CB_ADDSTRING,
75 0,
76 (LPARAM)szValue);
77 }
78
79 RegCloseKey(hKey);
80 }
81
82
83 INT_PTR CALLBACK
HighContrastDlgProc(HWND hwndDlg,UINT uMsg,WPARAM wParam,LPARAM lParam)84 HighContrastDlgProc(HWND hwndDlg,
85 UINT uMsg,
86 WPARAM wParam,
87 LPARAM lParam)
88 {
89 PGLOBAL_DATA pGlobalData;
90
91 pGlobalData = (PGLOBAL_DATA)GetWindowLongPtr(hwndDlg, DWLP_USER);
92
93 switch (uMsg)
94 {
95 case WM_INITDIALOG:
96 pGlobalData = (PGLOBAL_DATA)lParam;
97 SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)pGlobalData);
98
99 CheckDlgButton(hwndDlg,
100 IDC_CONTRAST_ACTIVATE_CHECK,
101 pGlobalData->highContrast.dwFlags & HCF_HOTKEYACTIVE ? BST_CHECKED : BST_UNCHECKED);
102
103 FillColorSchemeComboBox(GetDlgItem(hwndDlg, IDC_CONTRAST_COMBO));
104
105 SendDlgItemMessage(hwndDlg,
106 IDC_CONTRAST_COMBO,
107 CB_SELECTSTRING,
108 (WPARAM)-1,
109 (LPARAM)pGlobalData->highContrast.lpszDefaultScheme);
110 break;
111
112 case WM_COMMAND:
113 switch (LOWORD(wParam))
114 {
115 case IDC_CONTRAST_ACTIVATE_CHECK:
116 pGlobalData->highContrast.dwFlags ^= HCF_HOTKEYACTIVE;
117 break;
118
119 case IDC_CONTRAST_COMBO:
120 if (HIWORD(wParam) == CBN_SELCHANGE)
121 {
122 INT nSel;
123
124 nSel = SendDlgItemMessage(hwndDlg, IDC_CONTRAST_COMBO,
125 CB_GETCURSEL, 0, 0);
126 SendDlgItemMessage(hwndDlg, IDC_CONTRAST_COMBO,
127 CB_GETLBTEXT, nSel,
128 (LPARAM)pGlobalData->highContrast.lpszDefaultScheme);
129 }
130 break;
131
132 case IDOK:
133 EndDialog(hwndDlg, TRUE);
134 break;
135
136 case IDCANCEL:
137 EndDialog(hwndDlg, FALSE);
138 break;
139
140 default:
141 break;
142 }
143 break;
144 }
145
146 return FALSE;
147 }
148
149
150 /* Property page dialog callback */
151 INT_PTR CALLBACK
DisplayPageProc(HWND hwndDlg,UINT uMsg,WPARAM wParam,LPARAM lParam)152 DisplayPageProc(HWND hwndDlg,
153 UINT uMsg,
154 WPARAM wParam,
155 LPARAM lParam)
156 {
157 PGLOBAL_DATA pGlobalData;
158 LPPSHNOTIFY lppsn;
159 INT i;
160
161 pGlobalData = (PGLOBAL_DATA)GetWindowLongPtr(hwndDlg, DWLP_USER);
162
163 switch (uMsg)
164 {
165 case WM_INITDIALOG:
166 pGlobalData = (PGLOBAL_DATA)((LPPROPSHEETPAGE)lParam)->lParam;
167 if (pGlobalData == NULL)
168 return FALSE;
169
170 SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)pGlobalData);
171
172 pGlobalData->fShowCaret = TRUE;
173 GetWindowRect(GetDlgItem(hwndDlg, IDC_CURSOR_WIDTH_TEXT), &pGlobalData->rcCaret);
174 ScreenToClient(hwndDlg, (LPPOINT)&pGlobalData->rcCaret.left);
175 ScreenToClient(hwndDlg, (LPPOINT)&pGlobalData->rcCaret.right);
176 CopyRect(&pGlobalData->rcOldCaret, &pGlobalData->rcCaret);
177
178 pGlobalData->rcCaret.right = pGlobalData->rcCaret.left + pGlobalData->uCaretWidth;
179
180 /* Set the checkbox */
181 CheckDlgButton(hwndDlg,
182 IDC_CONTRAST_BOX,
183 pGlobalData->highContrast.dwFlags & HCF_HIGHCONTRASTON ? BST_CHECKED : BST_UNCHECKED);
184
185 SendDlgItemMessage(hwndDlg, IDC_CURSOR_BLINK_TRACK, TBM_SETRANGE, (WPARAM)TRUE, (LPARAM)MAKELONG(0, 10));
186 SendDlgItemMessage(hwndDlg, IDC_CURSOR_BLINK_TRACK, TBM_SETPOS, (WPARAM)TRUE, (LPARAM)(12 - (pGlobalData->uCaretBlinkTime / 100)));
187
188 SendDlgItemMessage(hwndDlg, IDC_CURSOR_WIDTH_TRACK, TBM_SETRANGE, (WPARAM)TRUE, (LPARAM)MAKELONG(0, 19));
189 SendDlgItemMessage(hwndDlg, IDC_CURSOR_WIDTH_TRACK, TBM_SETPOS, (WPARAM)TRUE, (LPARAM)(pGlobalData->uCaretWidth - 1));
190
191 /* Start the blink timer */
192 pGlobalData->uCaretBlinkTime = pGlobalData->uCaretBlinkTime >= 1200 ? -1 : pGlobalData->uCaretBlinkTime;
193 if ((INT)pGlobalData->uCaretBlinkTime > 0)
194 {
195 SetTimer(hwndDlg, ID_BLINK_TIMER, pGlobalData->uCaretBlinkTime, NULL);
196 }
197 else
198 {
199 PostMessage(hwndDlg, WM_TIMER, ID_BLINK_TIMER, 0);
200 }
201
202 return TRUE;
203
204 case WM_COMMAND:
205 switch (LOWORD(wParam))
206 {
207 case IDC_CONTRAST_BOX:
208 pGlobalData->highContrast.dwFlags ^= HCF_HIGHCONTRASTON;
209 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
210 break;
211
212 case IDC_CONTRAST_BUTTON:
213 if (DialogBoxParam(hApplet,
214 MAKEINTRESOURCE(IDD_CONTRASTOPTIONS),
215 hwndDlg,
216 HighContrastDlgProc,
217 (LPARAM)pGlobalData))
218 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
219 break;
220
221 default:
222 break;
223 }
224 break;
225
226 case WM_HSCROLL:
227 switch (GetWindowLongPtr((HWND) lParam, GWL_ID))
228 {
229 case IDC_CURSOR_BLINK_TRACK:
230 i = SendDlgItemMessage(hwndDlg, IDC_CURSOR_BLINK_TRACK, TBM_GETPOS, 0, 0);
231 pGlobalData->uCaretBlinkTime = (12 - (UINT)i) * 100;
232 KillTimer(hwndDlg, ID_BLINK_TIMER);
233 pGlobalData->uCaretBlinkTime = pGlobalData->uCaretBlinkTime >= 1200 ? -1 : pGlobalData->uCaretBlinkTime;
234 if ((INT)pGlobalData->uCaretBlinkTime > 0)
235 {
236 SetTimer(hwndDlg, ID_BLINK_TIMER, pGlobalData->uCaretBlinkTime, NULL);
237 }
238 else if (pGlobalData->fShowCaret)
239 {
240 SendMessage(hwndDlg, WM_TIMER, ID_BLINK_TIMER, 0);
241 }
242 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
243 break;
244
245 case IDC_CURSOR_WIDTH_TRACK:
246 i = SendDlgItemMessage(hwndDlg, IDC_CURSOR_WIDTH_TRACK, TBM_GETPOS, 0, 0);
247 pGlobalData->uCaretWidth = (UINT)i + 1;
248 pGlobalData->rcCaret.right = pGlobalData->rcCaret.left + pGlobalData->uCaretWidth;
249 if (pGlobalData->fShowCaret)
250 {
251 HDC hDC = GetDC(hwndDlg);
252 HBRUSH hBrush = GetSysColorBrush(COLOR_BTNTEXT);
253 FillRect(hDC, &pGlobalData->rcCaret, hBrush);
254 ReleaseDC(hwndDlg, hDC);
255 }
256 else
257 {
258 InvalidateRect(hwndDlg, &pGlobalData->rcOldCaret, TRUE);
259 }
260 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
261 break;
262 }
263 break;
264
265 case WM_TIMER:
266 if (wParam == ID_BLINK_TIMER)
267 {
268 if (pGlobalData->fShowCaret)
269 {
270 HDC hDC = GetDC(hwndDlg);
271 HBRUSH hBrush = GetSysColorBrush(COLOR_BTNTEXT);
272 FillRect(hDC, &pGlobalData->rcCaret, hBrush);
273 ReleaseDC(hwndDlg, hDC);
274 }
275 else
276 {
277 InvalidateRect(hwndDlg, &pGlobalData->rcOldCaret, TRUE);
278 }
279
280 pGlobalData->fShowCaret = !pGlobalData->fShowCaret;
281 }
282 break;
283
284 case WM_NOTIFY:
285 lppsn = (LPPSHNOTIFY)lParam;
286 if (lppsn->hdr.code == PSN_APPLY)
287 {
288 if (SetCaretBlinkTime(pGlobalData->uCaretBlinkTime))
289 {
290 UpdateCaretBlinkTimeReg(pGlobalData->uCaretBlinkTime);
291 }
292
293 SystemParametersInfo(SPI_SETCARETWIDTH,
294 0,
295 IntToPtr(pGlobalData->uCaretWidth),
296 SPIF_UPDATEINIFILE | SPIF_SENDCHANGE /*0*/);
297 SystemParametersInfo(SPI_SETHIGHCONTRAST,
298 sizeof(HIGHCONTRAST),
299 &pGlobalData->highContrast,
300 SPIF_UPDATEINIFILE | SPIF_SENDCHANGE /*0*/);
301 return TRUE;
302 }
303 break;
304
305 case WM_DESTROY:
306 KillTimer(hwndDlg, ID_BLINK_TIMER);
307 break;
308 }
309
310 return FALSE;
311 }
312