CursorData refactoring

This commit is contained in:
Jaex 2018-12-29 16:32:09 +03:00
parent 8c4b4d5c1e
commit c2bcf9b897
5 changed files with 84 additions and 52 deletions

View file

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

View file

@ -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.
/// <summary>
/// The size of the structure, in bytes. The caller must set this to sizeof(CURSORINFO).
/// </summary>
public int cbSize;
/// <summary>
/// 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.)
/// </summary>
public int flags;
/// <summary>
/// A handle to the cursor.
/// </summary>
public IntPtr hCursor;
/// <summary>
/// A structure that receives the screen coordinates of the cursor.
/// </summary>
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
/// <summary>
/// Specifies whether this structure defines an icon or a cursor. A value of TRUE specifies an icon; FALSE specifies a cursor.
/// </summary>
public bool fIcon;
/// <summary>
/// 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.
/// </summary>
public int xHotspot;
/// <summary>
/// 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.
/// </summary>
public int yHotspot;
/// <summary>
/// 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.
/// </summary>
public IntPtr hbmMask;
/// <summary>
/// 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.
/// </summary>
public IntPtr hbmColor;
}
/// <summary>

View file

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

View file

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

View file

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