[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:
Michael Clayton
2024-10-21 17:38:07 +01:00
committed by GitHub
parent db3c8e621e
commit dc7c7ef2b7
87 changed files with 281 additions and 308 deletions

View File

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

View File

@@ -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);
}

View File

@@ -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);
}
}