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