[MAGNIFY]
authorDavid Quintana <gigaherz@gmail.com>
Sun, 13 Dec 2015 05:07:37 +0000 (05:07 +0000)
committerDavid Quintana <gigaherz@gmail.com>
Sun, 13 Dec 2015 05:07:37 +0000 (05:07 +0000)
* Use GetGUIThreadInfo instead of multiple separate "hacks" to obtain all the necessary data in one single call.
* Keep the off-screen DC for later use, and only recreate when needed.
* Restore caret follow back to default-on.
More changes toward CORE-10691

svn path=/trunk/; revision=70337

reactos/base/applications/magnify/magnifier.c
reactos/base/applications/magnify/settings.c

index f080e8a..5b5f6f9 100644 (file)
@@ -44,6 +44,13 @@ HMENU notifyMenu;
 HWND hOptionsDialog;
 BOOL bOptionsDialog = FALSE;
 
+BOOL bRecreateOffscreenDC = TRUE;
+LONG sourceWidth = 0;
+LONG sourceHeight = 0;
+HDC hdcOffscreen = NULL;
+HANDLE hbmpOld;
+HBITMAP hbmpOffscreen = NULL;
+
 /* Current magnified area */
 POINT cp;
 
@@ -51,6 +58,8 @@ POINT cp;
 POINT pMouse;
 POINT pCaret;
 POINT pFocus;
+HWND pCaretWnd;
+HWND pFocusWnd;
 
 ATOM                MyRegisterClass(HINSTANCE hInstance);
 BOOL                InitInstance(HINSTANCE, int);
@@ -97,6 +106,11 @@ int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLin
         }
     }
 
+
+    SelectObject(hdcOffscreen, hbmpOld);
+    DeleteObject (hbmpOffscreen);
+    DeleteDC(hdcOffscreen);
+
     return (int) msg.wParam;
 }
 
@@ -201,9 +215,6 @@ void GetBestOverlapWithMonitors(LPRECT rect)
 void Draw(HDC aDc)
 {
     HDC desktopHdc = NULL;
-    HDC HdcStretch;
-    HANDLE hOld;
-    HBITMAP HbmpStrech;
 
     RECT sourceRect, intersectedRect;
     RECT targetRect, appRect;
@@ -212,7 +223,6 @@ void Draw(HDC aDc)
     ICONINFO iinfo;
 
     int AppWidth, AppHeight;
-    LONG blitAreaWidth, blitAreaHeight;
 
     if (bInvertColors)
         rop = NOTSRCCOPY;
@@ -220,7 +230,8 @@ void Draw(HDC aDc)
     desktopHdc = GetDC(0);
 
     GetClientRect(hMainWnd, &appRect);
-    GetWindowRect(hDesktopWindow, &sourceRect);
+    AppWidth  = (appRect.right - appRect.left);
+    AppHeight = (appRect.bottom - appRect.top);
 
     ZeroMemory(&cinfo, sizeof(cinfo));
     ZeroMemory(&iinfo, sizeof(iinfo));
@@ -232,38 +243,48 @@ void Draw(HDC aDc)
     ClientToScreen(hMainWnd, (POINT*)&targetRect.left);
     ClientToScreen(hMainWnd, (POINT*)&targetRect.right);
 
-    AppWidth  = (appRect.right - appRect.left);
-    AppHeight = (appRect.bottom - appRect.top);
+    if (bRecreateOffscreenDC || !hdcOffscreen)
+    {
+        bRecreateOffscreenDC = FALSE;
 
-    blitAreaWidth  = AppWidth / iZoom;
-    blitAreaHeight = AppHeight / iZoom;
+        if(hdcOffscreen)
+        {
+            SelectObject(hdcOffscreen, hbmpOld);
+            DeleteObject (hbmpOffscreen);
+            DeleteDC(hdcOffscreen);
+        }
 
-    sourceRect.left = (cp.x) - (blitAreaWidth /2);
-    sourceRect.top = (cp.y) - (blitAreaHeight /2);
-    sourceRect.right = sourceRect.left + blitAreaWidth;
-    sourceRect.bottom = sourceRect.top + blitAreaHeight;
+        sourceWidth  = AppWidth / iZoom;
+        sourceHeight = AppHeight / iZoom;
 
-    GetBestOverlapWithMonitors(&sourceRect);
+         /* Create a memory DC compatible with client area DC */
+        hdcOffscreen = CreateCompatibleDC(desktopHdc);
 
-     /* Create a memory DC compatible with client area DC */
-    HdcStretch = CreateCompatibleDC(desktopHdc);
+        /* Create a bitmap compatible with the client area DC */
+        hbmpOffscreen = CreateCompatibleBitmap(
+            desktopHdc,
+            sourceWidth,
+            sourceHeight);
 
-    /* Create a bitmap compatible with the client area DC */
-    HbmpStrech = CreateCompatibleBitmap(
-        desktopHdc,
-        blitAreaWidth,
-        blitAreaHeight);
+        /* Select our bitmap in memory DC and save the old one */
+        hbmpOld = SelectObject(hdcOffscreen , hbmpOffscreen);
+    }
+
+    GetWindowRect(hDesktopWindow, &sourceRect);
+    sourceRect.left = (cp.x) - (sourceWidth /2);
+    sourceRect.top = (cp.y) - (sourceHeight /2);
+    sourceRect.right = sourceRect.left + sourceWidth;
+    sourceRect.bottom = sourceRect.top + sourceHeight;
 
-    /* Select our bitmap in memory DC and save the old one */
-    hOld = SelectObject(HdcStretch , HbmpStrech);
+    GetBestOverlapWithMonitors(&sourceRect);
 
     /* Paint the screen bitmap to our in memory DC */
     BitBlt(
-        HdcStretch,
+        hdcOffscreen,
         0,
         0,
-        blitAreaWidth,
-        blitAreaHeight,
+        sourceWidth,
+        sourceHeight,
         desktopHdc,
         sourceRect.left,
         sourceRect.top,
@@ -272,12 +293,12 @@ void Draw(HDC aDc)
     if (IntersectRect(&intersectedRect, &sourceRect, &targetRect))
     {
         OffsetRect(&intersectedRect, -sourceRect.left, -sourceRect.top);
-        FillRect(HdcStretch, &intersectedRect, GetStockObject(DC_BRUSH));
+        FillRect(hdcOffscreen, &intersectedRect, GetStockObject(DC_BRUSH));
     }
 
     /* Draw the mouse pointer in the right position */
     DrawIcon(
-        HdcStretch ,
+        hdcOffscreen ,
         pMouse.x - iinfo.xHotspot - sourceRect.left, // - 10,
         pMouse.y - iinfo.yHotspot - sourceRect.top, // - 10,
         cinfo.hCursor);
@@ -289,11 +310,11 @@ void Draw(HDC aDc)
         0,
         AppWidth,
         AppHeight,
-        HdcStretch,
+        hdcOffscreen,
         0,
         0,
-        blitAreaWidth,
-        blitAreaHeight,
+        sourceWidth,
+        sourceHeight,
         SRCCOPY | NOMIRRORBITMAP);
 
     /* Cleanup */
@@ -301,9 +322,6 @@ void Draw(HDC aDc)
         DeleteObject(iinfo.hbmMask);
     if (iinfo.hbmColor)
         DeleteObject(iinfo.hbmColor);
-    SelectObject(HdcStretch, hOld);
-    DeleteObject (HbmpStrech);
-    DeleteDC(HdcStretch);
     ReleaseDC(hDesktopWindow, desktopHdc);
 }
 
@@ -332,6 +350,12 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
         case WM_TIMER:
         {
             BOOL hasMoved = FALSE;
+            HWND hwndForeground = GetForegroundWindow ();
+            DWORD threadId = GetWindowThreadProcessId(hwndForeground, NULL);
+            GUITHREADINFO guiInfo;
+            guiInfo.cbSize = sizeof(guiInfo);
+
+            GetGUIThreadInfo(threadId, &guiInfo);
 
             if (bFollowMouse)
             {
@@ -350,47 +374,43 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
                 }
             }
             
-            if (bFollowCaret && !hasMoved)
+            if (bFollowCaret && hwndForeground && guiInfo.hwndCaret)
             {
-                POINT pNewCaret;
-                HWND hwnd2;
-
-                //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);
+                POINT ptCaret;
+                ptCaret.x = (guiInfo.rcCaret.left + guiInfo.rcCaret.right) / 2;
+                ptCaret.y = (guiInfo.rcCaret.top + guiInfo.rcCaret.bottom) / 2;
 
-                if (((pCaret.x != pNewCaret.x) || (pCaret.y != pNewCaret.y)))
+                if (guiInfo.hwndCaret && ((pCaretWnd != guiInfo.hwndCaret) || (pCaret.x != ptCaret.x) || (pCaret.y != ptCaret.y)))
                 {
                     //Update to new position
-                    pCaret = pNewCaret;
-                    cp = pNewCaret;
+                    pCaret = ptCaret;
+                    pCaretWnd = guiInfo.hwndCaret;
+                    if(!hasMoved)
+                    {
+                        ClientToScreen (guiInfo.hwndCaret, (LPPOINT) &ptCaret);
+                        cp = ptCaret;
+                    }
                     hasMoved = TRUE;
                 }
             }
 
-            if (bFollowFocus && !hasMoved)
+            if (bFollowFocus && hwndForeground && guiInfo.hwndFocus)
             {
-                POINT pNewFocus;
-                RECT controlRect;
+                POINT ptFocus;
+                RECT activeRect;
 
                 //Get current control focus
-                HWND hwnd3 = GetFocus ();
-                GetWindowRect (hwnd3 , &controlRect);
-                pNewFocus.x = controlRect.left;
-                pNewFocus.y = controlRect.top;
+                GetWindowRect (guiInfo.hwndFocus, &activeRect);
+                ptFocus.x = (activeRect.left + activeRect.right) / 2;
+                ptFocus.y = (activeRect.top + activeRect.bottom) / 2;
 
-                if(((pFocus.x != pNewFocus.x) || (pFocus.y != pNewFocus.y)))
+                if(guiInfo.hwndFocus && ((guiInfo.hwndFocus != pFocusWnd) || (pFocus.x != ptFocus.x) || (pFocus.y != ptFocus.y)))
                 {
                     //Update to new position
-                    pFocus = pNewFocus;
-                    cp = pNewFocus;
+                    pFocus = ptFocus;
+                    pFocusWnd = guiInfo.hwndFocus;
+                    if(!hasMoved)
+                        cp = ptFocus;
                     hasMoved = TRUE;
                 }
             }
@@ -451,6 +471,16 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
             break;
         }
 
+        case WM_CONTEXTMENU:
+            TrackPopupMenu(notifyMenu, 0, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), 0, hWnd, NULL);
+            break;
+
+        case WM_SIZE:
+        case WM_DISPLAYCHANGE:
+            bRecreateOffscreenDC = TRUE;
+            Refresh();
+            return DefWindowProc(hWnd, message, wParam, lParam);
+
         case WM_ERASEBKGND:
             // handle WM_ERASEBKGND by simply returning non-zero because we did all the drawing in WM_PAINT.
             break;
@@ -511,12 +541,6 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
 
             break;
 
-        case WM_CONTEXTMENU:
-        {
-            TrackPopupMenu(notifyMenu, 0, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), 0, hWnd, NULL);
-            break;
-        }
-
         default:
             return DefWindowProc(hWnd, message, wParam, lParam);
     }
index e39a2a9..3d6cda3 100644 (file)
@@ -18,7 +18,7 @@ BOOL bShowWarning = TRUE;
 
 BOOL bFollowMouse = TRUE;
 BOOL bFollowFocus = TRUE;
-BOOL bFollowCaret = FALSE; // FIXME: Default to false because AttachThreadInput seems to break.
+BOOL bFollowCaret = TRUE;
 
 BOOL bInvertColors = FALSE;
 BOOL bStartMinimized = FALSE;