mirror of
https://github.com/microsoft/PowerToys.git
synced 2026-04-04 18:26:39 +02:00
[MouseJump][CQ]Refactor "common" classes into a separate project (#34333)
* [Mouse Jump] - moving common code to MouseJump.Common project - #25482 * [Mouse Jump] - fixing warnings in MouseJump.Common - #25482 * [MouseJump] - cherrypick 5653b4 - Exclude MouseJump Common tests from the checks # Conflicts: # src/modules/MouseUtils/MouseJump.Common.UnitTests/MouseJump.Common.UnitTests.csproj * [mOuSEjUMP] - cherry pick 61aab9 - Fix ci build issues # Conflicts: # src/modules/MouseUtils/MouseJump.Common.UnitTests/MouseJump.Common.UnitTests.csproj * [Mouse Jump] - remove project type guids - #25482 * [Mouse Jump] - simplify mousejump *.csproj files - #25482 * [Mouse Jump] - fixing broken tests - #25482 * [Mouse Jump] - fixing broken build - #25482 * [Mouse Jump] - editing MouseJump.Common.UnitTests.csproj - #25482 * [Mouse Jump] - editing MouseJump.Common.csproj (UseWindowsForms=true) - #25482 * [Mouse Jump] - fixing spellcheck - #25482 * [MouseJump] - enabled implicit usings - #25482 * [Mouse Jump] - re-add csproj attributes - #27511 * ci: Fix signing of Common dll --------- Co-authored-by: Clayton <mike.clayton@delinian.com>
This commit is contained in:
@@ -0,0 +1,122 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System.Diagnostics;
|
||||
|
||||
using MouseJump.Common.Models.Drawing;
|
||||
using MouseJump.Common.NativeMethods;
|
||||
using static MouseJump.Common.NativeMethods.Core;
|
||||
|
||||
namespace MouseJump.Common.Imaging;
|
||||
|
||||
/// <summary>
|
||||
/// Implements an IImageRegionCopyService that uses the current desktop window as the copy source.
|
||||
/// This is used during the main application runtime to generate preview images of the desktop.
|
||||
/// </summary>
|
||||
public sealed class DesktopImageRegionCopyService : IImageRegionCopyService
|
||||
{
|
||||
/// <summary>
|
||||
/// Copies the source region from the current desktop window
|
||||
/// to the target region on the specified Graphics object.
|
||||
/// </summary>
|
||||
public void CopyImageRegion(
|
||||
Graphics targetGraphics,
|
||||
RectangleInfo sourceBounds,
|
||||
RectangleInfo targetBounds)
|
||||
{
|
||||
var stopwatch = Stopwatch.StartNew();
|
||||
var (desktopHwnd, desktopHdc) = DesktopImageRegionCopyService.GetDesktopDeviceContext();
|
||||
var previewHdc = DesktopImageRegionCopyService.GetGraphicsDeviceContext(
|
||||
targetGraphics, Gdi32.STRETCH_BLT_MODE.STRETCH_HALFTONE);
|
||||
stopwatch.Stop();
|
||||
|
||||
var source = sourceBounds.ToRectangle();
|
||||
var target = targetBounds.ToRectangle();
|
||||
var result = Gdi32.StretchBlt(
|
||||
previewHdc,
|
||||
target.X,
|
||||
target.Y,
|
||||
target.Width,
|
||||
target.Height,
|
||||
desktopHdc,
|
||||
source.X,
|
||||
source.Y,
|
||||
source.Width,
|
||||
source.Height,
|
||||
Gdi32.ROP_CODE.SRCCOPY);
|
||||
if (!result)
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
$"{nameof(Gdi32.StretchBlt)} returned {result.Value}");
|
||||
}
|
||||
|
||||
// we need to release the graphics device context handle before anything
|
||||
// else tries to use the Graphics object otherwise it'll give an error
|
||||
// from GDI saying "Object is currently in use elsewhere"
|
||||
DesktopImageRegionCopyService.FreeGraphicsDeviceContext(targetGraphics, ref previewHdc);
|
||||
|
||||
DesktopImageRegionCopyService.FreeDesktopDeviceContext(ref desktopHwnd, ref desktopHdc);
|
||||
}
|
||||
|
||||
private static (HWND DesktopHwnd, HDC DesktopHdc) GetDesktopDeviceContext()
|
||||
{
|
||||
var desktopHwnd = User32.GetDesktopWindow();
|
||||
var desktopHdc = User32.GetWindowDC(desktopHwnd);
|
||||
if (desktopHdc.IsNull)
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
$"{nameof(User32.GetWindowDC)} returned null");
|
||||
}
|
||||
|
||||
return (desktopHwnd, desktopHdc);
|
||||
}
|
||||
|
||||
private static void FreeDesktopDeviceContext(ref HWND desktopHwnd, ref HDC desktopHdc)
|
||||
{
|
||||
if (!desktopHwnd.IsNull && !desktopHdc.IsNull)
|
||||
{
|
||||
var result = User32.ReleaseDC(desktopHwnd, desktopHdc);
|
||||
if (result == 0)
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
$"{nameof(User32.ReleaseDC)} returned {result}");
|
||||
}
|
||||
}
|
||||
|
||||
desktopHwnd = HWND.Null;
|
||||
desktopHdc = HDC.Null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if the target device context handle exists, and creates a new one from the
|
||||
/// specified Graphics object if not.
|
||||
/// </summary>
|
||||
private static HDC GetGraphicsDeviceContext(Graphics graphics, Gdi32.STRETCH_BLT_MODE mode)
|
||||
{
|
||||
var graphicsHdc = (HDC)graphics.GetHdc();
|
||||
|
||||
var result = Gdi32.SetStretchBltMode(graphicsHdc, mode);
|
||||
if (result == 0)
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
$"{nameof(Gdi32.SetStretchBltMode)} returned {result}");
|
||||
}
|
||||
|
||||
return graphicsHdc;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Free the specified device context handle if it exists.
|
||||
/// </summary>
|
||||
private static void FreeGraphicsDeviceContext(Graphics graphics, ref HDC graphicsHdc)
|
||||
{
|
||||
if (graphicsHdc.IsNull)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
graphics.ReleaseHdc(graphicsHdc.Value);
|
||||
graphicsHdc = HDC.Null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using MouseJump.Common.Models.Drawing;
|
||||
|
||||
namespace MouseJump.Common.Imaging;
|
||||
|
||||
public interface IImageRegionCopyService
|
||||
{
|
||||
/// <summary>
|
||||
/// Copies the source region from the provider's source image (e.g. the interactive desktop,
|
||||
/// a static image, etc) to the target region on the specified Graphics object.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Implementations of this interface are used to capture regions of the interactive desktop
|
||||
/// during runtime, or to capture regions of a static reference image during unit tests.
|
||||
/// </remarks>
|
||||
void CopyImageRegion(
|
||||
Graphics targetGraphics,
|
||||
RectangleInfo sourceBounds,
|
||||
RectangleInfo targetBounds);
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using MouseJump.Common.Models.Drawing;
|
||||
|
||||
namespace MouseJump.Common.Imaging;
|
||||
|
||||
/// <summary>
|
||||
/// Implements an IImageRegionCopyService that uses the specified image as the copy source.
|
||||
/// This is used for testing the DrawingHelper rather than as part of the main application.
|
||||
/// </summary>
|
||||
public sealed class StaticImageRegionCopyService : IImageRegionCopyService
|
||||
{
|
||||
public StaticImageRegionCopyService(Image sourceImage)
|
||||
{
|
||||
this.SourceImage = sourceImage ?? throw new ArgumentNullException(nameof(sourceImage));
|
||||
}
|
||||
|
||||
private Image SourceImage
|
||||
{
|
||||
get;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Copies the source region from the static source image
|
||||
/// to the target region on the specified Graphics object.
|
||||
/// </summary>
|
||||
public void CopyImageRegion(
|
||||
Graphics targetGraphics,
|
||||
RectangleInfo sourceBounds,
|
||||
RectangleInfo targetBounds)
|
||||
{
|
||||
targetGraphics.DrawImage(
|
||||
image: this.SourceImage,
|
||||
destRect: targetBounds.ToRectangle(),
|
||||
srcRect: sourceBounds.ToRectangle(),
|
||||
srcUnit: GraphicsUnit.Pixel);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user