private void CursorCapture(FrameInfo frame) { //if (_justStarted && (CursorShapeBuffer?.Length ?? 0) == 0) { //_justStarted = false; //https://stackoverflow.com/a/6374151/1735672 //Bitmap struct, is used to get the cursor shape when SharpDX fails to do so. var _infoHeader = new Native.BitmapInfoHeader(); _infoHeader.biSize = (uint)Marshal.SizeOf(_infoHeader); _infoHeader.biBitCount = 32; _infoHeader.biClrUsed = 0; _infoHeader.biClrImportant = 0; _infoHeader.biCompression = 0; _infoHeader.biHeight = -Height; //Negative, so the Y-axis will be positioned correctly. _infoHeader.biWidth = Width; _infoHeader.biPlanes = 1; try { var cursorInfo = new Native.CursorInfo(); cursorInfo.cbSize = Marshal.SizeOf(cursorInfo); if (Native.GetCursorInfo(out cursorInfo)) { if (cursorInfo.flags == Native.CursorShowing) { var hicon = Native.CopyIcon(cursorInfo.hCursor); if (hicon != IntPtr.Zero) { if (Native.GetIconInfo(hicon, out var iconInfo)) { frame.CursorX = cursorInfo.ptScreenPos.X - Left; frame.CursorY = cursorInfo.ptScreenPos.Y - Top; var bitmap = new Native.Bitmap(); var hndl = GCHandle.Alloc(bitmap, GCHandleType.Pinned); var ptrToBitmap = hndl.AddrOfPinnedObject(); Native.GetObject(iconInfo.hbmColor, Marshal.SizeOf <Native.Bitmap>(), ptrToBitmap); bitmap = Marshal.PtrToStructure <Native.Bitmap>(ptrToBitmap); hndl.Free(); //https://microsoft.public.vc.mfc.narkive.com/H1CZeqUk/how-can-i-get-bitmapinfo-object-from-bitmap-or-hbitmap _infoHeader.biHeight = bitmap.bmHeight; _infoHeader.biWidth = bitmap.bmWidth; _infoHeader.biBitCount = (ushort)bitmap.bmBitsPixel; var w = (bitmap.bmWidth * bitmap.bmBitsPixel + 31) / 8; CursorShapeBuffer = new byte[w * bitmap.bmHeight]; var windowDeviceContext = Native.GetWindowDC(IntPtr.Zero); var compatibleBitmap = Native.CreateCompatibleBitmap(windowDeviceContext, Width, Height); Native.GetDIBits(windowDeviceContext, compatibleBitmap, 0, (uint)_infoHeader.biHeight, CursorShapeBuffer, ref _infoHeader, Native.DibColorMode.DibRgbColors); //if (frame.CursorX > 0 && frame.CursorY > 0) // Native.DrawIconEx(_compatibleDeviceContext, frame.CursorX - iconInfo.xHotspot, frame.CursorY - iconInfo.yHotspot, cursorInfo.hCursor, 0, 0, 0, IntPtr.Zero, 0x0003); //Clean objects here. } Native.DeleteObject(iconInfo.hbmColor); Native.DeleteObject(iconInfo.hbmMask); } Native.DestroyIcon(hicon); } Native.DeleteObject(cursorInfo.hCursor); } } catch (Exception e) { LogWriter.Log(e, "Impossible to get the cursor"); } } }
public override int CaptureWithCursor(FrameInfo frame) { try { new System.Security.Permissions.UIPermission(System.Security.Permissions.UIPermissionWindow.AllWindows).Demand(); //var success = Native.BitBlt(CompatibleDeviceContext, 0, 0, Width, Height, WindowDeviceContext, Left, Top, Native.CopyPixelOperation.SourceCopy | Native.CopyPixelOperation.CaptureBlt); var success = Native.StretchBlt(CompatibleDeviceContext, 0, 0, StartWidth, StartHeight, WindowDeviceContext, Left, Top, Width, Height, Native.CopyPixelOperation.SourceCopy | Native.CopyPixelOperation.CaptureBlt); if (!success) { return(FrameCount); } #region Cursor try { var cursorInfo = new Native.CursorInfo(); cursorInfo.cbSize = Marshal.SizeOf(cursorInfo); if (Native.GetCursorInfo(out cursorInfo)) { if (cursorInfo.flags == Native.CursorShowing) { var hicon = Native.CopyIcon(cursorInfo.hCursor); if (hicon != IntPtr.Zero) { if (Native.GetIconInfo(hicon, out var iconInfo)) { frame.CursorX = cursorInfo.ptScreenPos.X - Left; frame.CursorY = cursorInfo.ptScreenPos.Y - Top; //If the cursor rate needs to be precisely captured. //https://source.winehq.org/source/dlls/user32/cursoricon.c#2325 //int rate = 0, num = 0; //var ok1 = Native.GetCursorFrameInfo(cursorInfo.hCursor, IntPtr.Zero, 17, ref rate, ref num); //CursorStep var ok = Native.DrawIconEx(CompatibleDeviceContext, frame.CursorX - iconInfo.xHotspot, frame.CursorY - iconInfo.yHotspot, cursorInfo.hCursor, 0, 0, CursorStep, IntPtr.Zero, 0x0003); if (!ok) { CursorStep = 0; Native.DrawIconEx(CompatibleDeviceContext, frame.CursorX - iconInfo.xHotspot, frame.CursorY - iconInfo.yHotspot, cursorInfo.hCursor, 0, 0, CursorStep, IntPtr.Zero, 0x0003); } else { CursorStep++; } //Set to fix all alpha bits back to 255. //frame.RemoveAnyTransparency = iconInfo.hbmMask != IntPtr.Zero; } Native.DeleteObject(iconInfo.hbmColor); Native.DeleteObject(iconInfo.hbmMask); } Native.DestroyIcon(hicon); } Native.DeleteObject(cursorInfo.hCursor); } } catch (Exception e) { //LogWriter.Log(e, "Impossible to get the cursor"); } #endregion //Set frame details. FrameCount++; frame.Path = $"{Project.FullPath}{FrameCount}.png"; frame.Delay = FrameRate.GetMilliseconds(SnapDelay); frame.DataLength = _byteLength; frame.Data = new byte[_byteLength]; Native.GetDIBits(WindowDeviceContext, CompatibleBitmap, 0, (uint)StartHeight, frame.Data, ref _infoHeader, Native.DibColorMode.DibRgbColors); BlockingCollection.Add(frame); } catch (Exception e) { //LogWriter.Log(ex, "Impossible to get the screenshot of the screen"); } return(FrameCount); }
public override int CaptureWithCursor(FrameInfo frame) { try { new System.Security.Permissions.UIPermission(System.Security.Permissions.UIPermissionWindow.AllWindows).Demand(); var success = Native.BitBlt(CompatibleDeviceContext, 0, 0, Width, Height, WindowDeviceContext, Left, Top, Native.CopyPixelOperation.SourceCopy | Native.CopyPixelOperation.CaptureBlt); if (!success) { return(FrameCount); } #region Cursor try { var cursorInfo = new Native.CursorInfo(); cursorInfo.cbSize = Marshal.SizeOf(cursorInfo); if (Native.GetCursorInfo(out cursorInfo)) { if (cursorInfo.flags == Native.CursorShowing) { var hicon = Native.CopyIcon(cursorInfo.hCursor); if (hicon != IntPtr.Zero) { if (Native.GetIconInfo(hicon, out var iconInfo)) { frame.CursorX = cursorInfo.ptScreenPos.X - Left; frame.CursorY = cursorInfo.ptScreenPos.Y - Top; var ok = Native.DrawIconEx(CompatibleDeviceContext, frame.CursorX - iconInfo.xHotspot, frame.CursorY - iconInfo.yHotspot, cursorInfo.hCursor, 0, 0, CursorStep, IntPtr.Zero, 0x0003); if (!ok) { CursorStep = 0; Native.DrawIconEx(CompatibleDeviceContext, frame.CursorX - iconInfo.xHotspot, frame.CursorY - iconInfo.yHotspot, cursorInfo.hCursor, 0, 0, CursorStep, IntPtr.Zero, 0x0003); } else { CursorStep++; } } Native.DeleteObject(iconInfo.hbmColor); Native.DeleteObject(iconInfo.hbmMask); } Native.DestroyIcon(hicon); } Native.DeleteObject(cursorInfo.hCursor); } } catch (Exception) { //LogWriter.Log(e, "Impossible to get the cursor"); } #endregion //Set frame details. FrameCount++; frame.Path = $"{Project.FullPath}{FrameCount}.png"; frame.Delay = FrameRate.GetMilliseconds(SnapDelay); frame.Image = Image.FromHbitmap(CompatibleBitmap); BlockingCollection.Add(frame); } catch (Exception) { //LogWriter.Log(ex, "Impossible to get the screenshot of the screen"); } return(FrameCount); }
/// <summary> /// Gets the position and Bitmap of the system cursor. /// </summary> /// <param name="point"><code>ref</code> parameter, only to return a second value.</param> /// <returns>The current Icon of the cursor</returns> public static Bitmap CaptureImageCursor(ref Point point) { var cursorInfo = new Native.CursorInfo(); cursorInfo.cbSize = Marshal.SizeOf(cursorInfo); if (!Native.GetCursorInfo(out cursorInfo)) { return(null); } if (cursorInfo.flags != Native.CursorShowing) { return(null); } var hicon = Native.CopyIcon(cursorInfo.hCursor); if (hicon == IntPtr.Zero) { return(null); } Native.ICONINFO iconInfo; if (!Native.GetIconInfo(hicon, out iconInfo)) { return(null); } point.X = cursorInfo.ptScreenPos.X - ((int)iconInfo.xHotspot); point.Y = cursorInfo.ptScreenPos.Y - ((int)iconInfo.yHotspot); try { using (var maskBitmap = Image.FromHbitmap(iconInfo.hbmMask)) { //Is this a monochrome cursor? //if (maskBitmap.Height == maskBitmap.Width * 2) if (maskBitmap.Height == maskBitmap.Width * 2 && iconInfo.hbmColor == IntPtr.Zero) { var resultBitmap = new Bitmap(maskBitmap.Width, maskBitmap.Width); using (var desktopGraphics = Graphics.FromHwnd(Native.GetDesktopWindow())) { var desktopHdc = desktopGraphics.GetHdc(); var maskHdc = Native.CreateCompatibleDC(desktopHdc); var oldPtr = Native.SelectObject(maskHdc, maskBitmap.GetHbitmap()); using (var resultGraphics = Graphics.FromImage(resultBitmap)) { var resultHdc = resultGraphics.GetHdc(); // These two operation will result in a black cursor over a white background. // Later in the code, a call to MakeTransparent() will get rid of the white background. // They take two pieces from a single image and merge into one. //Bottom part Native.BitBlt(resultHdc, 0, 0, resultBitmap.Width, resultBitmap.Height, maskHdc, 0, resultBitmap.Height, Native.CopyPixelOperation.SourceCopy); //SourceCopy //Top part. Native.BitBlt(resultHdc, 0, 0, resultBitmap.Width, resultBitmap.Height, maskHdc, 0, 0, Native.CopyPixelOperation.PatInvert); //SourceInvert //BUG: It still don't take into account the background color (from the desktop) with the I-bean cursor, the one that inverts its color. resultGraphics.ReleaseHdc(resultHdc); } var newPtr = Native.SelectObject(maskHdc, oldPtr); Native.DeleteObject(newPtr); Native.DeleteDC(maskHdc); desktopGraphics.ReleaseHdc(desktopHdc); } // Remove the white background from the BitBlt calls, // resulting in a black cursor over a transparent background. resultBitmap.MakeTransparent(Color.White); return(resultBitmap); } } } catch (Exception ex) { LogWriter.Log(ex, "Impossible to get the icon."); } var icon = Icon.FromHandle(hicon); return(icon.ToBitmap()); }