mirror of
https://github.com/reactos/reactos.git
synced 2024-07-06 04:35:07 +00:00
[MAGNIFY]
Some improvements to the drawing code: * Draw as soon as the mouse/caret/focus changes, or after 100ms if nothing changed. * Copy only the needed area of the screen into the internal buffer. * Blank out the area of the buffer where the client region of the magnifier overlaps, to avoid re-zooming the pixels. * Keep the source region contained within the closest monitor, instead of only the primary one. * Invert colors when copying from the screen, instead of when stretching, since there's less pixels to draw. First step toward the improvements described in CORE-10691 svn path=/trunk/; revision=70335
This commit is contained in:
parent
70e2eedd98
commit
82f42c9c92
|
@ -27,8 +27,11 @@ HWND hMainWnd;
|
||||||
|
|
||||||
TCHAR szTitle[MAX_LOADSTRING];
|
TCHAR szTitle[MAX_LOADSTRING];
|
||||||
|
|
||||||
|
#define TIMER_SPEED 1
|
||||||
#define REPAINT_SPEED 100
|
#define REPAINT_SPEED 100
|
||||||
|
|
||||||
|
DWORD lastTicks = 0;
|
||||||
|
|
||||||
HWND hDesktopWindow = NULL;
|
HWND hDesktopWindow = NULL;
|
||||||
|
|
||||||
/* Current magnified area */
|
/* Current magnified area */
|
||||||
|
@ -148,26 +151,62 @@ void Refresh()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GetBestOverlapWithMonitors(LPRECT rect)
|
||||||
|
{
|
||||||
|
int rcLeft, rcTop;
|
||||||
|
int rcWidth, rcHeight;
|
||||||
|
RECT rcMon;
|
||||||
|
HMONITOR hMon = MonitorFromRect(rect, MONITOR_DEFAULTTONEAREST);
|
||||||
|
MONITORINFO info;
|
||||||
|
info.cbSize = sizeof(info);
|
||||||
|
|
||||||
|
GetMonitorInfo(hMon, &info);
|
||||||
|
|
||||||
|
rcMon = info.rcMonitor;
|
||||||
|
|
||||||
|
rcLeft = rect->left;
|
||||||
|
rcTop = rect->top;
|
||||||
|
rcWidth = (rect->right - rect->left);
|
||||||
|
rcHeight = (rect->bottom - rect->top);
|
||||||
|
|
||||||
|
if (rcLeft < rcMon.left)
|
||||||
|
rcLeft = rcMon.left;
|
||||||
|
|
||||||
|
if (rcTop < rcMon.top)
|
||||||
|
rcTop = rcMon.top;
|
||||||
|
|
||||||
|
if (rcLeft > (rcMon.right - rcWidth))
|
||||||
|
rcLeft = (rcMon.right - rcWidth);
|
||||||
|
|
||||||
|
if (rcTop > (rcMon.bottom - rcHeight))
|
||||||
|
rcTop = (rcMon.bottom - rcHeight);
|
||||||
|
|
||||||
|
OffsetRect(rect, (rcLeft-rect->left), (rcTop-rect->top));
|
||||||
|
}
|
||||||
|
|
||||||
void Draw(HDC aDc)
|
void Draw(HDC aDc)
|
||||||
{
|
{
|
||||||
HDC desktopHdc = NULL;
|
HDC desktopHdc = NULL;
|
||||||
HDC HdcStrech;
|
HDC HdcStretch;
|
||||||
HANDLE hOld;
|
HANDLE hOld;
|
||||||
HBITMAP HbmpStrech;
|
HBITMAP HbmpStrech;
|
||||||
|
|
||||||
RECT R;
|
RECT sourceRect, intersectedRect;
|
||||||
RECT appRect;
|
RECT targetRect, appRect;
|
||||||
DWORD rop = SRCCOPY;
|
DWORD rop = SRCCOPY;
|
||||||
CURSORINFO cinfo;
|
CURSORINFO cinfo;
|
||||||
ICONINFO iinfo;
|
ICONINFO iinfo;
|
||||||
|
|
||||||
int Width, Height, AppWidth, AppHeight;
|
int AppWidth, AppHeight;
|
||||||
LONG blitAreaWidth, blitAreaHeight, blitAreaX, blitAreaY;
|
LONG blitAreaWidth, blitAreaHeight;
|
||||||
|
|
||||||
desktopHdc = GetWindowDC(hDesktopWindow);
|
if (bInvertColors)
|
||||||
|
rop = NOTSRCCOPY;
|
||||||
|
|
||||||
|
desktopHdc = GetDC(0);
|
||||||
|
|
||||||
GetClientRect(hMainWnd, &appRect);
|
GetClientRect(hMainWnd, &appRect);
|
||||||
GetWindowRect(hDesktopWindow, &R);
|
GetWindowRect(hDesktopWindow, &sourceRect);
|
||||||
|
|
||||||
ZeroMemory(&cinfo, sizeof(cinfo));
|
ZeroMemory(&cinfo, sizeof(cinfo));
|
||||||
ZeroMemory(&iinfo, sizeof(iinfo));
|
ZeroMemory(&iinfo, sizeof(iinfo));
|
||||||
|
@ -175,39 +214,9 @@ void Draw(HDC aDc)
|
||||||
GetCursorInfo(&cinfo);
|
GetCursorInfo(&cinfo);
|
||||||
GetIconInfo(cinfo.hCursor, &iinfo);
|
GetIconInfo(cinfo.hCursor, &iinfo);
|
||||||
|
|
||||||
/* Create a memory DC compatible with client area DC */
|
targetRect = appRect;
|
||||||
HdcStrech = CreateCompatibleDC(desktopHdc);
|
ClientToScreen(hMainWnd, (POINT*)&targetRect.left);
|
||||||
|
ClientToScreen(hMainWnd, (POINT*)&targetRect.right);
|
||||||
/* 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);
|
AppWidth = (appRect.right - appRect.left);
|
||||||
AppHeight = (appRect.bottom - appRect.top);
|
AppHeight = (appRect.bottom - appRect.top);
|
||||||
|
@ -215,23 +224,49 @@ void Draw(HDC aDc)
|
||||||
blitAreaWidth = AppWidth / iZoom;
|
blitAreaWidth = AppWidth / iZoom;
|
||||||
blitAreaHeight = AppHeight / iZoom;
|
blitAreaHeight = AppHeight / iZoom;
|
||||||
|
|
||||||
blitAreaX = (cp.x) - (blitAreaWidth /2);
|
sourceRect.left = (cp.x) - (blitAreaWidth /2);
|
||||||
blitAreaY = (cp.y) - (blitAreaHeight /2);
|
sourceRect.top = (cp.y) - (blitAreaHeight /2);
|
||||||
|
sourceRect.right = sourceRect.left + blitAreaWidth;
|
||||||
|
sourceRect.bottom = sourceRect.top + blitAreaHeight;
|
||||||
|
|
||||||
if (blitAreaX < 0)
|
GetBestOverlapWithMonitors(&sourceRect);
|
||||||
blitAreaX = 0;
|
|
||||||
|
|
||||||
if (blitAreaY < 0)
|
/* Create a memory DC compatible with client area DC */
|
||||||
blitAreaY = 0;
|
HdcStretch = CreateCompatibleDC(desktopHdc);
|
||||||
|
|
||||||
if (blitAreaX > (Width - blitAreaWidth))
|
/* Create a bitmap compatible with the client area DC */
|
||||||
blitAreaX = (Width - blitAreaWidth);
|
HbmpStrech = CreateCompatibleBitmap(
|
||||||
|
desktopHdc,
|
||||||
|
blitAreaWidth,
|
||||||
|
blitAreaHeight);
|
||||||
|
|
||||||
if (blitAreaY > (Height - blitAreaHeight))
|
/* Select our bitmap in memory DC and save the old one */
|
||||||
blitAreaY = (Height - blitAreaHeight);
|
hOld = SelectObject(HdcStretch , HbmpStrech);
|
||||||
|
|
||||||
if (bInvertColors)
|
/* Paint the screen bitmap to our in memory DC */
|
||||||
rop = NOTSRCCOPY;
|
BitBlt(
|
||||||
|
HdcStretch,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
blitAreaWidth,
|
||||||
|
blitAreaHeight,
|
||||||
|
desktopHdc,
|
||||||
|
sourceRect.left,
|
||||||
|
sourceRect.top,
|
||||||
|
rop);
|
||||||
|
|
||||||
|
if (IntersectRect(&intersectedRect, &sourceRect, &targetRect))
|
||||||
|
{
|
||||||
|
OffsetRect(&intersectedRect, -sourceRect.left, -sourceRect.top);
|
||||||
|
FillRect(HdcStretch, &intersectedRect, GetStockObject(DC_BRUSH));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Draw the mouse pointer in the right position */
|
||||||
|
DrawIcon(
|
||||||
|
HdcStretch ,
|
||||||
|
pMouse.x - iinfo.xHotspot - sourceRect.left, // - 10,
|
||||||
|
pMouse.y - iinfo.yHotspot - sourceRect.top, // - 10,
|
||||||
|
cinfo.hCursor);
|
||||||
|
|
||||||
/* Blast the stretched image from memory DC to window DC */
|
/* Blast the stretched image from memory DC to window DC */
|
||||||
StretchBlt(
|
StretchBlt(
|
||||||
|
@ -240,22 +275,21 @@ void Draw(HDC aDc)
|
||||||
0,
|
0,
|
||||||
AppWidth,
|
AppWidth,
|
||||||
AppHeight,
|
AppHeight,
|
||||||
HdcStrech,
|
HdcStretch,
|
||||||
blitAreaX,
|
0,
|
||||||
blitAreaY,
|
0,
|
||||||
blitAreaWidth,
|
blitAreaWidth,
|
||||||
blitAreaHeight,
|
blitAreaHeight,
|
||||||
rop | NOMIRRORBITMAP);
|
SRCCOPY | NOMIRRORBITMAP);
|
||||||
|
|
||||||
|
|
||||||
/* Cleanup */
|
/* Cleanup */
|
||||||
if (iinfo.hbmMask)
|
if (iinfo.hbmMask)
|
||||||
DeleteObject(iinfo.hbmMask);
|
DeleteObject(iinfo.hbmMask);
|
||||||
if (iinfo.hbmColor)
|
if (iinfo.hbmColor)
|
||||||
DeleteObject(iinfo.hbmColor);
|
DeleteObject(iinfo.hbmColor);
|
||||||
SelectObject(HdcStrech, hOld);
|
SelectObject(HdcStretch, hOld);
|
||||||
DeleteObject (HbmpStrech);
|
DeleteObject (HbmpStrech);
|
||||||
DeleteDC(HdcStrech);
|
DeleteDC(HdcStretch);
|
||||||
ReleaseDC(hDesktopWindow, desktopHdc);
|
ReleaseDC(hDesktopWindow, desktopHdc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -267,53 +301,85 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
|
||||||
{
|
{
|
||||||
case WM_TIMER:
|
case WM_TIMER:
|
||||||
{
|
{
|
||||||
POINT pNewMouse;
|
BOOL hasMoved = FALSE;
|
||||||
POINT pNewCaret;
|
|
||||||
POINT pNewFocus;
|
|
||||||
HWND hwnd1, hwnd2, hwnd3;
|
|
||||||
DWORD a, b;
|
|
||||||
RECT controlRect;
|
|
||||||
|
|
||||||
//Get current mouse position
|
if (bFollowMouse)
|
||||||
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
|
POINT pNewMouse;
|
||||||
pMouse = pNewMouse;
|
|
||||||
cp = pNewMouse;
|
//Get current mouse position
|
||||||
|
GetCursorPos (&pNewMouse);
|
||||||
|
|
||||||
|
//If mouse has moved ...
|
||||||
|
if (((pMouse.x != pNewMouse.x) || (pMouse.y != pNewMouse.y)))
|
||||||
|
{
|
||||||
|
//Update to new position
|
||||||
|
pMouse = pNewMouse;
|
||||||
|
cp = pNewMouse;
|
||||||
|
hasMoved = TRUE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (((pCaret.x != pNewCaret.x) || (pCaret.y != pNewCaret.y)) && bFollowCaret)
|
|
||||||
|
if (bFollowCaret && !hasMoved)
|
||||||
{
|
{
|
||||||
//Update to new position
|
POINT pNewCaret;
|
||||||
pCaret = pNewCaret;
|
HWND hwnd2;
|
||||||
cp = pNewCaret;
|
|
||||||
|
//Get caret position
|
||||||
|
HWND hwnd1 = GetForegroundWindow ();
|
||||||
|
DWORD a = GetWindowThreadProcessId(hwnd1, NULL);
|
||||||
|
DWORD b = GetCurrentThreadId();
|
||||||
|
AttachThreadInput (a, b, TRUE);
|
||||||
|
hwnd2 = GetFocus();
|
||||||
|
|
||||||
|
GetCaretPos( &pNewCaret);
|
||||||
|
ClientToScreen (hwnd2, (LPPOINT) &pNewCaret);
|
||||||
|
AttachThreadInput (a, b, FALSE);
|
||||||
|
|
||||||
|
if (((pCaret.x != pNewCaret.x) || (pCaret.y != pNewCaret.y)))
|
||||||
|
{
|
||||||
|
//Update to new position
|
||||||
|
pCaret = pNewCaret;
|
||||||
|
cp = pNewCaret;
|
||||||
|
hasMoved = TRUE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (((pFocus.x != pNewFocus.x) || (pFocus.y != pNewFocus.y)) && bFollowFocus)
|
|
||||||
|
if (bFollowFocus && !hasMoved)
|
||||||
{
|
{
|
||||||
//Update to new position
|
POINT pNewFocus;
|
||||||
pFocus = pNewFocus;
|
RECT controlRect;
|
||||||
cp = pNewFocus;
|
|
||||||
|
//Get current control focus
|
||||||
|
HWND hwnd3 = GetFocus ();
|
||||||
|
GetWindowRect (hwnd3 , &controlRect);
|
||||||
|
pNewFocus.x = controlRect.left;
|
||||||
|
pNewFocus.y = controlRect.top;
|
||||||
|
|
||||||
|
if(((pFocus.x != pNewFocus.x) || (pFocus.y != pNewFocus.y)))
|
||||||
|
{
|
||||||
|
//Update to new position
|
||||||
|
pFocus = pNewFocus;
|
||||||
|
cp = pNewFocus;
|
||||||
|
hasMoved = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!hasMoved)
|
||||||
|
{
|
||||||
|
DWORD newTicks = GetTickCount();
|
||||||
|
DWORD elapsed = (newTicks - lastTicks);
|
||||||
|
if(elapsed > REPAINT_SPEED)
|
||||||
|
{
|
||||||
|
hasMoved = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(hasMoved)
|
||||||
|
{
|
||||||
|
lastTicks = GetTickCount();
|
||||||
|
Refresh();
|
||||||
}
|
}
|
||||||
Refresh();
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -367,7 +433,7 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
|
||||||
hDesktopWindow = GetDesktopWindow();
|
hDesktopWindow = GetDesktopWindow();
|
||||||
|
|
||||||
/* Set the timer */
|
/* Set the timer */
|
||||||
SetTimer (hWnd , 1, REPAINT_SPEED , NULL);
|
SetTimer (hWnd , 1, TIMER_SPEED , NULL);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|
Loading…
Reference in a new issue