https://git.reactos.org/?p=reactos.git;a=commitdiff;h=f0179741d1a5aa67ee62a0f33b07962b63a5fad1

commit f0179741d1a5aa67ee62a0f33b07962b63a5fad1
Author:     Katayama Hirofumi MZ <katayama.hirofumi...@gmail.com>
AuthorDate: Fri Dec 15 15:16:50 2023 +0900
Commit:     GitHub <nore...@github.com>
CommitDate: Fri Dec 15 15:16:50 2023 +0900

    [SHIMGVW] Fix and improve zooming (#6167)
    
    - Add WC_ZOOM window class and
      use it for zooming.
    - Add ZoomWnd_OnDraw function
      and use it in ZoomWnd_OnPaint.
    - Use memory bitmap to reduce flickering.
    - Make rendering pixel-perfect.
    CORE-19220
---
 dll/win32/shimgvw/shimgvw.c | 360 ++++++++++++++++++++++++--------------------
 dll/win32/shimgvw/shimgvw.h |   1 +
 2 files changed, 200 insertions(+), 161 deletions(-)

diff --git a/dll/win32/shimgvw/shimgvw.c b/dll/win32/shimgvw/shimgvw.c
index 17dfc369e38..c84314b1828 100644
--- a/dll/win32/shimgvw/shimgvw.c
+++ b/dll/win32/shimgvw/shimgvw.c
@@ -21,16 +21,16 @@
 #define SLIDESHOW_TIMER_ID          0xFACE
 #define SLIDESHOW_TIMER_INTERVAL    5000 /* 5 seconds */
 
-HINSTANCE g_hInstance = NULL;
-HWND g_hMainWnd = NULL;
-HWND g_hwndFullscreen = NULL;
-SHIMGVW_SETTINGS g_Settings;
-SHIMGVW_FILENODE *g_pCurrentFile;
-GpImage *g_pImage = NULL;
+HINSTANCE           g_hInstance         = NULL;
+HWND                g_hMainWnd          = NULL;
+HWND                g_hwndFullscreen    = NULL;
+SHIMGVW_FILENODE *  g_pCurrentFile      = NULL;
+GpImage *           g_pImage            = NULL;
+SHIMGVW_SETTINGS    g_Settings;
 
 static const UINT s_ZoomSteps[] =
 {
-    5, 10, 25, 50, 100, 125, 200, 300, 500, 1000
+    5, 10, 25, 50, 100, 200, 300, 500, 1000, 2000, 4000
 };
 
 #define MIN_ZOOM s_ZoomSteps[0]
@@ -100,7 +100,6 @@ typedef struct tagPREVIEW_DATA
     HWND m_hwndZoom;
     HWND m_hwndToolBar;
     INT m_nZoomPercents;
-    WNDPROC m_fnPrevProc;
     ANIME m_Anime; /* Animation */
 } PREVIEW_DATA, *PPREVIEW_DATA;
 
@@ -116,30 +115,39 @@ Preview_IsMainWnd(HWND hwnd)
     return hwnd == g_hMainWnd;
 }
 
+static VOID
+Preview_RestartTimer(HWND hwnd)
+{
+    if (!Preview_IsMainWnd(hwnd))
+    {
+        KillTimer(hwnd, SLIDESHOW_TIMER_ID);
+        SetTimer(hwnd, SLIDESHOW_TIMER_ID, SLIDESHOW_TIMER_INTERVAL, NULL);
+    }
+}
+
 static VOID
 Preview_UpdateZoom(PPREVIEW_DATA pData, UINT NewZoom, BOOL bEnableBestFit, 
BOOL bEnableRealSize)
 {
     BOOL bEnableZoomIn, bEnableZoomOut;
     HWND hToolBar = pData->m_hwndToolBar;
 
-    /* If zoom has not been changed, ignore it */
-    if (pData->m_nZoomPercents == NewZoom)
-        return;
-
     pData->m_nZoomPercents = NewZoom;
 
     /* Check if a zoom button of the toolbar must be grayed */
-    bEnableZoomIn = (NewZoom < MAX_ZOOM);
+    bEnableZoomIn  = (NewZoom < MAX_ZOOM);
     bEnableZoomOut = (NewZoom > MIN_ZOOM);
 
     /* Update toolbar buttons */
-    SendMessageW(hToolBar, TB_ENABLEBUTTON, IDC_ZOOM_OUT, bEnableZoomOut);
-    SendMessageW(hToolBar, TB_ENABLEBUTTON, IDC_ZOOM_IN,  bEnableZoomIn);
-    SendMessageW(hToolBar, TB_ENABLEBUTTON, IDC_BEST_FIT, bEnableBestFit);
-    SendMessageW(hToolBar, TB_ENABLEBUTTON, IDC_REAL_SIZE, bEnableRealSize);
+    PostMessageW(hToolBar, TB_ENABLEBUTTON, IDC_ZOOM_OUT, bEnableZoomOut);
+    PostMessageW(hToolBar, TB_ENABLEBUTTON, IDC_ZOOM_IN,  bEnableZoomIn);
+    PostMessageW(hToolBar, TB_ENABLEBUTTON, IDC_BEST_FIT, bEnableBestFit);
+    PostMessageW(hToolBar, TB_ENABLEBUTTON, IDC_REAL_SIZE, bEnableRealSize);
 
     /* Redraw the display window */
-    InvalidateRect(pData->m_hwndZoom, NULL, FALSE);
+    InvalidateRect(pData->m_hwndZoom, NULL, TRUE);
+
+    /* Restart timer if necessary */
+    Preview_RestartTimer(pData->m_hwnd);
 }
 
 static VOID
@@ -389,8 +397,8 @@ static VOID
 Preview_UpdateUI(PPREVIEW_DATA pData)
 {
     BOOL bEnable = (g_pImage != NULL);
-    SendMessageW(pData->m_hwndToolBar, TB_ENABLEBUTTON, IDC_SAVEAS, bEnable);
-    SendMessageW(pData->m_hwndToolBar, TB_ENABLEBUTTON, IDC_PRINT, bEnable);
+    PostMessageW(pData->m_hwndToolBar, TB_ENABLEBUTTON, IDC_SAVEAS, bEnable);
+    PostMessageW(pData->m_hwndToolBar, TB_ENABLEBUTTON, IDC_PRINT, bEnable);
 
     if (!Preview_IsMainWnd(pData->m_hwnd))
         Preview_ResetZoom(pData);
@@ -530,7 +538,7 @@ pFreeFileList(SHIMGVW_FILENODE *root)
     }
 }
 
-static HBRUSH CreateCheckerBoardBrush(HDC hdc)
+static HBRUSH CreateCheckerBoardBrush(VOID)
 {
     static const CHAR pattern[] =
         
"\x28\x00\x00\x00\x10\x00\x00\x00\x10\x00\x00\x00\x01\x00\x04\x00\x00\x00"
@@ -551,59 +559,63 @@ static HBRUSH CreateCheckerBoardBrush(HDC hdc)
 }
 
 static VOID
-ZoomWnd_OnPaint(PPREVIEW_DATA pData, HWND hwnd)
+ZoomWnd_OnDraw(
+    PPREVIEW_DATA pData,
+    HDC hdc,
+    LPRECT prcPaint,
+    LPRECT prcClient)
 {
     GpGraphics *graphics;
-    INT ZoomedWidth, ZoomedHeight, x, y;
-    PAINTSTRUCT ps;
-    RECT rect, margin;
-    HDC hdc;
+    INT ZoomedWidth, ZoomedHeight;
+    RECT rect, rcClient = *prcClient;
+    HDC hdcMem;
     HBRUSH hBrush;
     HPEN hPen;
-    HGDIOBJ hbrOld, hPenOld, hFontOld;
+    HGDIOBJ hbrOld, hbmOld, hPenOld;
     UINT uFlags;
+    HBITMAP hbmMem;
+    SIZE paintSize = { prcPaint->right - prcPaint->left, prcPaint->bottom - 
prcPaint->top };
+    COLORREF color0, color1;
+    GpImageAttributes *imageAttributes;
 
-    hdc = BeginPaint(hwnd, &ps);
-    if (!hdc)
-    {
-        DPRINT1("BeginPaint() failed\n");
-        return;
-    }
-
-    GdipCreateFromHDC(hdc, &graphics);
-    if (!graphics)
-    {
-        DPRINT1("GdipCreateFromHDC() failed\n");
-        return;
-    }
-
-    GetClientRect(hwnd, &rect);
+    /* We use a memory bitmap to reduce flickering */
+    hdcMem = CreateCompatibleDC(hdc);
+    hbmMem = CreateCompatibleBitmap(hdc, paintSize.cx, paintSize.cy);
+    hbmOld = SelectObject(hdcMem, hbmMem);
 
+    /* Choose colors */
     if (Preview_IsMainWnd(pData->m_hwnd))
     {
-        hPen = (HPEN)GetStockObject(BLACK_PEN);
-        hBrush = (HBRUSH)GetStockObject(WHITE_BRUSH);
-        SetTextColor(hdc, RGB(0, 0, 0)); /* Black text */
+        color0 = GetSysColor(COLOR_WINDOW);
+        color1 = GetSysColor(COLOR_WINDOWTEXT);
     }
     else
     {
-        hPen = (HPEN)GetStockObject(WHITE_PEN);
-        hBrush = (HBRUSH)GetStockObject(BLACK_BRUSH);
-        SetTextColor(hdc, RGB(255, 255, 255)); /* White text */
+        color0 = RGB(0, 0, 0);
+        color1 = RGB(255, 255, 255);
     }
 
+    hBrush = CreateSolidBrush(color0);
+    SetBkColor(hdcMem, color0);
+
+    hPen = CreatePen(PS_SOLID, 1, color1);
+    SetTextColor(hdcMem, color1);
+
+    /* Fill background */
+    SetRect(&rect, 0, 0, paintSize.cx, paintSize.cy);
+    FillRect(hdcMem, &rect, hBrush);
+
+    DeleteObject(hBrush);
+
     if (g_pImage == NULL)
     {
         WCHAR szText[128];
         LoadStringW(g_hInstance, IDS_NOPREVIEW, szText, _countof(szText));
 
-        FillRect(hdc, &rect, hBrush);
-
-        hFontOld = SelectObject(hdc, GetStockObject(DEFAULT_GUI_FONT));
-        SetBkMode(hdc, TRANSPARENT);
-        DrawTextW(hdc, szText, -1, &rect, DT_SINGLELINE | DT_CENTER | 
DT_VCENTER |
-                                          DT_NOPREFIX);
-        SelectObject(hdc, hFontOld);
+        SelectObject(hdcMem, GetStockFont(DEFAULT_GUI_FONT));
+        OffsetRect(&rcClient, -prcPaint->left, -prcPaint->top);
+        DrawTextW(hdcMem, szText, -1, &rcClient, DT_SINGLELINE | DT_CENTER | 
DT_VCENTER |
+                                                 DT_NOPREFIX);
     }
     else
     {
@@ -612,34 +624,17 @@ ZoomWnd_OnPaint(PPREVIEW_DATA pData, HWND hwnd)
         GdipGetImageWidth(g_pImage, &ImageWidth);
         GdipGetImageHeight(g_pImage, &ImageHeight);
 
-        ZoomedWidth = (ImageWidth * pData->m_nZoomPercents) / 100;
+        ZoomedWidth  = (ImageWidth  * pData->m_nZoomPercents) / 100;
         ZoomedHeight = (ImageHeight * pData->m_nZoomPercents) / 100;
 
-        x = (rect.right - ZoomedWidth) / 2;
-        y = (rect.bottom - ZoomedHeight) / 2;
-
-        // Fill top part
-        margin = rect;
-        margin.bottom = y - 1;
-        FillRect(hdc, &margin, hBrush);
-        // Fill bottom part
-        margin.top = y + ZoomedHeight + 1;
-        margin.bottom = rect.bottom;
-        FillRect(hdc, &margin, hBrush);
-        // Fill left part
-        margin.top = y - 1;
-        margin.bottom = y + ZoomedHeight + 1;
-        margin.right = x - 1;
-        FillRect(hdc, &margin, hBrush);
-        // Fill right part
-        margin.left = x + ZoomedWidth + 1;
-        margin.right = rect.right;
-        FillRect(hdc, &margin, hBrush);
-
-        DPRINT("x = %d, y = %d, ImageWidth = %u, ImageHeight = %u\n");
-        DPRINT("rect.right = %ld, rect.bottom = %ld\n", rect.right, 
rect.bottom);
-        DPRINT("m_nZoomPercents = %d, ZoomedWidth = %d, ZoomedHeight = %d\n",
-               pData->m_nZoomPercents, ZoomedWidth, ZoomedWidth);
+        GdipCreateFromHDC(hdcMem, &graphics);
+        if (!graphics)
+        {
+            DPRINT1("error: GdipCreateFromHDC\n");
+            return;
+        }
+
+        GdipGetImageFlags(g_pImage, &uFlags);
 
         if (pData->m_nZoomPercents % 100 == 0)
         {
@@ -652,30 +647,61 @@ ZoomWnd_OnPaint(PPREVIEW_DATA pData, HWND hwnd)
             GdipSetSmoothingMode(graphics, SmoothingModeHighQuality);
         }
 
-        uFlags = 0;
-        GdipGetImageFlags(g_pImage, &uFlags);
+        rect.left   = (rcClient.right  - ZoomedWidth ) / 2;
+        rect.top    = (rcClient.bottom - ZoomedHeight) / 2;
+        rect.right  = rect.left + ZoomedWidth;
+        rect.bottom = rect.top  + ZoomedHeight;
+        OffsetRect(&rect, -prcPaint->left, -prcPaint->top);
 
-        hPenOld = SelectObject(hdc, hPen);
+        InflateRect(&rect, +1, +1); /* Add Rectangle() pen width */
+
+        /* Draw a rectangle. Fill by checker board if necessary */
         if (uFlags & (ImageFlagsHasAlpha | ImageFlagsHasTranslucent))
-        {
-            HBRUSH hbr = CreateCheckerBoardBrush(hdc);
-            hbrOld = SelectObject(hdc, hbr);
-            Rectangle(hdc, x - 1, y - 1, x + ZoomedWidth + 1, y + ZoomedHeight 
+ 1);
-            SelectObject(hdc, hbrOld);
-            DeleteObject(hbr);
-        }
+            hbrOld = SelectObject(hdcMem, CreateCheckerBoardBrush());
         else
-        {
-            hbrOld = SelectObject(hdc, GetStockObject(NULL_BRUSH));
-            Rectangle(hdc, x - 1, y - 1, x + ZoomedWidth + 1, y + ZoomedHeight 
+ 1);
-            SelectObject(hdc, hbrOld);
-        }
-        SelectObject(hdc, hPenOld);
+            hbrOld = SelectObject(hdcMem, GetStockBrush(NULL_BRUSH));
+        hPenOld = SelectObject(hdcMem, hPen);
+        Rectangle(hdcMem, rect.left, rect.top, rect.right, rect.bottom);
+        DeleteObject(SelectObject(hdcMem, hbrOld));
+        DeleteObject(SelectObject(hdcMem, hPenOld));
+
+        InflateRect(&rect, -1, -1); /* Subtract Rectangle() pen width */
+
+        /* Image attributes are required to draw image correctly */
+        GdipCreateImageAttributes(&imageAttributes);
+        GdipSetImageAttributesWrapMode(imageAttributes, WrapModeTile,
+                                       GetBkColor(hdcMem) | 0xFF000000, TRUE);
+
+        /* Draw image. -0.5f is used for interpolation */
+        GdipDrawImageRectRect(graphics, g_pImage,
+                              rect.left, rect.top,
+                              rect.right - rect.left, rect.bottom - rect.top,
+                              -0.5f, -0.5f, ImageWidth, ImageHeight,
+                              UnitPixel, imageAttributes, NULL, NULL);
+
+        GdipDisposeImageAttributes(imageAttributes);
+        GdipDeleteGraphics(graphics);
+    }
 
-        GdipDrawImageRectI(graphics, g_pImage, x, y, ZoomedWidth, 
ZoomedHeight);
+    BitBlt(hdc, prcPaint->left, prcPaint->top, paintSize.cx, paintSize.cy, 
hdcMem, 0, 0, SRCCOPY);
+    DeleteObject(SelectObject(hdcMem, hbmOld));
+    DeleteDC(hdcMem);
+}
+
+static VOID
+ZoomWnd_OnPaint(PPREVIEW_DATA pData, HWND hwnd)
+{
+    PAINTSTRUCT ps;
+    HDC hDC;
+    RECT rcClient;
+
+    hDC = BeginPaint(hwnd, &ps);
+    if (hDC)
+    {
+        GetClientRect(hwnd, &rcClient);
+        ZoomWnd_OnDraw(pData, hDC, &ps.rcPaint, &rcClient);
+        EndPaint(hwnd, &ps);
     }
-    GdipDeleteGraphics(graphics);
-    EndPaint(hwnd, &ps);
 }
 
 static VOID
@@ -727,13 +753,12 @@ Preview_CreateToolBar(PPREVIEW_DATA pData)
     HWND hwndToolBar;
     HIMAGELIST hImageList, hOldImageList;
     DWORD style = WS_CHILD | WS_VISIBLE | TBSTYLE_FLAT | TBSTYLE_TOOLTIPS;
-    DWORD exstyle = 0;
 
     if (!Preview_IsMainWnd(pData->m_hwnd))
         return TRUE; /* FIXME */
 
     style |= CCS_BOTTOM;
-    hwndToolBar = CreateWindowExW(exstyle, TOOLBARCLASSNAMEW, NULL, style,
+    hwndToolBar = CreateWindowExW(0, TOOLBARCLASSNAMEW, NULL, style,
                                   0, 0, 0, 0, pData->m_hwnd, NULL, 
g_hInstance, NULL);
     if (!hwndToolBar)
         return FALSE;
@@ -762,12 +787,39 @@ Preview_CreateToolBar(PPREVIEW_DATA pData)
     return TRUE;
 }
 
+static VOID
+Preview_EndSlideShow(HWND hwnd)
+{
+    if (Preview_IsMainWnd(hwnd))
+        return;
+
+    KillTimer(hwnd, SLIDESHOW_TIMER_ID);
+    ShowWindow(hwnd, SW_HIDE);
+    ShowWindow(g_hMainWnd, SW_SHOWNORMAL);
+    Preview_ResetZoom(Preview_GetData(g_hMainWnd));
+}
+
+static VOID
+ZoomWnd_OnButtonDown(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+    HWND hParent = GetParent(hwnd);
+    if (!Preview_IsMainWnd(hParent))
+        Preview_EndSlideShow(hParent);
+}
+
 LRESULT CALLBACK
 ZoomWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
 {
     PPREVIEW_DATA pData = Preview_GetData(hwnd);
     switch (uMsg)
     {
+        case WM_LBUTTONDOWN:
+        case WM_MBUTTONDOWN:
+        case WM_RBUTTONDOWN:
+        {
+            ZoomWnd_OnButtonDown(hwnd, uMsg, wParam, lParam);
+            break;
+        }
         case WM_PAINT:
         {
             ZoomWnd_OnPaint(pData, hwnd);
@@ -781,7 +833,7 @@ ZoomWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM 
lParam)
         }
         default:
         {
-            return CallWindowProcW(pData->m_fnPrevProc, hwnd, uMsg, wParam, 
lParam);
+            return DefWindowProcW(hwnd, uMsg, wParam, lParam);
         }
     }
     return 0;
@@ -790,21 +842,29 @@ ZoomWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM 
lParam)
 static BOOL
 Preview_OnCreate(HWND hwnd, LPCREATESTRUCT pCS)
 {
+    DWORD exstyle = 0;
     HWND hwndZoom;
     PPREVIEW_DATA pData = QuickAlloc(sizeof(PREVIEW_DATA), TRUE);
     pData->m_hwnd = hwnd;
     SetWindowLongPtrW(hwnd, GWLP_USERDATA, (LONG_PTR)pData);
 
+    DragAcceptFiles(hwnd, TRUE);
+
     if (g_hMainWnd == NULL)
+    {
         g_hMainWnd = hwnd;
+        exstyle |= WS_EX_CLIENTEDGE;
+    }
     else if (g_hwndFullscreen == NULL)
+    {
         g_hwndFullscreen = hwnd;
+    }
     else
+    {
         return FALSE;
+    }
 
-    DragAcceptFiles(hwnd, TRUE);
-
-    hwndZoom = CreateWindowExW(WS_EX_CLIENTEDGE, WC_STATIC, NULL, WS_CHILD | 
WS_VISIBLE,
+    hwndZoom = CreateWindowExW(exstyle, WC_ZOOM, NULL, WS_CHILD | WS_VISIBLE,
                                0, 0, 0, 0, hwnd, NULL, g_hInstance, NULL);
     if (!hwndZoom)
     {
@@ -814,10 +874,7 @@ Preview_OnCreate(HWND hwnd, LPCREATESTRUCT pCS)
 
     pData->m_hwndZoom = hwndZoom;
     SetWindowLongPtrW(hwndZoom, GWLP_USERDATA, (LONG_PTR)pData);
-
-    SetClassLongPtr(pData->m_hwndZoom, GCL_STYLE, CS_HREDRAW | CS_VREDRAW);
-    pData->m_fnPrevProc = (WNDPROC)SetWindowLongPtrW(pData->m_hwndZoom,
-                                                    GWLP_WNDPROC, 
(LPARAM)ZoomWndProc);
+    Anime_SetTimerWnd(&pData->m_Anime, pData->m_hwndZoom);
 
     if (!Preview_CreateToolBar(pData))
     {
@@ -825,8 +882,6 @@ Preview_OnCreate(HWND hwnd, LPCREATESTRUCT pCS)
         return FALSE;
     }
 
-    Anime_SetTimerWnd(&pData->m_Anime, pData->m_hwndZoom);
-
     if (pCS && pCS->lpCreateParams)
     {
         LPCWSTR pszFileName = (LPCWSTR)pCS->lpCreateParams;
@@ -867,6 +922,7 @@ Preview_OnMoveSize(HWND hwnd)
     wp.length = sizeof(WINDOWPLACEMENT);
     GetWindowPlacement(hwnd, &wp);
 
+    /* Remember window position and size */
     prc = &wp.rcNormalPosition;
     g_Settings.X = prc->left;
     g_Settings.Y = prc->top;
@@ -906,18 +962,6 @@ Preview_OnSize(HWND hwnd)
     }
 }
 
-static VOID
-Preview_EndSlideShow(HWND hwnd)
-{
-    if (Preview_IsMainWnd(hwnd))
-        return;
-
-    KillTimer(hwnd, SLIDESHOW_TIMER_ID);
-    ShowWindow(hwnd, SW_HIDE);
-    ShowWindow(g_hMainWnd, SW_SHOWNORMAL);
-    Preview_ResetZoom(Preview_GetData(g_hMainWnd));
-}
-
 static VOID
 Preview_Delete(PPREVIEW_DATA pData)
 {
@@ -995,37 +1039,35 @@ Preview_Edit(HWND hwnd)
 }
 
 static VOID
-Preview_StartSlideShow(PPREVIEW_DATA pData)
+Preview_ToggleSlideShow(PPREVIEW_DATA pData)
 {
-    HWND hwnd = g_hwndFullscreen;
-    DWORD style = WS_POPUP | WS_CLIPSIBLINGS, exstyle = WS_EX_TOPMOST;
-
-    ShowWindow(pData->m_hwnd, SW_HIDE);
-
-    if (!IsWindow(hwnd))
+    if (!IsWindow(g_hwndFullscreen))
     {
+        DWORD style = WS_POPUP | WS_CLIPSIBLINGS, exstyle = WS_EX_TOPMOST;
         WCHAR szTitle[256];
         LoadStringW(g_hInstance, IDS_APPTITLE, szTitle, _countof(szTitle));
-        hwnd = CreateWindowExW(exstyle, WC_PREVIEW, szTitle, style,
-                               0, 0, 0, 0, NULL, NULL, g_hInstance, NULL);
+        g_hwndFullscreen = CreateWindowExW(exstyle, WC_PREVIEW, szTitle, style,
+                                           0, 0, 0, 0, NULL, NULL, 
g_hInstance, NULL);
     }
 
-    ShowWindow(hwnd, SW_SHOWMAXIMIZED);
-    UpdateWindow(hwnd);
-
-    SetTimer(hwnd, SLIDESHOW_TIMER_ID, SLIDESHOW_TIMER_INTERVAL, NULL);
+    if (IsWindowVisible(g_hwndFullscreen))
+    {
+        ShowWindow(g_hwndFullscreen, SW_HIDE);
+        ShowWindow(g_hMainWnd, SW_SHOWNORMAL);
+        KillTimer(g_hwndFullscreen, SLIDESHOW_TIMER_ID);
+    }
+    else
+    {
+        ShowWindow(g_hMainWnd, SW_HIDE);
+        ShowWindow(g_hwndFullscreen, SW_SHOWMAXIMIZED);
+        Preview_RestartTimer(g_hwndFullscreen);
+    }
 }
 
 static VOID
 Preview_GoNextPic(PPREVIEW_DATA pData, BOOL bNext)
 {
-    HWND hwnd = pData->m_hwnd;
-    if (!Preview_IsMainWnd(hwnd))
-    {
-        KillTimer(hwnd, SLIDESHOW_TIMER_ID);
-        SetTimer(hwnd, SLIDESHOW_TIMER_ID, SLIDESHOW_TIMER_INTERVAL, NULL);
-    }
-
+    Preview_RestartTimer(pData->m_hwnd);
     if (g_pCurrentFile)
     {
         if (bNext)
@@ -1061,10 +1103,7 @@ Preview_OnCommand(HWND hwnd, UINT nCommandID)
             break;
 
         case IDC_SLIDE_SHOW:
-            if (Preview_IsMainWnd(hwnd))
-                Preview_StartSlideShow(pData);
-            else
-                Preview_EndSlideShow(hwnd);
+            Preview_ToggleSlideShow(pData);
             break;
 
         case IDC_ZOOM_IN:
@@ -1162,7 +1201,6 @@ Preview_OnDestroy(HWND hwnd)
 
     Anime_FreeInfo(&pData->m_Anime);
 
-    SetWindowLongPtrW(pData->m_hwndZoom, GWLP_WNDPROC, 
(LPARAM)pData->m_fnPrevProc);
     SetWindowLongPtrW(pData->m_hwndZoom, GWLP_USERDATA, 0);
     DestroyWindow(pData->m_hwndZoom);
     pData->m_hwndZoom = NULL;
@@ -1170,6 +1208,7 @@ Preview_OnDestroy(HWND hwnd)
     DestroyWindow(pData->m_hwndToolBar);
     pData->m_hwndToolBar = NULL;
 
+    SetWindowLongPtrW(pData->m_hwnd, GWLP_USERDATA, 0);
     QuickFree(pData);
 
     PostQuitMessage(0);
@@ -1190,13 +1229,6 @@ Preview_OnDropFiles(HWND hwnd, HDROP hDrop)
     DragFinish(hDrop);
 }
 
-static VOID
-Preview_OnButtonDown(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
-{
-    if (!Preview_IsMainWnd(hwnd))
-        Preview_EndSlideShow(hwnd);
-}
-
 LRESULT CALLBACK
 PreviewWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
 {
@@ -1245,11 +1277,11 @@ PreviewWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, 
LPARAM lParam)
             Preview_OnDropFiles(hwnd, (HDROP)wParam);
             break;
         }
-        case WM_LBUTTONDOWN:
-        case WM_MBUTTONDOWN:
-        case WM_RBUTTONDOWN:
+        case WM_SYSCOLORCHANGE:
         {
-            Preview_OnButtonDown(hwnd, uMsg, wParam, lParam);
+            PPREVIEW_DATA pData = Preview_GetData(hwnd);
+            InvalidateRect(pData->m_hwnd, NULL, TRUE);
+            InvalidateRect(pData->m_hwndZoom, NULL, TRUE);
             break;
         }
         case WM_DESTROY:
@@ -1311,7 +1343,13 @@ ImageView_Main(HWND hwnd, LPCWSTR szFileName)
     WndClass.style          = CS_HREDRAW | CS_VREDRAW;
     WndClass.hIcon          = LoadIconW(g_hInstance, 
MAKEINTRESOURCEW(IDI_APP_ICON));
     WndClass.hCursor        = LoadCursorW(NULL, (LPCWSTR)IDC_ARROW);
-    WndClass.hbrBackground  = NULL;   /* less flicker */
+    WndClass.hbrBackground  = (HBRUSH)UlongToHandle(COLOR_3DFACE + 1);
+    if (!RegisterClassW(&WndClass))
+        return -1;
+    WndClass.lpszClassName  = WC_ZOOM;
+    WndClass.lpfnWndProc    = ZoomWndProc;
+    WndClass.style          = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;
+    WndClass.hbrBackground  = GetStockBrush(NULL_BRUSH); /* less flicker */
     if (!RegisterClassW(&WndClass))
         return -1;
 
diff --git a/dll/win32/shimgvw/shimgvw.h b/dll/win32/shimgvw/shimgvw.h
index cebbaea06b3..0506c2a6af2 100644
--- a/dll/win32/shimgvw/shimgvw.h
+++ b/dll/win32/shimgvw/shimgvw.h
@@ -49,6 +49,7 @@ typedef struct tagSHIMGVW_FILENODE
 } SHIMGVW_FILENODE;
 
 #define WC_PREVIEW L"ShImgVw:CPreviewWnd"
+#define WC_ZOOM L"ShImgVw:CZoomWnd"
 
 /* Animation */
 typedef struct tagANIME

Reply via email to