[MAGNIFIER]: Code formatting.
[reactos.git] / reactos / base / applications / magnify / magnifier.c
1 /*
2 * PROJECT: ReactOS Magnify
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: base/applications/magnify/magnifier.c
5 * PURPOSE: Magnification of parts of the screen.
6 * COPYRIGHT: Copyright 2007 Marc Piulachs <marc.piulachs@codexchange.net>
7 *
8 */
9
10 /* TODO: AppBar */
11 #include "magnifier.h"
12
13 #include <winbase.h>
14 #include <winuser.h>
15 #include <wingdi.h>
16 #include <winnls.h>
17
18 #include "resource.h"
19
20 const TCHAR szWindowClass[] = TEXT("MAGNIFIER");
21
22 #define MAX_LOADSTRING 100
23
24 /* Global Variables */
25 HINSTANCE hInst;
26 HWND hMainWnd;
27
28 TCHAR szTitle[MAX_LOADSTRING];
29
30 #define REPAINT_SPEED 100
31
32 HWND hDesktopWindow = NULL;
33
34 /* Current magnified area /*
35 POINT cp;
36
37 /* Last positions */
38 POINT pMouse;
39 POINT pCaret;
40 POINT pFocus;
41
42 ATOM MyRegisterClass(HINSTANCE hInstance);
43 BOOL InitInstance(HINSTANCE, int);
44 LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
45 INT_PTR CALLBACK AboutProc(HWND, UINT, WPARAM, LPARAM);
46 INT_PTR CALLBACK OptionsProc(HWND, UINT, WPARAM, LPARAM);
47 INT_PTR CALLBACK WarningProc(HWND, UINT, WPARAM, LPARAM);
48
49 int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
50 {
51 MSG msg;
52 HACCEL hAccelTable;
53
54 UNREFERENCED_PARAMETER(hPrevInstance);
55 UNREFERENCED_PARAMETER(lpCmdLine);
56
57 switch (GetUserDefaultUILanguage())
58 {
59 case MAKELANGID(LANG_HEBREW, SUBLANG_DEFAULT):
60 SetProcessDefaultLayout(LAYOUT_RTL);
61 break;
62
63 default:
64 break;
65 }
66
67 /* Initialize global strings */
68 LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
69 MyRegisterClass(hInstance);
70
71 /* Perform application initialization */
72 if (!InitInstance(hInstance, nCmdShow))
73 return FALSE;
74
75 hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_MAGNIFIER));
76
77 /* Main message loop */
78 while (GetMessage(&msg, NULL, 0, 0))
79 {
80 if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
81 {
82 TranslateMessage(&msg);
83 DispatchMessage(&msg);
84 }
85 }
86
87 return (int) msg.wParam;
88 }
89
90 ATOM MyRegisterClass(HINSTANCE hInstance)
91 {
92 WNDCLASS wc;
93
94 wc.style = CS_HREDRAW | CS_VREDRAW;
95 wc.lpfnWndProc = WndProc;
96 wc.cbClsExtra = 0;
97 wc.cbWndExtra = 0;
98 wc.hInstance = hInstance;
99 wc.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_ICON));
100 wc.hCursor = LoadCursor(NULL, IDC_ARROW);
101 wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
102 wc.lpszMenuName = MAKEINTRESOURCE(IDC_MAGNIFIER);
103 wc.lpszClassName = szWindowClass;
104
105 return RegisterClass(&wc);
106 }
107
108 BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
109 {
110 RECT rcWorkArea;
111 hInst = hInstance; // Store instance handle in our global variable
112
113 SystemParametersInfo(SPI_GETWORKAREA, 0, &rcWorkArea, 0);
114
115 /* Create the Window */
116 hMainWnd = CreateWindowEx(
117 WS_EX_TOPMOST | WS_EX_PALETTEWINDOW,
118 szWindowClass,
119 szTitle,
120 WS_OVERLAPPEDWINDOW,
121 CW_USEDEFAULT,
122 CW_USEDEFAULT,
123 (rcWorkArea.right - rcWorkArea.left) * 2 / 3,
124 200,
125 NULL,
126 NULL,
127 hInstance,
128 NULL);
129
130 if (!hMainWnd)
131 return FALSE;
132
133 ShowWindow(hMainWnd, bStartMinimized ? SW_MINIMIZE : nCmdShow);
134 UpdateWindow(hMainWnd);
135
136 if (bShowWarning)
137 DialogBox(hInstance, MAKEINTRESOURCE(IDD_WARNINGDIALOG), hMainWnd, WarningProc);
138
139 return TRUE;
140 }
141
142 void Refresh()
143 {
144 if (!IsIconic(hMainWnd))
145 {
146 /* Invalidate the client area forcing a WM_PAINT message */
147 InvalidateRgn(hMainWnd, NULL, TRUE);
148 }
149 }
150
151 void Draw(HDC aDc)
152 {
153 HDC desktopHdc = NULL;
154 HDC HdcStrech;
155 HANDLE hOld;
156 HBITMAP HbmpStrech;
157
158 RECT R;
159 RECT appRect;
160 DWORD rop = SRCCOPY;
161 CURSORINFO cinfo;
162 ICONINFO iinfo;
163
164 int Width, Height, AppWidth, AppHeight;
165 LONG blitAreaWidth, blitAreaHeight, blitAreaX, blitAreaY;
166
167 desktopHdc = GetWindowDC(hDesktopWindow);
168
169 GetClientRect(hMainWnd, &appRect);
170 GetWindowRect(hDesktopWindow, &R);
171
172 ZeroMemory(&cinfo, sizeof(cinfo));
173 ZeroMemory(&iinfo, sizeof(iinfo));
174 cinfo.cbSize = sizeof(cinfo);
175 GetCursorInfo(&cinfo);
176 GetIconInfo(cinfo.hCursor, &iinfo);
177
178 /* Create a memory DC compatible with client area DC */
179 HdcStrech = CreateCompatibleDC(desktopHdc);
180
181 /* Create a bitmap compatible with the client area DC */
182 HbmpStrech = CreateCompatibleBitmap(
183 desktopHdc,
184 R.right,
185 R.bottom);
186
187 /* Select our bitmap in memory DC and save the old one */
188 hOld = SelectObject(HdcStrech , HbmpStrech);
189
190 /* Paint the screen bitmap to our in memory DC */
191 BitBlt(
192 HdcStrech,
193 0,
194 0,
195 R.right,
196 R.bottom,
197 desktopHdc,
198 0,
199 0,
200 SRCCOPY);
201
202 /* Draw the mouse pointer in the right position */
203 DrawIcon(
204 HdcStrech ,
205 pMouse.x - iinfo.xHotspot, // - 10,
206 pMouse.y - iinfo.yHotspot, // - 10,
207 cinfo.hCursor);
208
209 Width = (R.right - R.left);
210 Height = (R.bottom - R.top);
211
212 AppWidth = (appRect.right - appRect.left);
213 AppHeight = (appRect.bottom - appRect.top);
214
215 blitAreaWidth = AppWidth / iZoom;
216 blitAreaHeight = AppHeight / iZoom;
217
218 blitAreaX = (cp.x) - (blitAreaWidth /2);
219 blitAreaY = (cp.y) - (blitAreaHeight /2);
220
221 if (blitAreaX < 0)
222 blitAreaX = 0;
223
224 if (blitAreaY < 0)
225 blitAreaY = 0;
226
227 if (blitAreaX > (Width - blitAreaWidth))
228 blitAreaX = (Width - blitAreaWidth);
229
230 if (blitAreaY > (Height - blitAreaHeight))
231 blitAreaY = (Height - blitAreaHeight);
232
233 if (bInvertColors)
234 rop = NOTSRCCOPY;
235
236 /* Blast the stretched image from memory DC to window DC */
237 StretchBlt(
238 aDc,
239 0,
240 0,
241 AppWidth,
242 AppHeight,
243 HdcStrech,
244 blitAreaX,
245 blitAreaY,
246 blitAreaWidth,
247 blitAreaHeight,
248 rop | NOMIRRORBITMAP);
249
250
251 /* Cleanup */
252 if (iinfo.hbmMask)
253 DeleteObject(iinfo.hbmMask);
254 if (iinfo.hbmColor)
255 DeleteObject(iinfo.hbmColor);
256 SelectObject(HdcStrech, hOld);
257 DeleteObject (HbmpStrech);
258 DeleteDC(HdcStrech);
259 ReleaseDC(hDesktopWindow, desktopHdc);
260 }
261
262 LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
263 {
264 int wmId;
265
266 switch (message)
267 {
268 case WM_TIMER:
269 {
270 POINT pNewMouse;
271 POINT pNewCaret;
272 POINT pNewFocus;
273 HWND hwnd1, hwnd2, hwnd3;
274 DWORD a, b;
275 RECT controlRect;
276
277 //Get current mouse position
278 GetCursorPos (&pNewMouse);
279
280 //Get caret position
281 hwnd1 = GetForegroundWindow ();
282 a = GetWindowThreadProcessId(hwnd1, NULL);
283 b = GetCurrentThreadId();
284 AttachThreadInput (a, b, TRUE);
285 hwnd2 = GetFocus();
286
287 GetCaretPos( &pNewCaret);
288 ClientToScreen (hwnd2, (LPPOINT) &pNewCaret);
289 AttachThreadInput (a, b, FALSE);
290
291 //Get current control focus
292 hwnd3 = GetFocus ();
293 GetWindowRect (hwnd3 , &controlRect);
294 pNewFocus.x = controlRect.left;
295 pNewFocus.y = controlRect.top;
296
297 //If mouse has moved ....
298 if (((pMouse.x != pNewMouse.x) || (pMouse.y != pNewMouse.y)) && bFollowMouse)
299 {
300 //Update to new position
301 pMouse = pNewMouse;
302 cp = pNewMouse;
303 }
304 else if (((pCaret.x != pNewCaret.x) || (pCaret.y != pNewCaret.y)) && bFollowCaret)
305 {
306 //Update to new position
307 pCaret = pNewCaret;
308 cp = pNewCaret;
309 }
310 else if (((pFocus.x != pNewFocus.x) || (pFocus.y != pNewFocus.y)) && bFollowFocus)
311 {
312 //Update to new position
313 pFocus = pNewFocus;
314 cp = pNewFocus;
315 }
316 Refresh();
317 }
318 break;
319
320 case WM_COMMAND:
321 {
322 wmId = LOWORD(wParam);
323 /* Parse the menu selections */
324 switch (wmId)
325 {
326 case IDM_OPTIONS:
327 DialogBox(hInst, MAKEINTRESOURCE(IDD_DIALOGOPTIONS), hWnd, OptionsProc);
328 break;
329 case IDM_ABOUT:
330 DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, AboutProc);
331 break;
332 case IDM_EXIT:
333 DestroyWindow(hWnd);
334 break;
335 default:
336 return DefWindowProc(hWnd, message, wParam, lParam);
337 }
338 break;
339 }
340
341 case WM_PAINT:
342 {
343 PAINTSTRUCT PaintStruct;
344 HDC dc;
345 dc = BeginPaint(hWnd, &PaintStruct);
346 Draw(dc);
347 EndPaint(hWnd, &PaintStruct);
348 break;
349 }
350
351 case WM_ERASEBKGND:
352 // handle WM_ERASEBKGND by simply returning non-zero because we did all the drawing in WM_PAINT.
353 break;
354
355 case WM_DESTROY:
356 /* Save settings to registry */
357 SaveSettings();
358 KillTimer(hWnd , 1);
359 PostQuitMessage(0);
360 break;
361
362 case WM_CREATE:
363 /* Load settings from registry */
364 LoadSettings();
365
366 /* Get the desktop window */
367 hDesktopWindow = GetDesktopWindow();
368
369 /* Set the timer */
370 SetTimer (hWnd , 1, REPAINT_SPEED , NULL);
371 break;
372
373 default:
374 return DefWindowProc(hWnd, message, wParam, lParam);
375 }
376
377 return 0;
378 }
379
380 INT_PTR CALLBACK AboutProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
381 {
382 UNREFERENCED_PARAMETER(lParam);
383 switch (message)
384 {
385 case WM_INITDIALOG:
386 return (INT_PTR)TRUE;
387
388 case WM_COMMAND:
389 if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
390 {
391 EndDialog(hDlg, LOWORD(wParam));
392 return (INT_PTR)TRUE;
393 }
394 break;
395 }
396
397 return (INT_PTR)FALSE;
398 }
399
400 INT_PTR CALLBACK OptionsProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
401 {
402 UNREFERENCED_PARAMETER(lParam);
403 switch (message)
404 {
405 case WM_INITDIALOG:
406 {
407 // Add the zoom items...
408 SendDlgItemMessage(hDlg, IDC_ZOOM, CB_ADDSTRING, 0, (LPARAM)("1"));
409 SendDlgItemMessage(hDlg, IDC_ZOOM, CB_ADDSTRING, 0, (LPARAM)("2"));
410 SendDlgItemMessage(hDlg, IDC_ZOOM, CB_ADDSTRING, 0, (LPARAM)("3"));
411 SendDlgItemMessage(hDlg, IDC_ZOOM, CB_ADDSTRING, 0, (LPARAM)("4"));
412 SendDlgItemMessage(hDlg, IDC_ZOOM, CB_ADDSTRING, 0, (LPARAM)("5"));
413 SendDlgItemMessage(hDlg, IDC_ZOOM, CB_ADDSTRING, 0, (LPARAM)("6"));
414 SendDlgItemMessage(hDlg, IDC_ZOOM, CB_ADDSTRING, 0, (LPARAM)("7"));
415 SendDlgItemMessage(hDlg, IDC_ZOOM, CB_ADDSTRING, 0, (LPARAM)("8"));
416
417 SendDlgItemMessage(hDlg, IDC_ZOOM, CB_SETCURSEL, iZoom - 1, 0);
418
419 if (bFollowMouse)
420 SendDlgItemMessage(hDlg,IDC_FOLLOWMOUSECHECK,BM_SETCHECK , wParam ,0);
421
422 if (bFollowFocus)
423 SendDlgItemMessage(hDlg,IDC_FOLLOWKEYBOARDCHECK,BM_SETCHECK , wParam ,0);
424
425 if (bFollowCaret)
426 SendDlgItemMessage(hDlg,IDC_FOLLOWTEXTEDITINGCHECK,BM_SETCHECK , wParam ,0);
427
428 if (bInvertColors)
429 SendDlgItemMessage(hDlg,IDC_INVERTCOLORSCHECK,BM_SETCHECK , wParam ,0);
430
431 if (bStartMinimized)
432 SendDlgItemMessage(hDlg,IDC_STARTMINIMIZEDCHECK,BM_SETCHECK , wParam ,0);
433
434 if (bShowMagnifier)
435 SendDlgItemMessage(hDlg,IDC_SHOWMAGNIFIERCHECK,BM_SETCHECK , wParam ,0);
436
437 return (INT_PTR)TRUE;
438 }
439
440 case WM_COMMAND:
441 switch (LOWORD(wParam))
442 {
443 case IDOK:
444 case IDCANCEL:
445 EndDialog(hDlg, LOWORD(wParam));
446 return (INT_PTR)TRUE;
447
448 case IDC_BUTTON_HELP:
449 /* Unimplemented */
450 MessageBox(hDlg , TEXT("Magnifier help not available yet!") , TEXT("Help") , MB_OK);
451 break;
452 case IDC_ZOOM:
453 if (HIWORD(wParam) == CBN_SELCHANGE)
454 {
455 HWND hCombo = GetDlgItem(hDlg,IDC_ZOOM);
456
457 /* Get index of current selection and the text of that selection */
458 iZoom = SendMessage( hCombo, CB_GETCURSEL, (WPARAM) wParam, (LPARAM) lParam ) + 1;
459
460 /* Update the magnifier UI */
461 Refresh();
462 }
463 break;
464 case IDC_INVERTCOLORSCHECK:
465 bInvertColors = IsDlgButtonChecked(hDlg, IDC_INVERTCOLORSCHECK);
466 Refresh();
467 break;
468 case IDC_FOLLOWMOUSECHECK:
469 bFollowMouse = IsDlgButtonChecked(hDlg, IDC_FOLLOWMOUSECHECK);
470 break;
471 case IDC_FOLLOWKEYBOARDCHECK:
472 bFollowFocus = IsDlgButtonChecked(hDlg, IDC_FOLLOWKEYBOARDCHECK);
473 break;
474 case IDC_FOLLOWTEXTEDITINGCHECK:
475 bFollowCaret = IsDlgButtonChecked(hDlg, IDC_FOLLOWTEXTEDITINGCHECK);
476 break;
477 case IDC_STARTMINIMIZEDCHECK:
478 bStartMinimized = IsDlgButtonChecked(hDlg, IDC_STARTMINIMIZEDCHECK);
479 break;
480 case IDC_SHOWMAGNIFIER:
481 bShowMagnifier = IsDlgButtonChecked(hDlg, IDC_SHOWMAGNIFIERCHECK);
482 if (bShowMagnifier)
483 ShowWindow (hMainWnd , SW_SHOW);
484 else
485 ShowWindow (hMainWnd , SW_HIDE);
486 break;
487 }
488 }
489
490 return (INT_PTR)FALSE;
491 }
492
493 INT_PTR CALLBACK WarningProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
494 {
495 UNREFERENCED_PARAMETER(lParam);
496
497 switch (message)
498 {
499 case WM_INITDIALOG:
500 return (INT_PTR)TRUE;
501
502 case WM_COMMAND:
503 switch (LOWORD(wParam))
504 {
505 case IDC_SHOWWARNINGCHECK:
506 bShowWarning = !IsDlgButtonChecked(hDlg, IDC_SHOWWARNINGCHECK);
507 break;
508 }
509 if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
510 {
511 EndDialog(hDlg, LOWORD(wParam));
512 return (INT_PTR)TRUE;
513 }
514 break;
515 }
516
517 return (INT_PTR)FALSE;
518 }