From c2bcf9b897f288830e9a1375f71d929b6c23ca5b Mon Sep 17 00:00:00 2001 From: Jaex Date: Sat, 29 Dec 2018 16:32:09 +0300 Subject: [PATCH] CursorData refactoring --- ShareX.HelpersLib/CursorData.cs | 62 ++++++++++--------- ShareX.HelpersLib/Native/NativeStructs.cs | 55 +++++++++++++--- ShareX.ScreenCaptureLib/Screenshot.cs | 8 +-- .../Screenshot_Transparent.cs | 6 +- ShareX/CaptureHelpers/CaptureRegion.cs | 5 +- 5 files changed, 84 insertions(+), 52 deletions(-) diff --git a/ShareX.HelpersLib/CursorData.cs b/ShareX.HelpersLib/CursorData.cs index 0435375a0..2bb3f4097 100644 --- a/ShareX.HelpersLib/CursorData.cs +++ b/ShareX.HelpersLib/CursorData.cs @@ -29,13 +29,11 @@ namespace ShareX.HelpersLib { - public class CursorData : IDisposable + public class CursorData { public IntPtr Handle { get; private set; } - public bool IsVisible { get; private set; } public Point Position { get; private set; } - - public bool IsValid => Handle != IntPtr.Zero && IsVisible; + public bool IsVisible { get; private set; } public CursorData() { @@ -44,32 +42,43 @@ public CursorData() public void UpdateCursorData() { + Handle = IntPtr.Zero; + Position = Point.Empty; + IsVisible = false; + CursorInfo cursorInfo = new CursorInfo(); cursorInfo.cbSize = Marshal.SizeOf(cursorInfo); if (NativeMethods.GetCursorInfo(out cursorInfo)) { + Handle = cursorInfo.hCursor; + Position = cursorInfo.ptScreenPos; IsVisible = cursorInfo.flags == NativeConstants.CURSOR_SHOWING; if (IsVisible) { - Handle = NativeMethods.CopyIcon(cursorInfo.hCursor); - IconInfo iconInfo; + IntPtr iconHandle = NativeMethods.CopyIcon(Handle); - if (NativeMethods.GetIconInfo(Handle, out iconInfo)) + if (iconHandle != IntPtr.Zero) { - Point cursorPosition = CaptureHelpers.GetZeroBasedMousePosition(); - Position = new Point(cursorPosition.X - iconInfo.xHotspot, cursorPosition.Y - iconInfo.yHotspot); + IconInfo iconInfo; - if (iconInfo.hbmMask != IntPtr.Zero) + if (NativeMethods.GetIconInfo(iconHandle, out iconInfo)) { - NativeMethods.DeleteObject(iconInfo.hbmMask); + Position = new Point(Position.X - iconInfo.xHotspot, Position.Y - iconInfo.yHotspot); + + if (iconInfo.hbmMask != IntPtr.Zero) + { + NativeMethods.DeleteObject(iconInfo.hbmMask); + } + + if (iconInfo.hbmColor != IntPtr.Zero) + { + NativeMethods.DeleteObject(iconInfo.hbmColor); + } } - if (iconInfo.hbmColor != IntPtr.Zero) - { - NativeMethods.DeleteObject(iconInfo.hbmColor); - } + NativeMethods.DestroyIcon(iconHandle); } } } @@ -80,11 +89,12 @@ public void DrawCursor(Image img) DrawCursor(img, Point.Empty); } - public void DrawCursor(Image img, Point cursorOffset) + public void DrawCursor(Image img, Point offset) { - if (IsValid) + if (IsVisible) { - Point drawPosition = new Point(Position.X - cursorOffset.X, Position.Y - cursorOffset.Y); + Point drawPosition = new Point(Position.X - offset.X, Position.Y - offset.Y); + drawPosition = CaptureHelpers.ScreenToClient(drawPosition); using (Graphics g = Graphics.FromImage(img)) using (Icon icon = Icon.FromHandle(Handle)) @@ -99,23 +109,15 @@ public void DrawCursor(IntPtr hdcDest) DrawCursor(hdcDest, Point.Empty); } - public void DrawCursor(IntPtr hdcDest, Point cursorOffset) + public void DrawCursor(IntPtr hdcDest, Point offset) { - if (IsValid) + if (IsVisible) { - Point drawPosition = new Point(Position.X - cursorOffset.X, Position.Y - cursorOffset.Y); + Point drawPosition = new Point(Position.X - offset.X, Position.Y - offset.Y); + drawPosition = CaptureHelpers.ScreenToClient(drawPosition); NativeMethods.DrawIconEx(hdcDest, drawPosition.X, drawPosition.Y, Handle, 0, 0, 0, IntPtr.Zero, NativeConstants.DI_NORMAL); } } - - public void Dispose() - { - if (Handle != IntPtr.Zero) - { - NativeMethods.DestroyIcon(Handle); - Handle = IntPtr.Zero; - } - } } } \ No newline at end of file diff --git a/ShareX.HelpersLib/Native/NativeStructs.cs b/ShareX.HelpersLib/Native/NativeStructs.cs index 9a5021ed2..7c0fd901d 100644 --- a/ShareX.HelpersLib/Native/NativeStructs.cs +++ b/ShareX.HelpersLib/Native/NativeStructs.cs @@ -316,20 +316,57 @@ public struct DWM_THUMBNAIL_PROPERTIES [StructLayout(LayoutKind.Sequential)] public struct CursorInfo { - public int cbSize; // Specifies the size, in bytes, of the structure. - public int flags; // Specifies the cursor state. This parameter can be one of the following values: - public IntPtr hCursor; // Handle to the cursor. - public Point ptScreenPos; // A POINT structure that receives the screen coordinates of the cursor. + /// + /// The size of the structure, in bytes. The caller must set this to sizeof(CURSORINFO). + /// + public int cbSize; + + /// + /// The cursor state. This parameter can be one of the following values: + /// 0 (The cursor is hidden.) + /// CURSOR_SHOWING 0x00000001 (The cursor is showing.) + /// CURSOR_SUPPRESSED 0x00000002 (Windows 8: The cursor is suppressed.This flag indicates that the system is not drawing the cursor because the user is providing input through touch or pen instead of the mouse.) + /// + public int flags; + + /// + /// A handle to the cursor. + /// + public IntPtr hCursor; + + /// + /// A structure that receives the screen coordinates of the cursor. + /// + public Point ptScreenPos; } [StructLayout(LayoutKind.Sequential)] public struct IconInfo { - public bool fIcon; // Specifies whether this structure defines an icon or a cursor. A value of TRUE specifies - public int xHotspot; // Specifies the x-coordinate of a cursor's hot spot. If this structure defines an icon, the hot - public int yHotspot; // Specifies the y-coordinate of the cursor's hot spot. If this structure defines an icon, the hot - public IntPtr hbmMask; // (HBITMAP) Specifies the icon bitmask bitmap. If this structure defines a black and white icon, - public IntPtr hbmColor; // (HBITMAP) Handle to the icon color bitmap. This member can be optional if this + /// + /// Specifies whether this structure defines an icon or a cursor. A value of TRUE specifies an icon; FALSE specifies a cursor. + /// + public bool fIcon; + + /// + /// The x-coordinate of a cursor's hot spot. If this structure defines an icon, the hot spot is always in the center of the icon, and this member is ignored. + /// + public int xHotspot; + + /// + /// The y-coordinate of the cursor's hot spot. If this structure defines an icon, the hot spot is always in the center of the icon, and this member is ignored. + /// + public int yHotspot; + + /// + /// The icon bitmask bitmap. If this structure defines a black and white icon, this bitmask is formatted so that the upper half is the icon AND bitmask and the lower half is the icon XOR bitmask. Under this condition, the height should be an even multiple of two. If this structure defines a color icon, this mask only defines the AND bitmask of the icon. + /// + public IntPtr hbmMask; + + /// + /// A handle to the icon color bitmap. This member can be optional if this structure defines a black and white icon. The AND bitmask of hbmMask is applied with the SRCAND flag to the destination; subsequently, the color bitmap is applied (using XOR) to the destination by using the SRCINVERT flag. + /// + public IntPtr hbmColor; } /// diff --git a/ShareX.ScreenCaptureLib/Screenshot.cs b/ShareX.ScreenCaptureLib/Screenshot.cs index ece36fc71..09ca4fecb 100644 --- a/ShareX.ScreenCaptureLib/Screenshot.cs +++ b/ShareX.ScreenCaptureLib/Screenshot.cs @@ -129,14 +129,10 @@ private Image CaptureRectangleNative(IntPtr handle, Rectangle rect, bool capture if (captureCursor) { - Point cursorOffset = CaptureHelpers.ScreenToClient(rect.Location); - try { - using (CursorData cursorData = new CursorData()) - { - cursorData.DrawCursor(hdcDest, cursorOffset); - } + CursorData cursorData = new CursorData(); + cursorData.DrawCursor(hdcDest, rect.Location); } catch (Exception e) { diff --git a/ShareX.ScreenCaptureLib/Screenshot_Transparent.cs b/ShareX.ScreenCaptureLib/Screenshot_Transparent.cs index 539b23889..c11495695 100644 --- a/ShareX.ScreenCaptureLib/Screenshot_Transparent.cs +++ b/ShareX.ScreenCaptureLib/Screenshot_Transparent.cs @@ -119,10 +119,9 @@ public Image CaptureWindowTransparent(IntPtr handle) transparentImage = whiteBackground2; } - if (cursorData != null && cursorData.IsValid) + if (cursorData != null) { - Point cursorOffset = CaptureHelpers.ScreenToClient(rect.Location); - cursorData.DrawCursor(transparentImage, cursorOffset); + cursorData.DrawCursor(transparentImage, rect.Location); } if (isTransparent) @@ -147,7 +146,6 @@ public Image CaptureWindowTransparent(IntPtr handle) if (whiteBackground != null) whiteBackground.Dispose(); if (blackBackground != null) blackBackground.Dispose(); if (isTransparent && whiteBackground2 != null) whiteBackground2.Dispose(); - if (cursorData != null) cursorData.Dispose(); } } diff --git a/ShareX/CaptureHelpers/CaptureRegion.cs b/ShareX/CaptureHelpers/CaptureRegion.cs index 5069f3971..6bbf7b951 100644 --- a/ShareX/CaptureHelpers/CaptureRegion.cs +++ b/ShareX/CaptureHelpers/CaptureRegion.cs @@ -87,10 +87,9 @@ protected ImageInfo ExecuteRegionCapture(TaskSettings taskSettings) using (RegionCaptureForm form = new RegionCaptureForm(mode, taskSettings.CaptureSettingsReference.SurfaceOptions, img)) { - if (cursorData != null && cursorData.IsValid) + if (cursorData != null && cursorData.IsVisible) { - form.AddCursor(cursorData.Handle, cursorData.Position); - cursorData.Dispose(); + form.AddCursor(cursorData.Handle, CaptureHelpers.ScreenToClient(cursorData.Position)); } form.ShowDialog();