using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Runtime.InteropServices; using System.Text; using System.Threading.Tasks; namespace Tango.ScreenCapture { public static class CursorUtils { #region INTERNALS internal static class User32 { public const Int32 CURSOR_SHOWING = 0x00000001; [StructLayout(LayoutKind.Sequential)] public struct ICONINFO { public bool fIcon; public Int32 xHotspot; public Int32 yHotspot; public IntPtr hbmMask; public IntPtr hbmColor; } [StructLayout(LayoutKind.Sequential)] public struct POINT { public Int32 x; public Int32 y; } [StructLayout(LayoutKind.Sequential)] public struct CURSORINFO { public Int32 cbSize; public Int32 flags; public IntPtr hCursor; public POINT ptScreenPos; } [DllImport("user32.dll")] public static extern bool GetCursorInfo(out CURSORINFO pci); [DllImport("user32.dll")] public static extern IntPtr CopyIcon(IntPtr hIcon); [DllImport("user32.dll", SetLastError = true)] public static extern bool DestroyIcon(IntPtr hIcon); [DllImport("user32.dll", SetLastError = true)] public static extern bool DrawIconEx(IntPtr hdc, int xLeft, int yTop, IntPtr hIcon, int cxWidth, int cyHeight, int istepIfAniCur, IntPtr hbrFlickerFreeDraw, int diFlags); [DllImport("user32.dll")] public static extern bool DrawIcon(IntPtr hdc, int x, int y, IntPtr hIcon); [DllImport("user32.dll")] public static extern bool GetIconInfo(IntPtr hIcon, out ICONINFO piconinfo); } #endregion #region Internal Classes [StructLayout(LayoutKind.Sequential)] struct CURSORINFO { public Int32 cbSize; public Int32 flags; public IntPtr hCursor; public POINTAPI ptScreenPos; } [StructLayout(LayoutKind.Sequential)] struct POINTAPI { public int x; public int y; } [DllImport("user32.dll")] static extern bool GetCursorInfo(out CURSORINFO pci); [DllImport("user32.dll")] static extern bool DrawIcon(IntPtr hDC, int X, int Y, IntPtr hIcon); const Int32 CURSOR_SHOWING = 0x00000001; internal struct SIZE { public int cx; public int cy; } internal class GDIStuff { #region Class Variables public const int SRCCOPY = 13369376; #endregion #region Class Functions [DllImport("gdi32.dll", EntryPoint = "CreateDC")] public static extern IntPtr CreateDC(IntPtr lpszDriver, string lpszDevice, IntPtr lpszOutput, IntPtr lpInitData); [DllImport("gdi32.dll", EntryPoint = "DeleteDC")] public static extern IntPtr DeleteDC(IntPtr hDc); [DllImport("gdi32.dll", EntryPoint = "DeleteObject")] public static extern IntPtr DeleteObject(IntPtr hDc); [DllImport("gdi32.dll", EntryPoint = "BitBlt")] public static extern bool BitBlt(IntPtr hdcDest, int xDest, int yDest, int wDest, int hDest, IntPtr hdcSource, int xSrc, int ySrc, int RasterOp); [DllImport("gdi32.dll", EntryPoint = "CreateCompatibleBitmap")] public static extern IntPtr CreateCompatibleBitmap (IntPtr hdc, int nWidth, int nHeight); [DllImport("gdi32.dll", EntryPoint = "CreateCompatibleDC")] public static extern IntPtr CreateCompatibleDC(IntPtr hdc); [DllImport("gdi32.dll", EntryPoint = "SelectObject")] public static extern IntPtr SelectObject(IntPtr hdc, IntPtr bmp); #endregion } internal class Win32Stuff { #region Class Variables public const int SM_CXSCREEN = 0; public const int SM_CYSCREEN = 1; public const Int32 CURSOR_SHOWING = 0x00000001; [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 Int32 xHotspot; // Specifies the x-coordinate of a cursor's hot spot. If this structure defines an icon, the hot public Int32 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 } [StructLayout(LayoutKind.Sequential)] public struct POINT { public Int32 x; public Int32 y; } [StructLayout(LayoutKind.Sequential)] public struct CURSORINFO { public Int32 cbSize; // Specifies the size, in bytes, of the structure. public Int32 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. } #endregion #region Class Functions [DllImport("user32.dll", EntryPoint = "GetDesktopWindow")] public static extern IntPtr GetDesktopWindow(); [DllImport("user32.dll", EntryPoint = "GetDC")] public static extern IntPtr GetDC(IntPtr ptr); [DllImport("user32.dll", EntryPoint = "GetSystemMetrics")] public static extern int GetSystemMetrics(int abc); [DllImport("user32.dll", EntryPoint = "GetWindowDC")] public static extern IntPtr GetWindowDC(Int32 ptr); [DllImport("user32.dll", EntryPoint = "ReleaseDC")] public static extern IntPtr ReleaseDC(IntPtr hWnd, IntPtr hDc); [DllImport("user32.dll", EntryPoint = "GetCursorInfo")] public static extern bool GetCursorInfo(out CURSORINFO pci); [DllImport("user32.dll", EntryPoint = "CopyIcon")] public static extern IntPtr CopyIcon(IntPtr hIcon); [DllImport("user32.dll", SetLastError = true)] static extern bool DestroyIcon(IntPtr hIcon); [DllImport("user32.dll", EntryPoint = "GetIconInfo")] public static extern bool GetIconInfo(IntPtr hIcon, out ICONINFO piconinfo); #endregion } #endregion [DebuggerHidden] [DebuggerStepThrough] public static void ApplyCursor(System.Drawing.Graphics g, System.Drawing.Bitmap bitmap, int left, int top) { try { CURSORINFO pci; pci.cbSize = Marshal.SizeOf(typeof(CURSORINFO)); if (GetCursorInfo(out pci)) { if (pci.flags == CURSOR_SHOWING) { //var iconPointer = User32.CopyIcon(pci.hCursor); //User32.ICONINFO iconInfo; //User32.GetIconInfo(iconPointer, out iconInfo); var hdc = g.GetHdc(); User32.DrawIconEx(hdc, pci.ptScreenPos.x - left, pci.ptScreenPos.y - top, pci.hCursor, 0, 0, 0, IntPtr.Zero, 0x0003); //User32.DestroyIcon(iconPointer); GDIStuff.DeleteObject(pci.hCursor); } } g.ReleaseHdc(); } catch { } } } }