Я использую этот код для захвата экрана + курсор:
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;
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 (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);
}
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");
}
frame.DataLength = _byteLength;
frame.Data = new byte[_byteLength];
//If saving to disk as bitmap, it works.
//System.Drawing.Image.FromHbitmap(_compatibleBitmap).Save(frame.Path);
//If getting the image as pixel array, the square where the cursor is located is all transparent.
Native.GetDIBits(_windowDeviceContext, _compatibleBitmap, 0, (uint)Height, frame.Data, ref _infoHeader, Native.DibColorMode.DibRgbColors);
По какой-то причине, когда курсор - это I-луч (текстовый курсор), область изображения, где он должен бытьнаходится все прозрачно. Информация RGB есть, но альфа-бит 0
.

(Правильное изображение - это то, как будет выглядеть рамка после того, как все пиксельные альфа-биты установлены на 255 вручную).
Если курсор - стрелка, он работает нормально.
Но если я получу Bitmap
из ручки, а затем сохраню на диск, у изображения не будет прозрачного отверстия, как и ожидалось.
Что происходит? Это что-то с DrawIconEx
или с FromHbitmap
?
Может быть, FromHbitmap
всегда устанавливает альфа на 255 для всех пикселей? Может быть, GetDiBits
объединяет два изображения (скриншот + курсор) по-разному?
Редактировать
Как быстрое решение, я понимаю, что могу определить, является ли курсор I-Beam (замаскированный монохромный)введите) и вручную исправьте его при сохранении массива пикселей.
//Set to fix all alpha bits back to 255.
frame.RemoveAnyTransparency = iconInfo.hbmMask != IntPtr.Zero;
И:
if (frame.RemoveAnyTransparency)
for (var i = 3; i < _byteLength; i += 4)
frame.Data[i] = 255;