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