xref: /reactos/dll/cpl/access/display.c (revision c0eb4071)
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