reactos/base/applications/magnify/magnifier.c

558 lines
15 KiB
C
Raw Normal View History

/*
* PROJECT: ReactOS Magnify
* LICENSE: GPL - See COPYING in the top level directory
* FILE: base/applications/magnify/magnifier.c
* PURPOSE: Magnification of parts of the screen.
* COPYRIGHT: Copyright 2007 Marc Piulachs <marc.piulachs@codexchange.net>
*
*/
/* TODO: AppBar */
#include "magnifier.h"
const TCHAR szWindowClass[] = TEXT("MAGNIFIER");
#define MAX_LOADSTRING 100
// Global Variables:
HINSTANCE hInst; // current instance
HWND hMainWnd;
TCHAR szTitle[MAX_LOADSTRING]; // The title bar text
#define REPAINT_SPEED 100
HWND hDesktopWindow = NULL;
//Current magnified area
POINT cp;
//Last positions
POINT pMouse;
POINT pCaret;
POINT pFocus;
// Forward declarations of functions included in this code module:
ATOM MyRegisterClass(HINSTANCE hInstance);
BOOL InitInstance(HINSTANCE, int);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
INT_PTR CALLBACK AboutProc(HWND, UINT, WPARAM, LPARAM);
INT_PTR CALLBACK OptionsProc(HWND, UINT, WPARAM, LPARAM);
INT_PTR CALLBACK WarningProc(HWND, UINT, WPARAM, LPARAM);
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
// TODO: Place code here.
MSG msg;
HACCEL hAccelTable;
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
switch (GetUserDefaultUILanguage())
{
case MAKELANGID(LANG_HEBREW, SUBLANG_DEFAULT):
SetProcessDefaultLayout(LAYOUT_RTL);
break;
default:
break;
}
// Initialize global strings
LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
MyRegisterClass(hInstance);
// Perform application initialization:
if (!InitInstance (hInstance, nCmdShow))
{
return FALSE;
}
hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_MAGNIFIER));
// Main message loop:
while (GetMessage(&msg, NULL, 0, 0))
{
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return (int) msg.wParam;
}
/*
* FUNCTION: MyRegisterClass()
*
* PURPOSE: Registers the window class.
*
* COMMENTS:
*
* This function and its usage are only necessary if you want this code
* to be compatible with Win32 systems prior to the 'RegisterClassEx'
* function that was added to Windows 95. It is important to call this function
* so that the application will get 'well formed' small icons associated
* with it.
*/
ATOM MyRegisterClass(HINSTANCE hInstance)
{
WNDCLASS wc;
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_ICON));
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wc.lpszMenuName = MAKEINTRESOURCE(IDC_MAGNIFIER);
wc.lpszClassName = szWindowClass;
return RegisterClass(&wc);
}
/*
* FUNCTION: InitInstance(HINSTANCE, int)
*
* PURPOSE: Saves instance handle and creates main window
*
* COMMENTS:
*
* In this function, we save the instance handle in a global variable and
* create and display the main program window.
*/
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
RECT rcWorkArea;
hInst = hInstance; // Store instance handle in our global variable
SystemParametersInfo(SPI_GETWORKAREA, 0, &rcWorkArea, 0);
/* Create the Window */
hMainWnd = CreateWindowEx(
WS_EX_TOPMOST | WS_EX_PALETTEWINDOW,
szWindowClass,
szTitle,
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
(rcWorkArea.right - rcWorkArea.left) * 2 / 3,
200,
NULL,
NULL,
hInstance,
NULL);
if (!hMainWnd)
{
return FALSE;
}
ShowWindow(hMainWnd, (bStartMinimized) ? SW_MINIMIZE : nCmdShow);
UpdateWindow(hMainWnd);
if (bShowWarning)
{
DialogBox (hInstance, MAKEINTRESOURCE(IDD_WARNINGDIALOG), hMainWnd, (DLGPROC)WarningProc);
}
return TRUE;
}
void Refresh ()
{
if (!IsIconic(hMainWnd))
{
// Invalidate the client area forcing a WM_PAINT message
InvalidateRgn(hMainWnd, NULL, TRUE);
}
}
void Draw(HDC aDc)
{
HDC desktopHdc = NULL;
HDC HdcStrech;
HANDLE hOld;
HBITMAP HbmpStrech;
RECT R;
RECT appRect;
DWORD rop = SRCCOPY;
CURSORINFO cinfo;
ICONINFO iinfo;
int Width, Height, AppWidth, AppHeight;
LONG blitAreaWidth, blitAreaHeight, blitAreaX, blitAreaY;
desktopHdc = GetWindowDC (hDesktopWindow);
GetClientRect(hMainWnd, &appRect);
GetWindowRect(hDesktopWindow, &R);
ZeroMemory(&cinfo, sizeof(CURSORINFO));
ZeroMemory(&iinfo, sizeof(ICONINFO));
cinfo.cbSize = sizeof(cinfo);
GetCursorInfo(&cinfo);
GetIconInfo(cinfo.hCursor, &iinfo);
/* Create a memory DC compatible with client area DC.*/
HdcStrech = CreateCompatibleDC(desktopHdc);
/* Create a bitmap compatible with the client area DC.*/
HbmpStrech = CreateCompatibleBitmap(
desktopHdc,
R.right,
R.bottom);
/* Select our bitmap in memory DC and save the old one.*/
hOld = SelectObject (HdcStrech , HbmpStrech);
/* Paint the screen bitmap to our in memory DC */
BitBlt(
HdcStrech,
0,
0,
R.right,
R.bottom,
desktopHdc,
0,
0,
SRCCOPY);
/* Draw the mouse pointer in the right position */
DrawIcon(
HdcStrech ,
pMouse.x - iinfo.xHotspot, // - 10,
pMouse.y - iinfo.yHotspot, // - 10,
cinfo.hCursor);
Width = (R.right - R.left);
Height = (R.bottom - R.top);
AppWidth = (appRect.right - appRect.left);
AppHeight = (appRect.bottom - appRect.top);
blitAreaWidth = AppWidth / iZoom;
blitAreaHeight = AppHeight / iZoom;
blitAreaX = (cp.x) - (blitAreaWidth /2);
blitAreaY = (cp.y) - (blitAreaHeight /2);
if (blitAreaX < 0)
{
blitAreaX = 0;
}
if (blitAreaY < 0)
{
blitAreaY = 0;
}
if (blitAreaX > (Width - blitAreaWidth))
{
blitAreaX = (Width - blitAreaWidth);
}
if (blitAreaY > (Height - blitAreaHeight))
{
blitAreaY = (Height - blitAreaHeight);
}
if (bInvertColors)
{
rop = NOTSRCCOPY;
}
/* Blast the stretched image from memory DC to window DC.*/
StretchBlt(
aDc,
0,
0,
AppWidth,
AppHeight,
HdcStrech,
blitAreaX,
blitAreaY,
blitAreaWidth,
blitAreaHeight,
rop | NOMIRRORBITMAP);
/* Cleanup.*/
if (iinfo.hbmMask)
DeleteObject(iinfo.hbmMask);
if (iinfo.hbmColor)
DeleteObject(iinfo.hbmColor);
SelectObject (HdcStrech, hOld);
DeleteObject (HbmpStrech);
DeleteDC (HdcStrech);
ReleaseDC(hDesktopWindow, desktopHdc);
}
/*
* FUNCTION: WndProc(HWND, UINT, WPARAM, LPARAM)
*
* PURPOSE: Processes messages for the main window.
*
* WM_COMMAND - process the application menu
* WM_PAINT - Paint the main window
* WM_DESTROY - post a quit message and return
*
*/
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int wmId;
switch (message)
{
case WM_TIMER:
{
POINT pNewMouse;
POINT pNewCaret;
POINT pNewFocus;
HWND hwnd1, hwnd2, hwnd3;
DWORD a, b;
RECT controlRect;
//Get current mouse position
GetCursorPos (&pNewMouse);
//Get caret position
hwnd1 = GetForegroundWindow ();
a = GetWindowThreadProcessId(hwnd1, NULL);
b = GetCurrentThreadId();
AttachThreadInput (a, b, TRUE);
hwnd2 = GetFocus();
GetCaretPos( &pNewCaret);
ClientToScreen (hwnd2, (LPPOINT) &pNewCaret);
AttachThreadInput (a, b, FALSE);
//Get current control focus
hwnd3 = GetFocus ();
GetWindowRect (hwnd3 , &controlRect);
pNewFocus.x = controlRect.left;
pNewFocus.y = controlRect.top;
//If mouse has moved ....
if (((pMouse.x != pNewMouse.x) || (pMouse.y != pNewMouse.y)) && bFollowMouse)
{
//Update to new position
pMouse = pNewMouse;
cp = pNewMouse;
Refresh();
}
else if (((pCaret.x != pNewCaret.x) || (pCaret.y != pNewCaret.y)) && bFollowCaret)
{
//Update to new position
pCaret = pNewCaret;
cp = pNewCaret;
Refresh();
}
else if (((pFocus.x != pNewFocus.x) || (pFocus.y != pNewFocus.y)) && bFollowFocus)
{
//Update to new position
pFocus = pNewFocus;
cp = pNewFocus;
Refresh();
}
}
break;
case WM_COMMAND:
wmId = LOWORD(wParam);
// Parse the menu selections:
switch (wmId)
{
case IDM_OPTIONS:
DialogBox(hInst, MAKEINTRESOURCE(IDD_DIALOGOPTIONS), hWnd, (DLGPROC)OptionsProc);
break;
case IDM_ABOUT:
DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, (DLGPROC)AboutProc);
break;
case IDM_EXIT:
DestroyWindow(hWnd);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
break;
case WM_PAINT:
{
PAINTSTRUCT PaintStruct;
HDC dc;
dc = BeginPaint(hWnd, &PaintStruct);
Draw(dc);
EndPaint(hWnd, &PaintStruct);
}
break;
case WM_ERASEBKGND:
//handle WM_ERASEBKGND by simply returning non-zero because we did all the drawing in WM_PAINT.
break;
case WM_DESTROY:
//Save settings to registry
SaveSettings ();
KillTimer (hWnd , 1);
PostQuitMessage(0);
break;
case WM_CREATE:
//Load settings from registry
LoadSettings ();
//Get the desktop window
hDesktopWindow = GetDesktopWindow();
//Set the timer
SetTimer (hWnd , 1, REPAINT_SPEED , NULL);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
// Message handler for about box.
INT_PTR CALLBACK AboutProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
UNREFERENCED_PARAMETER(lParam);
switch (message)
{
case WM_INITDIALOG:
return (INT_PTR)TRUE;
case WM_COMMAND:
if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
{
EndDialog(hDlg, LOWORD(wParam));
return (INT_PTR)TRUE;
}
break;
}
return (INT_PTR)FALSE;
}
// Message handler for options box.
INT_PTR CALLBACK OptionsProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
UNREFERENCED_PARAMETER(lParam);
switch (message)
{
case WM_INITDIALOG:
{
//Add the zoom items....
SendDlgItemMessage(hDlg, IDC_ZOOM, CB_ADDSTRING, 0, (LPARAM)("1"));
SendDlgItemMessage(hDlg, IDC_ZOOM, CB_ADDSTRING, 0, (LPARAM)("2"));
SendDlgItemMessage(hDlg, IDC_ZOOM, CB_ADDSTRING, 0, (LPARAM)("3"));
SendDlgItemMessage(hDlg, IDC_ZOOM, CB_ADDSTRING, 0, (LPARAM)("4"));
SendDlgItemMessage(hDlg, IDC_ZOOM, CB_ADDSTRING, 0, (LPARAM)("5"));
SendDlgItemMessage(hDlg, IDC_ZOOM, CB_ADDSTRING, 0, (LPARAM)("6"));
SendDlgItemMessage(hDlg, IDC_ZOOM, CB_ADDSTRING, 0, (LPARAM)("7"));
SendDlgItemMessage(hDlg, IDC_ZOOM, CB_ADDSTRING, 0, (LPARAM)("8"));
//
SendDlgItemMessage(hDlg, IDC_ZOOM, CB_SETCURSEL, iZoom - 1, 0);
if (bFollowMouse)
SendDlgItemMessage(hDlg,IDC_FOLLOWMOUSECHECK,BM_SETCHECK , wParam ,0);
if (bFollowFocus)
SendDlgItemMessage(hDlg,IDC_FOLLOWKEYBOARDCHECK,BM_SETCHECK , wParam ,0);
if (bFollowCaret)
SendDlgItemMessage(hDlg,IDC_FOLLOWTEXTEDITINGCHECK,BM_SETCHECK , wParam ,0);
if (bInvertColors)
SendDlgItemMessage(hDlg,IDC_INVERTCOLORSCHECK,BM_SETCHECK , wParam ,0);
if (bStartMinimized)
SendDlgItemMessage(hDlg,IDC_STARTMINIMIZEDCHECK,BM_SETCHECK , wParam ,0);
if (bShowMagnifier)
SendDlgItemMessage(hDlg,IDC_SHOWMAGNIFIERCHECK,BM_SETCHECK , wParam ,0);
return (INT_PTR)TRUE;
}
case WM_COMMAND:
switch(LOWORD(wParam))
{
case IDOK:
case IDCANCEL:
EndDialog(hDlg, LOWORD(wParam));
return (INT_PTR)TRUE;
case IDC_BUTTON_HELP:
/* unimplemented */
MessageBox(hDlg , TEXT("Magnifier help not available yet!") , TEXT("Help") , MB_OK);
break;
case IDC_ZOOM:
if(HIWORD(wParam) == CBN_SELCHANGE)
{
HWND hCombo = GetDlgItem(hDlg,IDC_ZOOM);
/* Get index of current selection and the text of that selection. */
iZoom = SendMessage( hCombo, CB_GETCURSEL, (WPARAM) wParam, (LPARAM) lParam ) + 1;
//Update the magnigier UI
Refresh ();
}
break;
case IDC_INVERTCOLORSCHECK:
bInvertColors = IsDlgButtonChecked (hDlg, IDC_INVERTCOLORSCHECK);
Refresh ();
break;
case IDC_FOLLOWMOUSECHECK:
bFollowMouse = IsDlgButtonChecked (hDlg, IDC_FOLLOWMOUSECHECK);
break;
case IDC_FOLLOWKEYBOARDCHECK:
bFollowFocus = IsDlgButtonChecked (hDlg, IDC_FOLLOWKEYBOARDCHECK);
break;
case IDC_FOLLOWTEXTEDITINGCHECK:
bFollowCaret = IsDlgButtonChecked (hDlg, IDC_FOLLOWTEXTEDITINGCHECK);
break;
case IDC_STARTMINIMIZEDCHECK:
bStartMinimized = IsDlgButtonChecked (hDlg, IDC_STARTMINIMIZEDCHECK);
break;
case IDC_SHOWMAGNIFIER:
bShowMagnifier = IsDlgButtonChecked (hDlg, IDC_SHOWMAGNIFIERCHECK);
if (bShowMagnifier){
ShowWindow (hMainWnd , SW_SHOW);
}else{
ShowWindow (hMainWnd , SW_HIDE);
}
break;
}
}
return (INT_PTR)FALSE;
}
// Message handler for warning box.
INT_PTR CALLBACK WarningProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
UNREFERENCED_PARAMETER(lParam);
switch (message)
{
case WM_INITDIALOG:
return (INT_PTR)TRUE;
case WM_COMMAND:
switch(LOWORD(wParam))
{
case IDC_SHOWWARNINGCHECK:
bShowWarning = !IsDlgButtonChecked (hDlg, IDC_SHOWWARNINGCHECK);
break;
}
if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
{
EndDialog(hDlg, LOWORD(wParam));
return (INT_PTR)TRUE;
}
break;
}
return (INT_PTR)FALSE;
}