ZoomIt smooth image zooming (#42200)

Added smooth image option that results in GDI+ image smoothing for
static zoom and Magnifier API image smoothing for live zoom.

---------

Co-authored-by: Mark Russinovich <markruss@ntdev.microsoft.com>
Co-authored-by: Clint Rutkas <clint@rutkas.com>
Co-authored-by: Niels Laute <niels.laute@live.nl>
This commit is contained in:
Mark Russinovich
2025-10-07 11:20:00 -07:00
committed by GitHub
parent 14ff4dbc8c
commit e04e6a11d1
10 changed files with 159 additions and 73 deletions

View File

@@ -856,6 +856,7 @@ linkid
LINKOVERLAY
LINQTo
listview
LIVEDRAW
LIVEZOOM
LLKH
llkhf
@@ -1237,6 +1238,7 @@ PATPAINT
pbc
pbi
PBlob
pbrush
pcb
pcch
pcelt

View File

@@ -96,7 +96,10 @@ typedef struct {
#define SHALLOW_DESTROY 2
#define LIVE_DRAW_ZOOM 3
#define PEN_COLOR_HIGHLIGHT(Pencolor) (Pencolor >> 24) != 0xFF
#define PEN_COLOR_HIGHLIGHT(Pencolor) ((Pencolor >> 24) != 0xFF)
#define PEN_COLOR_BLUR(Pencolor) ((Pencolor & 0x00FFFFFF) == COLOR_BLUR)
#define CURSOR_SAVE_MARGIN 4
typedef BOOL (__stdcall *type_pGetMonitorInfo)(
@@ -143,7 +146,14 @@ typedef BOOL(__stdcall *type_pMagSetWindowFilterList)(
int count,
HWND* pHWND
);
typedef BOOL (__stdcall *type_pMagInitialize)(VOID);
typedef BOOL(__stdcall* type_pMagSetLensUseBitmapSmoothing)(
_In_ HWND,
_In_ BOOL
);
typedef BOOL(__stdcall* type_MagSetFullscreenUseBitmapSmoothing)(
BOOL fUseBitmapSmoothing
);
typedef BOOL(__stdcall* type_pMagInitialize)(VOID);
typedef BOOL(__stdcall *type_pGetPointerType)(
_In_ UINT32 pointerId,

View File

@@ -2,13 +2,6 @@
//
#include "resource.h"
// version.h and branding.h are different in the Sysinternals repository,
// keep the includes as such, here.
// From $(MSBuildThisFileDirectory)..\..\..\common\version
#include "version.h"
// From $(MSBuildThisFileDirectory)PowerToys
#include "branding.h"
#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
@@ -75,8 +68,8 @@ APPICON ICON "appicon.ico"
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION FILE_VERSION
PRODUCTVERSION PRODUCT_VERSION
FILEVERSION 9,10,0,0
PRODUCTVERSION 9,10,0,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@@ -91,14 +84,14 @@ BEGIN
BEGIN
BLOCK "040904b0"
BEGIN
VALUE "CompanyName", COMPANY_NAME
VALUE "FileDescription", FILE_DESCRIPTION
VALUE "FileVersion", FILE_VERSION_STRING
VALUE "InternalName", INTERNAL_NAME
VALUE "LegalCopyright", COPYRIGHT_NOTE
VALUE "OriginalFilename", ORIGINAL_FILENAME
VALUE "ProductName", ZOOMIT_PRODUCT_NAME
VALUE "ProductVersion", PRODUCT_VERSION_STRING
VALUE "CompanyName", "Microsoft Corporation"
VALUE "FileDescription", "Sysinternals Screen Magnifier"
VALUE "FileVersion", "9.10"
VALUE "InternalName", "ZoomIt"
VALUE "LegalCopyright", "Copyright (C) Microsoft Corporation. All rights reserved."
VALUE "OriginalFilename", "PowerToys.ZoomIt.exe"
VALUE "ProductName", "PowerToys Sysinternals ZoomIt"
VALUE "ProductVersion", "9.10"
END
END
BLOCK "VarFileInfo"
@@ -122,7 +115,7 @@ BEGIN
DEFPUSHBUTTON "OK",IDOK,166,306,50,14
PUSHBUTTON "Cancel",IDCANCEL,223,306,50,14
LTEXT "ZoomIt v9.01",IDC_VERSION,42,7,73,10
LTEXT "Copyright © 2006-2025 Mark Russinovich",IDC_COPYRIGHT,42,17,166,8
LTEXT "Copyright <EFBFBD> 2006-2025 Mark Russinovich",IDC_COPYRIGHT,42,17,231,8
CONTROL "<a HREF=""https://www.sysinternals.com"">Sysinternals - www.sysinternals.com</a>",IDC_LINK,
"SysLink",WS_TABSTOP,42,26,150,9
ICON "APPICON",IDC_STATIC,12,9,20,20
@@ -149,7 +142,8 @@ BEGIN
CONTROL "",IDC_TIMER_POS7,"Button",BS_AUTORADIOBUTTON,63,108,10,10
CONTROL "",IDC_TIMER_POS8,"Button",BS_AUTORADIOBUTTON,79,108,10,10
CONTROL "",IDC_TIMER_POS9,"Button",BS_AUTORADIOBUTTON,97,108,10,10
CONTROL "Show background bitmap:",IDC_CHECK_BACKGROUND_FILE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,3,122,99,10,WS_EX_RIGHT
CONTROL "Show background bitmap:",IDC_CHECK_BACKGROUND_FILE,
"Button",BS_AUTOCHECKBOX | WS_TABSTOP,3,122,99,10,WS_EX_RIGHT
CONTROL "Use faded desktop as background",IDC_STATIC_DESKTOP_BACKGROUND,
"Button",BS_AUTORADIOBUTTON | WS_GROUP | WS_TABSTOP,46,135,125,10
CONTROL "Use image file as background",IDC_STATIC_BACKGROUND_FILE,
@@ -165,23 +159,25 @@ BEGIN
CONTROL "",IDC_STATIC,"Static",SS_BLACKFRAME | SS_SUNKEN,7,196,193,1,WS_EX_CLIENTEDGE
END
ZOOM DIALOGEX 0, 0, 260, 158
ZOOM DIALOGEX 0, 0, 260, 170
STYLE DS_SETFONT | DS_FIXEDSYS | DS_CONTROL | WS_CHILD | WS_CLIPSIBLINGS | WS_SYSMENU
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
CONTROL "",IDC_HOTKEY,"msctls_hotkey32",WS_BORDER | WS_TABSTOP,59,57,80,12
LTEXT "After toggling ZoomIt you can zoom in with the mouse wheel or up and down arrow keys. Exit zoom mode with Escape or by pressing the right mouse button.",IDC_STATIC,7,6,246,26
LTEXT "Zoom Toggle:",IDC_STATIC,7,59,51,8
CONTROL "",IDC_ZOOM_SLIDER,"msctls_trackbar32",TBS_AUTOTICKS | TBS_BOTH | TBS_NOTICKS | WS_TABSTOP,53,104,150,15,WS_EX_TRANSPARENT
LTEXT "Specify the initial level of magnification when zooming in:",IDC_STATIC,7,91,215,10
LTEXT "1.25",IDC_STATIC,52,122,16,8
LTEXT "1.5",IDC_STATIC,82,122,12,8
LTEXT "1.75",IDC_STATIC,108,122,16,8
LTEXT "2.0",IDC_STATIC,138,122,12,8
LTEXT "3.0",IDC_STATIC,164,122,12,8
LTEXT "4.0",IDC_STATIC,190,122,12,8
CONTROL "",IDC_ZOOM_SLIDER,"msctls_trackbar32",TBS_AUTOTICKS | TBS_BOTH | TBS_NOTICKS | WS_TABSTOP,53,118,150,15,WS_EX_TRANSPARENT
LTEXT "Specify the initial level of magnification when zooming in:",IDC_STATIC,7,105,215,10
LTEXT "1.25",IDC_STATIC,52,136,16,8
LTEXT "1.5",IDC_STATIC,82,136,12,8
LTEXT "1.75",IDC_STATIC,108,136,16,8
LTEXT "2.0",IDC_STATIC,138,136,12,8
LTEXT "3.0",IDC_STATIC,164,136,12,8
LTEXT "4.0",IDC_STATIC,190,136,12,8
CONTROL "Animate zoom in and zoom out:",IDC_ANIMATE_ZOOM,"Button",BS_AUTOCHECKBOX | BS_LEFTTEXT | WS_TABSTOP,7,74,116,10
LTEXT "Copy a zoomed screen with Ctrl+C or save it by typing Ctrl+S. Crop the copy or save region by entering Ctrl+Shift instead of Ctrl.",IDC_STATIC,7,34,246,17
CONTROL "Smooth zoomed image:",IDC_SMOOTH_IMAGE,"Button",BS_AUTOCHECKBOX | BS_LEFTTEXT | WS_TABSTOP,7,88,116,10
LTEXT "Copy a zoomed screen with Ctrl+C or save it by typing Ctrl+S. Crop the copy or save region by entering Ctrl+Shift instead of Ctrl.",IDC_STATIC,7,148,246,17
LTEXT "Copy a zoomed screen with Ctrl+C or save it by typing Ctrl+S. Crop the copy or save region by entering Ctrl+Shift instead of Ctrl.",IDC_STATIC,6,34,246,18
END
DRAW DIALOGEX 0, 0, 260, 228
@@ -295,7 +291,8 @@ BEGIN
LTEXT "DemoType toggle:",IDC_STATIC,7,157,63,8
PUSHBUTTON "&...",IDC_DEMOTYPE_BROWSE,231,137,16,13
CONTROL "",IDC_DEMOTYPE_SPEED_SLIDER,"msctls_trackbar32",TBS_AUTOTICKS | TBS_BOTH | TBS_NOTICKS | WS_TABSTOP,52,202,150,11,WS_EX_TRANSPARENT
CONTROL "Drive input with typing:",IDC_DEMOTYPE_USER_DRIVEN,"Button",BS_AUTOCHECKBOX | BS_LEFTTEXT | WS_TABSTOP,7,173,88,10
CONTROL "Drive input with typing:",IDC_DEMOTYPE_USER_DRIVEN,
"Button",BS_AUTOCHECKBOX | BS_LEFTTEXT | WS_TABSTOP,7,173,88,10
LTEXT "DemoType typing speed:",IDC_STATIC,7,189,215,10
LTEXT "Slow",IDC_DEMOTYPE_STATIC1,51,213,18,8
LTEXT "Fast",IDC_DEMOTYPE_STATIC2,186,213,17,8

View File

@@ -14,6 +14,7 @@ DWORD g_SnipToggleKey = ((HOTKEYF_CONTROL) << 8) | '6';
DWORD g_ShowExpiredTime = 1;
DWORD g_SliderZoomLevel = 3;
BOOLEAN g_AnimateZoom = TRUE;
BOOLEAN g_SmoothImage = TRUE;
DWORD g_PenColor = COLOR_RED;
DWORD g_BreakPenColor = COLOR_RED;
DWORD g_RootPenWidth = PEN_WIDTH;
@@ -72,6 +73,7 @@ REG_SETTING RegSettings[] = {
{ L"ShowTrayIcon", SETTING_TYPE_BOOLEAN, 0, &g_ShowTrayIcon, static_cast<DOUBLE>(g_ShowTrayIcon) },
// NOTE: AnimateZoom is misspelled, but since it is a user setting stored in the registry we must continue to misspell it.
{ L"AnimnateZoom", SETTING_TYPE_BOOLEAN, 0, &g_AnimateZoom, static_cast<DOUBLE>(g_AnimateZoom) },
{ L"SmoothImage", SETTING_TYPE_BOOLEAN, 0, &g_SmoothImage, static_cast<DOUBLE>(g_SmoothImage) },
{ L"TelescopeZoomOut", SETTING_TYPE_BOOLEAN, 0, &g_TelescopeZoomOut, static_cast<DOUBLE>(g_TelescopeZoomOut) },
{ L"SnapToGrid", SETTING_TYPE_BOOLEAN, 0, &g_SnapToGrid, static_cast<DOUBLE>(g_SnapToGrid) },
{ L"ZoominSliderLevel", SETTING_TYPE_DWORD, 0, &g_SliderZoomLevel, static_cast<DOUBLE>(g_SliderZoomLevel) },

View File

@@ -170,6 +170,8 @@ type_pMagSetFullscreenTransform pMagSetFullscreenTransform;
type_pMagSetInputTransform pMagSetInputTransform;
type_pMagShowSystemCursor pMagShowSystemCursor;
type_pMagSetWindowFilterList pMagSetWindowFilterList;
type_MagSetFullscreenUseBitmapSmoothing pMagSetFullscreenUseBitmapSmoothing;
type_pMagSetLensUseBitmapSmoothing pMagSetLensUseBitmapSmoothing;
type_pMagInitialize pMagInitialize;
type_pDwmIsCompositionEnabled pDwmIsCompositionEnabled;
type_pGetPointerType pGetPointerType;
@@ -1099,6 +1101,8 @@ void DrawHighlightedShape( DWORD Shape, HDC hdcScreenCompat, Gdiplus::Brush *pBr
// Create a new bitmap that's the size of the area covered by the line + 2 * g_PenWidth
Gdiplus::Rect lineBounds(min(x1, x2), min(y1, y2), abs(x2 - x1), abs(y2 - y1));
OutputDebug(L"DrawHighlightedShape\n");
// Expand for line drawing
if (Shape == DRAW_LINE)
lineBounds.Inflate(static_cast<int>(g_PenWidth / 2), static_cast<int>(g_PenWidth / 2));
@@ -1186,7 +1190,7 @@ void DrawHighlightedShape( DWORD Shape, HDC hdcScreenCompat, Gdiplus::Brush *pBr
DeleteDC(hdcDIBOrig);
// Invalidate the updated rectangle
// InvalidateGdiplusRect(hWnd, lineBounds);
//InvalidateGdiplusRect(hWnd, lineBounds);
}
//----------------------------------------------------------------------------
@@ -1284,7 +1288,12 @@ void ScaleImage( HDC hdcDst, float xDst, float yDst, float wDst, float hDst,
{
Gdiplus::Bitmap srcBitmap( bmSrc, NULL );
// Use high quality interpolation when smooth image is enabled
if (g_SmoothImage) {
dstGraphics.SetInterpolationMode( Gdiplus::InterpolationModeHighQuality );
} else {
dstGraphics.SetInterpolationMode( Gdiplus::InterpolationModeLowQuality );
}
dstGraphics.SetPixelOffsetMode( Gdiplus::PixelOffsetModeHalf );
dstGraphics.DrawImage( &srcBitmap, Gdiplus::RectF(xDst,yDst,wDst,hDst), xSrc, ySrc, wSrc, hSrc, Gdiplus::UnitPixel );
@@ -2071,6 +2080,8 @@ INT_PTR CALLBACK OptionsProc( HWND hDlg, UINT message,
IsAutostartConfigured() ? BST_CHECKED: BST_UNCHECKED );
CheckDlgButton( g_OptionsTabs[ZOOM_PAGE].hPage, IDC_ANIMATE_ZOOM,
g_AnimateZoom ? BST_CHECKED: BST_UNCHECKED );
CheckDlgButton( g_OptionsTabs[ZOOM_PAGE].hPage, IDC_SMOOTH_IMAGE,
g_SmoothImage ? BST_CHECKED: BST_UNCHECKED );
SendMessage( GetDlgItem(g_OptionsTabs[ZOOM_PAGE].hPage, IDC_ZOOM_SLIDER), TBM_SETRANGE, false, MAKELONG(0,_countof(g_ZoomLevels)-1) );
SendMessage( GetDlgItem(g_OptionsTabs[ZOOM_PAGE].hPage, IDC_ZOOM_SLIDER), TBM_SETPOS, true, g_SliderZoomLevel );
@@ -2210,6 +2221,7 @@ INT_PTR CALLBACK OptionsProc( HWND hDlg, UINT message,
}
g_ShowTrayIcon = IsDlgButtonChecked( hDlg, IDC_SHOW_TRAY_ICON ) == BST_CHECKED;
g_AnimateZoom = IsDlgButtonChecked( g_OptionsTabs[ZOOM_PAGE].hPage, IDC_ANIMATE_ZOOM ) == BST_CHECKED;
g_SmoothImage = IsDlgButtonChecked( g_OptionsTabs[ZOOM_PAGE].hPage, IDC_SMOOTH_IMAGE ) == BST_CHECKED;
g_DemoTypeUserDriven = IsDlgButtonChecked( g_OptionsTabs[DEMOTYPE_PAGE].hPage, IDC_DEMOTYPE_USER_DRIVEN ) == BST_CHECKED;
newToggleKey = static_cast<DWORD>(SendMessage( GetDlgItem( g_OptionsTabs[ZOOM_PAGE].hPage, IDC_HOTKEY), HKM_GETHOTKEY, 0, 0 ));
@@ -2723,7 +2735,6 @@ VOID DrawShape( DWORD Shape, HDC hDc, RECT *Rect, bool UseGdiPlus = false )
bool isBlur = false;
Gdiplus::Graphics dstGraphics(hDc);
if( ( GetWindowLong( g_hWndMain, GWL_EXSTYLE ) & WS_EX_LAYERED ) == 0 )
{
dstGraphics.SetSmoothingMode(Gdiplus::SmoothingModeAntiAlias);
@@ -2746,6 +2757,7 @@ VOID DrawShape( DWORD Shape, HDC hDc, RECT *Rect, bool UseGdiPlus = false )
InflateRect(Rect, g_PenWidth / 2, g_PenWidth / 2);
isBlur = true;
}
OutputDebug(L"Draw shape: highlight: %d pbrush: %d\n", PEN_COLOR_HIGHLIGHT(g_PenColor), pBrush != NULL);
switch (Shape) {
case DRAW_RECTANGLE:
@@ -2920,7 +2932,7 @@ void InvalidateCursorMoveArea( HWND hWnd, float zoomLevel, int width, int height
{
int x, y;
RECT rc;
int invWidth = g_PenWidth;
int invWidth = g_PenWidth + CURSOR_SAVE_MARGIN;
if( DrawHighlightedCursor( zoomLevel, width, height ) ) {
@@ -2945,7 +2957,7 @@ void InvalidateCursorMoveArea( HWND hWnd, float zoomLevel, int width, int height
void SaveCursorArea( HDC hDcTarget, HDC hDcSource, POINT pt )
{
OutputDebug( L"SaveCursorArea\n");
int penWidth = g_PenWidth + 2;
int penWidth = g_PenWidth + CURSOR_SAVE_MARGIN;
BitBlt( hDcTarget, 0, 0, penWidth +CURSOR_ARM_LENGTH*2, penWidth +CURSOR_ARM_LENGTH*2,
hDcSource, static_cast<INT> (pt.x- penWidth /2)-CURSOR_ARM_LENGTH,
static_cast<INT>(pt.y- penWidth /2)-CURSOR_ARM_LENGTH, SRCCOPY|CAPTUREBLT );
@@ -2959,7 +2971,7 @@ void SaveCursorArea( HDC hDcTarget, HDC hDcSource, POINT pt )
void RestoreCursorArea( HDC hDcTarget, HDC hDcSource, POINT pt )
{
OutputDebug( L"RestoreCursorArea\n");
int penWidth = g_PenWidth + 2;
int penWidth = g_PenWidth + CURSOR_SAVE_MARGIN;
BitBlt( hDcTarget, static_cast<INT>(pt.x- penWidth /2)-CURSOR_ARM_LENGTH,
static_cast<INT>(pt.y- penWidth /2)-CURSOR_ARM_LENGTH, penWidth +CURSOR_ARM_LENGTH*2,
penWidth + CURSOR_ARM_LENGTH*2, hDcSource, 0, 0, SRCCOPY|CAPTUREBLT );
@@ -4178,6 +4190,11 @@ LRESULT APIENTRY MainWndProc(
}
#endif
}
OutputDebug(L"LIVEDRAW SMOOTHING: %d\n", g_SmoothImage);
if (!pMagSetLensUseBitmapSmoothing(g_hWndLiveZoomMag, g_SmoothImage))
{
OutputDebug(L"MagSetLensUseBitmapSmoothing failed: %d\n", GetLastError());
}
if ( g_RecordToggle )
{
@@ -5296,6 +5313,8 @@ LRESULT APIENTRY MainWndProc(
if( g_Drawing ) {
OutputDebug(L"Mousemove: Drawing\n");
POINT currentPt;
// Are we in pen mode on a tablet?
@@ -5334,7 +5353,15 @@ LRESULT APIENTRY MainWndProc(
}
else
{
DrawShape( g_DrawingShape, hdcScreenCompat, &g_rcRectangle );
if (PEN_COLOR_HIGHLIGHT(g_PenColor))
{
// copy original bitmap to screen bitmap to erase previous highlight
BitBlt(hdcScreenCompat, 0, 0, bmp.bmWidth, bmp.bmHeight, drawUndoList->hDc, 0, 0, SRCCOPY | CAPTUREBLT);
}
else
{
DrawShape(g_DrawingShape, hdcScreenCompat, &g_rcRectangle, PEN_COLOR_HIGHLIGHT(g_PenColor));
}
}
}
@@ -5380,7 +5407,7 @@ LRESULT APIENTRY MainWndProc(
g_rcRectangle.top != g_rcRectangle.bottom) {
// Draw the new target rectangle.
DrawShape(g_DrawingShape, hdcScreenCompat, &g_rcRectangle);
DrawShape(g_DrawingShape, hdcScreenCompat, &g_rcRectangle, PEN_COLOR_HIGHLIGHT(g_PenColor));
OutputDebug(L"SHAPE: (%d, %d) - (%d, %d)\n", g_rcRectangle.left, g_rcRectangle.top,
g_rcRectangle.right, g_rcRectangle.bottom);
}
@@ -5418,9 +5445,6 @@ LRESULT APIENTRY MainWndProc(
Gdiplus::BitmapData* lineData = LockGdiPlusBitmap(lineBitmap);
BYTE* pPixels = static_cast<BYTE*>(lineData->Scan0);
// Copy the contents of the screen bitmap to the temporary bitmap
GetOldestUndo(drawUndoList);
// Create a GDI bitmap that's the size of the lineBounds rectangle
Gdiplus::Bitmap *blurBitmap = CreateGdiplusBitmap( hdcScreenCompat, // oldestUndo->hDc,
lineBounds.X, lineBounds.Y, lineBounds.Width, lineBounds.Height);
@@ -5445,6 +5469,8 @@ LRESULT APIENTRY MainWndProc(
}
else if(PEN_COLOR_HIGHLIGHT(g_PenColor)) {
OutputDebug(L"HIGHLIGHT\n");
// This is a highlighting pen color
Gdiplus::Rect lineBounds = GetLineBounds(prevPt, currentPt, g_PenWidth);
Gdiplus::Bitmap* lineBitmap = DrawBitmapLine(lineBounds, prevPt, currentPt, &pen);
@@ -5784,7 +5810,10 @@ LRESULT APIENTRY MainWndProc(
if( !g_DrawingShape ) {
// If the point has changed, draw a line to it
if (prevPt.x != LOWORD(lParam) || prevPt.y != HIWORD(lParam)) {
if (!PEN_COLOR_HIGHLIGHT(g_PenColor))
{
if (prevPt.x != LOWORD(lParam) || prevPt.y != HIWORD(lParam))
{
Gdiplus::Graphics dstGraphics(hdcScreenCompat);
if ((GetWindowLong(g_hWndMain, GWL_EXSTYLE) & WS_EX_LAYERED) == 0)
{
@@ -5798,12 +5827,13 @@ LRESULT APIENTRY MainWndProc(
dstGraphics.DrawPath(&pen, &path);
}
// Draw a dot at the current point, if the point hasn't changed
else {
else
{
MoveToEx(hdcScreenCompat, prevPt.x, prevPt.y, NULL);
LineTo(hdcScreenCompat, LOWORD(lParam), HIWORD(lParam));
InvalidateRect(hWnd, NULL, FALSE);
}
}
prevPt.x = LOWORD( lParam );
prevPt.y = HIWORD( lParam );
@@ -5818,8 +5848,11 @@ LRESULT APIENTRY MainWndProc(
g_rcRectangle.left != g_rcRectangle.right ) {
// erase previous
if (!PEN_COLOR_HIGHLIGHT(g_PenColor))
{
SetROP2(hdcScreenCompat, R2_NOTXORPEN);
DrawShape( g_DrawingShape, hdcScreenCompat, &g_rcRectangle );
DrawShape(g_DrawingShape, hdcScreenCompat, &g_rcRectangle);
}
// Draw the final shape
HBRUSH hBrush = static_cast<HBRUSH>(GetStockObject( NULL_BRUSH ));
@@ -6185,8 +6218,14 @@ LRESULT APIENTRY MainWndProc(
SetStretchBltMode( hInterimSaveDc, HALFTONE );
SetStretchBltMode( hSaveDc, HALFTONE );
#else
// Use HALFTONE for better quality when smooth image is enabled
if (g_SmoothImage) {
SetStretchBltMode( hInterimSaveDc, HALFTONE );
SetStretchBltMode( hSaveDc, HALFTONE );
} else {
SetStretchBltMode( hInterimSaveDc, COLORONCOLOR );
SetStretchBltMode( hSaveDc, COLORONCOLOR );
}
#endif
StretchBlt( hInterimSaveDc,
0, 0,
@@ -6309,7 +6348,12 @@ LRESULT APIENTRY MainWndProc(
#if SCALE_HALFTONE
SetStretchBltMode( hSaveDc, HALFTONE );
#else
// Use HALFTONE for better quality when smooth image is enabled
if (g_SmoothImage) {
SetStretchBltMode( hSaveDc, HALFTONE );
} else {
SetStretchBltMode( hSaveDc, COLORONCOLOR );
}
#endif
StretchBlt( hSaveDc,
0, 0,
@@ -6646,8 +6690,8 @@ LRESULT APIENTRY MainWndProc(
(float)x, (float)y,
width/zoomLevel, height/zoomLevel );
} else {
// do a fast, less accurate render
SetStretchBltMode( hDc, HALFTONE );
// do a fast, less accurate render (but use smooth if enabled)
SetStretchBltMode( hDc, g_SmoothImage ? HALFTONE : COLORONCOLOR );
StretchBlt( ps.hdc,
0, 0,
bmp.bmWidth, bmp.bmHeight,
@@ -6660,7 +6704,12 @@ LRESULT APIENTRY MainWndProc(
#if SCALE_HALFTONE
SetStretchBltMode( hDc, zoomLevel == zoomTelescopeTarget ? HALFTONE : COLORONCOLOR );
#else
// Use HALFTONE for better quality when smooth image is enabled
if (g_SmoothImage) {
SetStretchBltMode( hDc, HALFTONE );
} else {
SetStretchBltMode( hDc, COLORONCOLOR );
}
#endif
StretchBlt( ps.hdc,
0, 0,
@@ -6683,7 +6732,7 @@ LRESULT APIENTRY MainWndProc(
BITMAP local_bmp;
GetObject(g_hBackgroundBmp, sizeof(local_bmp), &local_bmp);
SetStretchBltMode( hdcScreenCompat, HALFTONE );
SetStretchBltMode( hdcScreenCompat, g_SmoothImage ? HALFTONE : COLORONCOLOR );
if( g_BreakBackgroundStretch ) {
StretchBlt( hdcScreenCompat, 0, 0, width, height,
g_hDcBackgroundFile, 0, 0, local_bmp.bmWidth, local_bmp.bmHeight, SRCCOPY|CAPTUREBLT );
@@ -6842,7 +6891,6 @@ LRESULT CALLBACK LiveZoomWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM
WS_CHILD | MS_SHOWMAGNIFIEDCURSOR | WS_VISIBLE,
0, 0, 0, 0, hWnd, NULL, g_hInstance, NULL );
}
ShowWindow( hWnd, SW_SHOW );
InvalidateRect( g_hWndLiveZoomMag, NULL, TRUE );
@@ -7555,6 +7603,10 @@ int APIENTRY wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance
"MagSetWindowTransform" );
pMagSetFullscreenTransform = (type_pMagSetFullscreenTransform)GetProcAddress(LoadLibrarySafe(L"magnification.dll", DLL_LOAD_LOCATION_SYSTEM),
"MagSetFullscreenTransform");
pMagSetFullscreenUseBitmapSmoothing = (type_MagSetFullscreenUseBitmapSmoothing)GetProcAddress(LoadLibrarySafe(L"magnification.dll", DLL_LOAD_LOCATION_SYSTEM),
"MagSetFullscreenUseBitmapSmoothing");
pMagSetLensUseBitmapSmoothing = (type_pMagSetLensUseBitmapSmoothing)GetProcAddress(LoadLibrarySafe(L"magnification.dll", DLL_LOAD_LOCATION_SYSTEM),
"MagSetLensUseBitmapSmoothing");
pMagSetInputTransform = (type_pMagSetInputTransform)GetProcAddress(LoadLibrarySafe(L"magnification.dll", DLL_LOAD_LOCATION_SYSTEM),
"MagSetInputTransform");
pMagShowSystemCursor = (type_pMagShowSystemCursor)GetProcAddress(LoadLibrarySafe(L"magnification.dll", DLL_LOAD_LOCATION_SYSTEM),

View File

@@ -95,6 +95,7 @@
#define IDC_COPYRIGHT 1075
#define IDC_PEN_WIDTH 1105
#define IDC_TIMER 1106
#define IDC_SMOOTH_IMAGE 1107
#define IDC_SAVE 40002
#define IDC_COPY 40004
#define IDC_RECORD 40006
@@ -109,7 +110,7 @@
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 118
#define _APS_NEXT_COMMAND_VALUE 40013
#define _APS_NEXT_CONTROL_VALUE 1076
#define _APS_NEXT_CONTROL_VALUE 1078
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif

View File

@@ -81,6 +81,8 @@ namespace Microsoft.PowerToys.Settings.UI.Library
[JsonPropertyName("AnimnateZoom")]
public BoolProperty AnimateZoom { get; set; }
public BoolProperty SmoothImage { get; set; }
public IntProperty ZoominSliderLevel { get; set; }
public IntProperty RecordScaling { get; set; }

View File

@@ -54,6 +54,9 @@
<tkcontrols:SettingsCard Name="ZoomItToggleAnimateZoom" x:Uid="ZoomIt_Toggle_AnimateZoom">
<ToggleSwitch x:Uid="ToggleSwitch" IsOn="{x:Bind ViewModel.AnimateZoom, Mode=TwoWay}" />
</tkcontrols:SettingsCard>
<tkcontrols:SettingsCard Name="ZoomItSmoothZoomedImage" x:Uid="ZoomIt_Toggle_SmoothZoomedImage">
<ToggleSwitch x:Uid="ToggleSwitch" IsOn="{x:Bind ViewModel.SmoothImage, Mode=TwoWay}" />
</tkcontrols:SettingsCard>
<tkcontrols:SettingsCard Name="ZoomItSliderInitialMagnification" x:Uid="ZoomIt_Slider_InitialMagnification">
<Slider
MinWidth="{StaticResource SettingActionControlMinWidth}"

View File

@@ -4662,6 +4662,9 @@ Copy a zoomed screen with Ctrl+C or save it by typing Ctrl+S. Crop the copy or s
<data name="ZoomIt_Toggle_AnimateZoom.Header" xml:space="preserve">
<value>Animate zoom in and zoom out</value>
</data>
<data name="ZoomIt_Toggle_SmoothZoomedImage.Header" xml:space="preserve">
<value>Smooth zoomed image</value>
</data>
<data name="ZoomIt_Slider_InitialMagnification.Header" xml:space="preserve">
<value>Specify the initial level of magnification when zooming in</value>
</data>

View File

@@ -197,6 +197,20 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
}
}
public bool SmoothImage
{
get => _zoomItSettings.Properties.SmoothImage.Value;
set
{
if (_zoomItSettings.Properties.SmoothImage.Value != value)
{
_zoomItSettings.Properties.SmoothImage.Value = value;
OnPropertyChanged(nameof(SmoothImage));
NotifySettingsChanged();
}
}
}
public int ZoominSliderLevel
{
get => _zoomItSettings.Properties.ZoominSliderLevel.Value;