[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
This commit is contained in:
Katayama Hirofumi MZ 2023-12-15 15:16:50 +09:00 committed by GitHub
parent ae534e8cee
commit f0179741d1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 204 additions and 165 deletions

View file

@ -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;
GdipCreateFromHDC(hdcMem, &graphics);
if (!graphics)
{
DPRINT1("error: GdipCreateFromHDC\n");
return;
}
// 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);
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));
GdipDrawImageRectI(graphics, g_pImage, x, y, ZoomedWidth, ZoomedHeight);
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);
}
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);
if (g_hMainWnd == NULL)
g_hMainWnd = hwnd;
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,
if (g_hMainWnd == NULL)
{
g_hMainWnd = hwnd;
exstyle |= WS_EX_CLIENTEDGE;
}
else if (g_hwndFullscreen == NULL)
{
g_hwndFullscreen = hwnd;
}
else
{
return FALSE;
}
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;

View file

@ -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