https://git.reactos.org/?p=reactos.git;a=commitdiff;h=0864d2de85ccdb07913fe…
commit 0864d2de85ccdb07913fe9bb7404a83eac9f2d3e
Author:     Katayama Hirofumi MZ <katayama.hirofumi.mz(a)gmail.com>
AuthorDate: Wed Jan 31 04:36:59 2018 +0900
Commit:     Ged Murphy <gedmurphy(a)reactos.org>
CommitDate: Tue Jan 30 19:36:59 2018 +0000
    [SHIMGVW] Enable zooming
    * merge ZoomIn and ZoomOut functions
    * NULL to hbrBackground
    * use GET_X_LPARAM and GET_Y_LPARAM for WM_MOUSEWHEEL
---
 dll/win32/shimgvw/shimgvw.c | 193 ++++++++++++++++++++++++++++++++++++--------
 1 file changed, 161 insertions(+), 32 deletions(-)
diff --git a/dll/win32/shimgvw/shimgvw.c b/dll/win32/shimgvw/shimgvw.c
index 44bbf7cb0e..6d3471e8d4 100644
--- a/dll/win32/shimgvw/shimgvw.c
+++ b/dll/win32/shimgvw/shimgvw.c
@@ -2,10 +2,8 @@
  * PROJECT:         ReactOS Picture and Fax Viewer
  * FILE:            dll/win32/shimgvw/shimgvw.c
  * PURPOSE:         shimgvw.dll
- * PROGRAMMER:      Dmitry Chapyshev (dmitry(a)reactos.org)
- *
- * UPDATE HISTORY:
- *      28/05/2008  Created
+ * PROGRAMMERS:     Dmitry Chapyshev (dmitry(a)reactos.org)
+ *                  Katayama Hirofumi MZ (katayama.hirofumi.mz(a)gmail.com)
  */
 #define WIN32_NO_STATUS
@@ -19,6 +17,7 @@
 #include <winnls.h>
 #include <winreg.h>
 #include <wingdi.h>
+#include <windowsx.h>
 #include <objbase.h>
 #include <commctrl.h>
 #include <commdlg.h>
@@ -41,6 +40,105 @@ WNDPROC PrevProc = NULL;
 HWND hDispWnd, hToolBar;
+/* zooming */
+#define MIN_ZOOM 10
+#define MAX_ZOOM 1600
+UINT ZoomPercents = 100;
+static const UINT ZoomSteps[] =
+{
+    10, 25, 50, 100, 200, 400, 800, 1600
+};
+
+static void ZoomInOrOut(BOOL bZoomIn)
+{
+    INT i;
+
+    if (bZoomIn)    /* zoom in */
+    {
+        /* find next step */
+        for (i = 0; i < ARRAYSIZE(ZoomSteps); ++i)
+        {
+            if (ZoomPercents < ZoomSteps[i])
+                break;
+        }
+        if (i == ARRAYSIZE(ZoomSteps))
+            ZoomPercents = MAX_ZOOM;
+        else
+            ZoomPercents = ZoomSteps[i];
+
+        /* update tool bar buttons */
+        SendMessage(hToolBar, TB_ENABLEBUTTON, IDC_ZOOMM, TRUE);
+        if (ZoomPercents >= MAX_ZOOM)
+            SendMessage(hToolBar, TB_ENABLEBUTTON, IDC_ZOOMP, FALSE);
+        else
+            SendMessage(hToolBar, TB_ENABLEBUTTON, IDC_ZOOMP, TRUE);
+    }
+    else            /* zoom out */
+    {
+        /* find previous step */
+        for (i = ARRAYSIZE(ZoomSteps); i > 0; )
+        {
+            --i;
+            if (ZoomSteps[i] < ZoomPercents)
+                break;
+        }
+        if (i < 0)
+            ZoomPercents = MIN_ZOOM;
+        else
+            ZoomPercents = ZoomSteps[i];
+
+        /* update tool bar buttons */
+        SendMessage(hToolBar, TB_ENABLEBUTTON, IDC_ZOOMP, TRUE);
+        if (ZoomPercents <= MIN_ZOOM)
+            SendMessage(hToolBar, TB_ENABLEBUTTON, IDC_ZOOMM, FALSE);
+        else
+            SendMessage(hToolBar, TB_ENABLEBUTTON, IDC_ZOOMM, TRUE);
+    }
+
+    /* redraw */
+    InvalidateRect(hDispWnd, NULL, TRUE);
+}
+
+static void ResetZoom(void)
+{
+    RECT Rect;
+    UINT ImageWidth, ImageHeight;
+
+    /* get disp window size and image size */
+    GetClientRect(hDispWnd, &Rect);
+    GdipGetImageWidth(image, &ImageWidth);
+    GdipGetImageHeight(image, &ImageHeight);
+
+    /* compare two aspect rates. same as
+       (ImageHeight / ImageWidth < Rect.bottom / Rect.right) in real */
+    if (ImageHeight * Rect.right < Rect.bottom * ImageWidth)
+    {
+        if (Rect.right < ImageWidth)
+        {
+            /* it's large, shrink it */
+            ZoomPercents = (Rect.right * 100) / ImageWidth;
+        }
+        else
+        {
+            /* it's small. show as original size */
+            ZoomPercents = 100;
+        }
+    }
+    else
+    {
+        if (Rect.bottom < ImageHeight)
+        {
+            /* it's large, shrink it */
+            ZoomPercents = (Rect.bottom * 100) / ImageHeight;
+        }
+        else
+        {
+            /* it's small. show as original size */
+            ZoomPercents = 100;
+        }
+    }
+}
+
 /* ToolBar Buttons */
 static const TBBUTTON Buttons [] =
 {   /* iBitmap,     idCommand,   fsState,         fsStyle,     bReserved[2], dwData,
iString */
@@ -59,17 +157,26 @@ static const TBBUTTON Buttons [] =
 static void pLoadImage(LPWSTR szOpenFileName)
 {
+    /* check file presence */
     if (GetFileAttributesW(szOpenFileName) == 0xFFFFFFFF)
     {
         DPRINT1("File %s not found!\n", szOpenFileName);
         return;
     }
+    /* load now */
     GdipLoadImageFromFile(szOpenFileName, &image);
     if (!image)
     {
         DPRINT1("GdipLoadImageFromFile() failed\n");
+        return;
     }
+
+    /* reset zoom */
+    ResetZoom();
+
+    /* redraw */
+    InvalidateRect(hDispWnd, NULL, TRUE);
 }
 static void pSaveImageAs(HWND hwnd)
@@ -185,8 +292,6 @@ pLoadImageFromNode(SHIMGVW_FILENODE *node, HWND hwnd)
         }
         pLoadImage(node->FileName);
-        InvalidateRect(hDispWnd, NULL, TRUE);
-        UpdateWindow(hDispWnd);
     }
 }
@@ -330,8 +435,8 @@ static VOID
 ImageView_DrawImage(HWND hwnd)
 {
     GpGraphics *graphics;
-    UINT uImgWidth, uImgHeight;
-    UINT height = 0, width = 0, x = 0, y = 0;
+    UINT ImageWidth, ImageHeight;
+    INT ZoomedWidth, ZoomedHeight, x, y;
     PAINTSTRUCT ps;
     RECT rect;
     HDC hdc;
@@ -350,38 +455,37 @@ ImageView_DrawImage(HWND hwnd)
         return;
     }
-    GdipGetImageWidth(image, &uImgWidth);
-    GdipGetImageHeight(image, &uImgHeight);
+    GdipGetImageWidth(image, &ImageWidth);
+    GdipGetImageHeight(image, &ImageHeight);
     if (GetClientRect(hwnd, &rect))
     {
         FillRect(hdc, &rect, (HBRUSH)GetStockObject(WHITE_BRUSH));
-        if ((rect.right >= uImgWidth)&&(rect.bottom >= uImgHeight))
+        ZoomedWidth = (ImageWidth * ZoomPercents) / 100;
+        ZoomedHeight = (ImageHeight * ZoomPercents) / 100;
+
+        x = (rect.right - ZoomedWidth) / 2;
+        y = (rect.bottom - ZoomedHeight) / 2;
+
+        DPRINT("x = %d, y = %d, ImageWidth = %u, ImageHeight = %u\n");
+        DPRINT("rect.right = %ld, rect.bottom = %ld\n", rect.right,
rect.bottom);
+        DPRINT("ZoomPercents = %d, ZoomedWidth = %d, ZoomedHeight = %d\n",
+               ZoomPercents, ZoomedWidth, ZoomedWidth);
+
+        if (ZoomPercents % 100 == 0)
         {
-            width = uImgWidth;
-            height = uImgHeight;
+            GdipSetInterpolationMode(graphics, InterpolationModeNearestNeighbor);
+            GdipSetSmoothingMode(graphics, SmoothingModeNone);
         }
         else
         {
-            height = uImgHeight * (UINT)rect.right / uImgWidth;
-            if (height <= rect.bottom)
-            {
-                width = rect.right;
-            }
-            else
-            {
-                width = uImgWidth * (UINT)rect.bottom / uImgHeight;
-                height = rect.bottom;
-            }
+            GdipSetInterpolationMode(graphics, InterpolationModeHighQualityBilinear);
+            GdipSetSmoothingMode(graphics, SmoothingModeHighQuality);
         }
-        y = (rect.bottom / 2) - (height / 2);
-        x = (rect.right / 2) - (width / 2);
-
-        DPRINT("x = %d\ny = %d\nWidth = %d\nHeight = %d\n\nrect.right =
%d\nrect.bottom = %d\n\nuImgWidth = %d\nuImgHeight = %d\n", x, y, width, height,
rect.right, rect.bottom, uImgWidth, uImgHeight);
-        Rectangle(hdc, x - 1, y - 1, x + width + 1, y + height + 1);
-        GdipDrawImageRect(graphics, image, x, y, width, height);
+        Rectangle(hdc, x - 1, y - 1, x + ZoomedWidth + 1, y + ZoomedHeight + 1);
+        GdipDrawImageRectI(graphics, image, x, y, ZoomedWidth, ZoomedHeight);
     }
     GdipDeleteGraphics(graphics);
     EndPaint(hwnd, &ps);
@@ -524,6 +628,15 @@ ImageView_InitControls(HWND hwnd)
     ImageView_CreateToolBar(hwnd);
 }
+static VOID
+ImageView_OnMouseWheel(HWND hwnd, INT x, INT y, INT zDelta, UINT fwKeys)
+{
+    if (zDelta != 0)
+    {
+        ZoomInOrOut(zDelta > 0);
+    }
+}
+
 LRESULT CALLBACK
 ImageView_WndProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam)
 {
@@ -567,10 +680,14 @@ ImageView_WndProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM
lParam)
                 break;
                 case IDC_ZOOMP:
-
+                {
+                    ZoomInOrOut(TRUE);
+                }
                 break;
                 case IDC_ZOOMM:
-
+                {
+                    ZoomInOrOut(FALSE);
+                }
                 break;
                 case IDC_SAVE:
                     pSaveImageAs(hwnd);
@@ -597,6 +714,12 @@ ImageView_WndProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM
lParam)
         }
         break;
+        case WM_MOUSEWHEEL:
+            ImageView_OnMouseWheel(hwnd,
+                GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam),
+                (SHORT)HIWORD(wParam), (UINT)LOWORD(wParam));
+            break;
+
         case WM_NOTIFY:
         {
             LPNMHDR pnmhdr = (LPNMHDR)lParam;
@@ -660,6 +783,12 @@ ImageView_WndProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM
lParam)
             SendMessage(hToolBar, TB_AUTOSIZE, 0, 0);
             GetWindowRect(hToolBar, &rc);
             MoveWindow(hDispWnd, 1, 1, LOWORD(lParam) - 1, HIWORD(lParam) - (rc.bottom -
rc.top) - 1, TRUE);
+            /* is it maximized or restored? */
+            if (wParam == SIZE_MAXIMIZED || wParam == SIZE_RESTORED)
+            {
+                /* reset zoom */
+                ResetZoom();
+            }
             return 0L;
         }
         case WM_DESTROY:
@@ -710,7 +839,7 @@ ImageView_CreateWindow(HWND hwnd, LPWSTR szFileName)
     WndClass.style          = CS_HREDRAW | CS_VREDRAW;
     WndClass.hIcon          = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_APPICON));
     WndClass.hCursor        = LoadCursor(hInstance, IDC_ARROW);
-    WndClass.hbrBackground  = (HBRUSH)COLOR_WINDOW;
+    WndClass.hbrBackground  = NULL;   /* less flicker */
     if (!RegisterClass(&WndClass)) return -1;