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>
11 #include "magnifier.h"
20 const TCHAR szWindowClass
[] = TEXT("MAGNIFIER");
22 #define MAX_LOADSTRING 100
24 /* Global Variables */
28 TCHAR szTitle
[MAX_LOADSTRING
];
31 #define REPAINT_SPEED 100
35 HWND hDesktopWindow
= NULL
;
37 /* Current magnified area */
45 ATOM
MyRegisterClass(HINSTANCE hInstance
);
46 BOOL
InitInstance(HINSTANCE
, int);
47 LRESULT CALLBACK
WndProc(HWND
, UINT
, WPARAM
, LPARAM
);
48 INT_PTR CALLBACK
AboutProc(HWND
, UINT
, WPARAM
, LPARAM
);
49 INT_PTR CALLBACK
OptionsProc(HWND
, UINT
, WPARAM
, LPARAM
);
50 INT_PTR CALLBACK
WarningProc(HWND
, UINT
, WPARAM
, LPARAM
);
52 int WINAPI
WinMain( HINSTANCE hInstance
, HINSTANCE hPrevInstance
, LPSTR lpCmdLine
, int nCmdShow
)
57 UNREFERENCED_PARAMETER(hPrevInstance
);
58 UNREFERENCED_PARAMETER(lpCmdLine
);
60 switch (GetUserDefaultUILanguage())
62 case MAKELANGID(LANG_HEBREW
, SUBLANG_DEFAULT
):
63 SetProcessDefaultLayout(LAYOUT_RTL
);
70 /* Initialize global strings */
71 LoadString(hInstance
, IDS_APP_TITLE
, szTitle
, MAX_LOADSTRING
);
72 MyRegisterClass(hInstance
);
74 /* Perform application initialization */
75 if (!InitInstance(hInstance
, nCmdShow
))
78 hAccelTable
= LoadAccelerators(hInstance
, MAKEINTRESOURCE(IDC_MAGNIFIER
));
80 /* Main message loop */
81 while (GetMessage(&msg
, NULL
, 0, 0))
83 if (!TranslateAccelerator(msg
.hwnd
, hAccelTable
, &msg
))
85 TranslateMessage(&msg
);
86 DispatchMessage(&msg
);
90 return (int) msg
.wParam
;
93 ATOM
MyRegisterClass(HINSTANCE hInstance
)
97 wc
.style
= CS_HREDRAW
| CS_VREDRAW
;
98 wc
.lpfnWndProc
= WndProc
;
101 wc
.hInstance
= hInstance
;
102 wc
.hIcon
= LoadIcon(hInstance
, MAKEINTRESOURCE(IDI_ICON
));
103 wc
.hCursor
= LoadCursor(NULL
, IDC_ARROW
);
104 wc
.hbrBackground
= (HBRUSH
)(COLOR_WINDOW
+1);
105 wc
.lpszMenuName
= MAKEINTRESOURCE(IDC_MAGNIFIER
);
106 wc
.lpszClassName
= szWindowClass
;
108 return RegisterClass(&wc
);
111 BOOL
InitInstance(HINSTANCE hInstance
, int nCmdShow
)
114 hInst
= hInstance
; // Store instance handle in our global variable
116 SystemParametersInfo(SPI_GETWORKAREA
, 0, &rcWorkArea
, 0);
118 /* Create the Window */
119 hMainWnd
= CreateWindowEx(
120 WS_EX_TOPMOST
| WS_EX_PALETTEWINDOW
,
126 (rcWorkArea
.right
- rcWorkArea
.left
) * 2 / 3,
136 ShowWindow(hMainWnd
, bStartMinimized
? SW_MINIMIZE
: nCmdShow
);
137 UpdateWindow(hMainWnd
);
140 DialogBox(hInstance
, MAKEINTRESOURCE(IDD_WARNINGDIALOG
), hMainWnd
, WarningProc
);
147 if (!IsIconic(hMainWnd
))
149 /* Invalidate the client area forcing a WM_PAINT message */
150 InvalidateRgn(hMainWnd
, NULL
, TRUE
);
154 void GetBestOverlapWithMonitors(LPRECT rect
)
157 int rcWidth
, rcHeight
;
159 HMONITOR hMon
= MonitorFromRect(rect
, MONITOR_DEFAULTTONEAREST
);
161 info
.cbSize
= sizeof(info
);
163 GetMonitorInfo(hMon
, &info
);
165 rcMon
= info
.rcMonitor
;
169 rcWidth
= (rect
->right
- rect
->left
);
170 rcHeight
= (rect
->bottom
- rect
->top
);
172 if (rcLeft
< rcMon
.left
)
175 if (rcTop
< rcMon
.top
)
178 if (rcLeft
> (rcMon
.right
- rcWidth
))
179 rcLeft
= (rcMon
.right
- rcWidth
);
181 if (rcTop
> (rcMon
.bottom
- rcHeight
))
182 rcTop
= (rcMon
.bottom
- rcHeight
);
184 OffsetRect(rect
, (rcLeft
-rect
->left
), (rcTop
-rect
->top
));
189 HDC desktopHdc
= NULL
;
194 RECT sourceRect
, intersectedRect
;
195 RECT targetRect
, appRect
;
200 int AppWidth
, AppHeight
;
201 LONG blitAreaWidth
, blitAreaHeight
;
206 desktopHdc
= GetDC(0);
208 GetClientRect(hMainWnd
, &appRect
);
209 GetWindowRect(hDesktopWindow
, &sourceRect
);
211 ZeroMemory(&cinfo
, sizeof(cinfo
));
212 ZeroMemory(&iinfo
, sizeof(iinfo
));
213 cinfo
.cbSize
= sizeof(cinfo
);
214 GetCursorInfo(&cinfo
);
215 GetIconInfo(cinfo
.hCursor
, &iinfo
);
217 targetRect
= appRect
;
218 ClientToScreen(hMainWnd
, (POINT
*)&targetRect
.left
);
219 ClientToScreen(hMainWnd
, (POINT
*)&targetRect
.right
);
221 AppWidth
= (appRect
.right
- appRect
.left
);
222 AppHeight
= (appRect
.bottom
- appRect
.top
);
224 blitAreaWidth
= AppWidth
/ iZoom
;
225 blitAreaHeight
= AppHeight
/ iZoom
;
227 sourceRect
.left
= (cp
.x
) - (blitAreaWidth
/2);
228 sourceRect
.top
= (cp
.y
) - (blitAreaHeight
/2);
229 sourceRect
.right
= sourceRect
.left
+ blitAreaWidth
;
230 sourceRect
.bottom
= sourceRect
.top
+ blitAreaHeight
;
232 GetBestOverlapWithMonitors(&sourceRect
);
234 /* Create a memory DC compatible with client area DC */
235 HdcStretch
= CreateCompatibleDC(desktopHdc
);
237 /* Create a bitmap compatible with the client area DC */
238 HbmpStrech
= CreateCompatibleBitmap(
243 /* Select our bitmap in memory DC and save the old one */
244 hOld
= SelectObject(HdcStretch
, HbmpStrech
);
246 /* Paint the screen bitmap to our in memory DC */
258 if (IntersectRect(&intersectedRect
, &sourceRect
, &targetRect
))
260 OffsetRect(&intersectedRect
, -sourceRect
.left
, -sourceRect
.top
);
261 FillRect(HdcStretch
, &intersectedRect
, GetStockObject(DC_BRUSH
));
264 /* Draw the mouse pointer in the right position */
267 pMouse
.x
- iinfo
.xHotspot
- sourceRect
.left
, // - 10,
268 pMouse
.y
- iinfo
.yHotspot
- sourceRect
.top
, // - 10,
271 /* Blast the stretched image from memory DC to window DC */
283 SRCCOPY
| NOMIRRORBITMAP
);
287 DeleteObject(iinfo
.hbmMask
);
289 DeleteObject(iinfo
.hbmColor
);
290 SelectObject(HdcStretch
, hOld
);
291 DeleteObject (HbmpStrech
);
292 DeleteDC(HdcStretch
);
293 ReleaseDC(hDesktopWindow
, desktopHdc
);
296 LRESULT CALLBACK
WndProc(HWND hWnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
304 BOOL hasMoved
= FALSE
;
310 //Get current mouse position
311 GetCursorPos (&pNewMouse
);
313 //If mouse has moved ...
314 if (((pMouse
.x
!= pNewMouse
.x
) || (pMouse
.y
!= pNewMouse
.y
)))
316 //Update to new position
323 if (bFollowCaret
&& !hasMoved
)
329 HWND hwnd1
= GetForegroundWindow ();
330 DWORD a
= GetWindowThreadProcessId(hwnd1
, NULL
);
331 DWORD b
= GetCurrentThreadId();
332 AttachThreadInput (a
, b
, TRUE
);
335 GetCaretPos( &pNewCaret
);
336 ClientToScreen (hwnd2
, (LPPOINT
) &pNewCaret
);
337 AttachThreadInput (a
, b
, FALSE
);
339 if (((pCaret
.x
!= pNewCaret
.x
) || (pCaret
.y
!= pNewCaret
.y
)))
341 //Update to new position
348 if (bFollowFocus
&& !hasMoved
)
353 //Get current control focus
354 HWND hwnd3
= GetFocus ();
355 GetWindowRect (hwnd3
, &controlRect
);
356 pNewFocus
.x
= controlRect
.left
;
357 pNewFocus
.y
= controlRect
.top
;
359 if(((pFocus
.x
!= pNewFocus
.x
) || (pFocus
.y
!= pNewFocus
.y
)))
361 //Update to new position
370 DWORD newTicks
= GetTickCount();
371 DWORD elapsed
= (newTicks
- lastTicks
);
372 if(elapsed
> REPAINT_SPEED
)
380 lastTicks
= GetTickCount();
388 wmId
= LOWORD(wParam
);
389 /* Parse the menu selections */
393 DialogBox(hInst
, MAKEINTRESOURCE(IDD_DIALOGOPTIONS
), hWnd
, OptionsProc
);
396 DialogBox(hInst
, MAKEINTRESOURCE(IDD_ABOUTBOX
), hWnd
, AboutProc
);
402 return DefWindowProc(hWnd
, message
, wParam
, lParam
);
409 PAINTSTRUCT PaintStruct
;
411 dc
= BeginPaint(hWnd
, &PaintStruct
);
413 EndPaint(hWnd
, &PaintStruct
);
418 // handle WM_ERASEBKGND by simply returning non-zero because we did all the drawing in WM_PAINT.
422 /* Save settings to registry */
429 /* Load settings from registry */
432 /* Get the desktop window */
433 hDesktopWindow
= GetDesktopWindow();
436 SetTimer (hWnd
, 1, TIMER_SPEED
, NULL
);
440 return DefWindowProc(hWnd
, message
, wParam
, lParam
);
446 INT_PTR CALLBACK
AboutProc(HWND hDlg
, UINT message
, WPARAM wParam
, LPARAM lParam
)
448 UNREFERENCED_PARAMETER(lParam
);
452 return (INT_PTR
)TRUE
;
455 if (LOWORD(wParam
) == IDOK
|| LOWORD(wParam
) == IDCANCEL
)
457 EndDialog(hDlg
, LOWORD(wParam
));
458 return (INT_PTR
)TRUE
;
463 return (INT_PTR
)FALSE
;
466 INT_PTR CALLBACK
OptionsProc(HWND hDlg
, UINT message
, WPARAM wParam
, LPARAM lParam
)
468 UNREFERENCED_PARAMETER(lParam
);
473 // Add the zoom items...
474 SendDlgItemMessage(hDlg
, IDC_ZOOM
, CB_ADDSTRING
, 0, (LPARAM
)("1"));
475 SendDlgItemMessage(hDlg
, IDC_ZOOM
, CB_ADDSTRING
, 0, (LPARAM
)("2"));
476 SendDlgItemMessage(hDlg
, IDC_ZOOM
, CB_ADDSTRING
, 0, (LPARAM
)("3"));
477 SendDlgItemMessage(hDlg
, IDC_ZOOM
, CB_ADDSTRING
, 0, (LPARAM
)("4"));
478 SendDlgItemMessage(hDlg
, IDC_ZOOM
, CB_ADDSTRING
, 0, (LPARAM
)("5"));
479 SendDlgItemMessage(hDlg
, IDC_ZOOM
, CB_ADDSTRING
, 0, (LPARAM
)("6"));
480 SendDlgItemMessage(hDlg
, IDC_ZOOM
, CB_ADDSTRING
, 0, (LPARAM
)("7"));
481 SendDlgItemMessage(hDlg
, IDC_ZOOM
, CB_ADDSTRING
, 0, (LPARAM
)("8"));
483 SendDlgItemMessage(hDlg
, IDC_ZOOM
, CB_SETCURSEL
, iZoom
- 1, 0);
486 SendDlgItemMessage(hDlg
,IDC_FOLLOWMOUSECHECK
,BM_SETCHECK
, wParam
,0);
489 SendDlgItemMessage(hDlg
,IDC_FOLLOWKEYBOARDCHECK
,BM_SETCHECK
, wParam
,0);
492 SendDlgItemMessage(hDlg
,IDC_FOLLOWTEXTEDITINGCHECK
,BM_SETCHECK
, wParam
,0);
495 SendDlgItemMessage(hDlg
,IDC_INVERTCOLORSCHECK
,BM_SETCHECK
, wParam
,0);
498 SendDlgItemMessage(hDlg
,IDC_STARTMINIMIZEDCHECK
,BM_SETCHECK
, wParam
,0);
501 SendDlgItemMessage(hDlg
,IDC_SHOWMAGNIFIERCHECK
,BM_SETCHECK
, wParam
,0);
503 return (INT_PTR
)TRUE
;
507 switch (LOWORD(wParam
))
511 EndDialog(hDlg
, LOWORD(wParam
));
512 return (INT_PTR
)TRUE
;
514 case IDC_BUTTON_HELP
:
516 MessageBox(hDlg
, TEXT("Magnifier help not available yet!") , TEXT("Help") , MB_OK
);
519 if (HIWORD(wParam
) == CBN_SELCHANGE
)
521 HWND hCombo
= GetDlgItem(hDlg
,IDC_ZOOM
);
523 /* Get index of current selection and the text of that selection */
524 iZoom
= SendMessage( hCombo
, CB_GETCURSEL
, (WPARAM
) wParam
, (LPARAM
) lParam
) + 1;
526 /* Update the magnifier UI */
530 case IDC_INVERTCOLORSCHECK
:
531 bInvertColors
= IsDlgButtonChecked(hDlg
, IDC_INVERTCOLORSCHECK
);
534 case IDC_FOLLOWMOUSECHECK
:
535 bFollowMouse
= IsDlgButtonChecked(hDlg
, IDC_FOLLOWMOUSECHECK
);
537 case IDC_FOLLOWKEYBOARDCHECK
:
538 bFollowFocus
= IsDlgButtonChecked(hDlg
, IDC_FOLLOWKEYBOARDCHECK
);
540 case IDC_FOLLOWTEXTEDITINGCHECK
:
541 bFollowCaret
= IsDlgButtonChecked(hDlg
, IDC_FOLLOWTEXTEDITINGCHECK
);
543 case IDC_STARTMINIMIZEDCHECK
:
544 bStartMinimized
= IsDlgButtonChecked(hDlg
, IDC_STARTMINIMIZEDCHECK
);
546 case IDC_SHOWMAGNIFIER
:
547 bShowMagnifier
= IsDlgButtonChecked(hDlg
, IDC_SHOWMAGNIFIERCHECK
);
549 ShowWindow (hMainWnd
, SW_SHOW
);
551 ShowWindow (hMainWnd
, SW_HIDE
);
556 return (INT_PTR
)FALSE
;
559 INT_PTR CALLBACK
WarningProc(HWND hDlg
, UINT message
, WPARAM wParam
, LPARAM lParam
)
561 UNREFERENCED_PARAMETER(lParam
);
566 return (INT_PTR
)TRUE
;
569 switch (LOWORD(wParam
))
571 case IDC_SHOWWARNINGCHECK
:
572 bShowWarning
= !IsDlgButtonChecked(hDlg
, IDC_SHOWWARNINGCHECK
);
575 if (LOWORD(wParam
) == IDOK
|| LOWORD(wParam
) == IDCANCEL
)
577 EndDialog(hDlg
, LOWORD(wParam
));
578 return (INT_PTR
)TRUE
;
583 return (INT_PTR
)FALSE
;