|
|
|
@ -1,8 +1,15 @@ |
|
|
|
using System; |
|
|
|
using System.Collections.Generic; |
|
|
|
using System.Drawing; |
|
|
|
using System.Drawing.Imaging; |
|
|
|
using System.IO; |
|
|
|
using System.Runtime.InteropServices; |
|
|
|
using Avalonia.Input; |
|
|
|
using Avalonia.Media.Imaging; |
|
|
|
using Avalonia.Platform; |
|
|
|
using Avalonia.Win32.Interop; |
|
|
|
using SdBitmap = System.Drawing.Bitmap; |
|
|
|
using SdPixelFormat = System.Drawing.Imaging.PixelFormat; |
|
|
|
|
|
|
|
namespace Avalonia.Win32 |
|
|
|
{ |
|
|
|
@ -87,5 +94,78 @@ namespace Avalonia.Win32 |
|
|
|
|
|
|
|
return rv; |
|
|
|
} |
|
|
|
|
|
|
|
public IPlatformHandle CreateCursor(IBitmapImpl cursor, PixelPoint hotSpot) |
|
|
|
{ |
|
|
|
using var source = LoadSystemDrawingBitmap(cursor); |
|
|
|
using var mask = AlphaToMask(source); |
|
|
|
|
|
|
|
var info = new UnmanagedMethods.ICONINFO |
|
|
|
{ |
|
|
|
IsIcon = false, |
|
|
|
xHotspot = hotSpot.X, |
|
|
|
yHotspot = hotSpot.Y, |
|
|
|
MaskBitmap = mask.GetHbitmap(), |
|
|
|
ColorBitmap = source.GetHbitmap(), |
|
|
|
}; |
|
|
|
|
|
|
|
return new PlatformHandle( |
|
|
|
UnmanagedMethods.CreateIconIndirect(ref info), |
|
|
|
PlatformConstants.CursorHandleType); |
|
|
|
} |
|
|
|
|
|
|
|
private SdBitmap LoadSystemDrawingBitmap(IBitmapImpl bitmap) |
|
|
|
{ |
|
|
|
using var memoryStream = new MemoryStream(); |
|
|
|
bitmap.Save(memoryStream); |
|
|
|
return new SdBitmap(memoryStream); |
|
|
|
} |
|
|
|
|
|
|
|
private unsafe SdBitmap AlphaToMask(SdBitmap source) |
|
|
|
{ |
|
|
|
var dest = new SdBitmap(source.Width, source.Height, SdPixelFormat.Format1bppIndexed); |
|
|
|
|
|
|
|
if (source.PixelFormat != SdPixelFormat.Format32bppArgb && |
|
|
|
source.PixelFormat != SdPixelFormat.Format32bppPArgb) |
|
|
|
{ |
|
|
|
return dest; |
|
|
|
} |
|
|
|
|
|
|
|
var sourceData = source.LockBits( |
|
|
|
new Rectangle(default, source.Size), |
|
|
|
ImageLockMode.ReadOnly, |
|
|
|
SdPixelFormat.Format32bppArgb); |
|
|
|
var destData = dest.LockBits( |
|
|
|
new Rectangle(default, source.Size), |
|
|
|
ImageLockMode.ReadOnly, |
|
|
|
SdPixelFormat.Format1bppIndexed); |
|
|
|
|
|
|
|
try |
|
|
|
{ |
|
|
|
var pSource = (byte*)sourceData.Scan0.ToPointer(); |
|
|
|
var pDest = (byte*)destData.Scan0.ToPointer(); |
|
|
|
|
|
|
|
for (var y = 0; y < dest.Height; ++y) |
|
|
|
{ |
|
|
|
for (var x = 0; x < dest.Width; ++x) |
|
|
|
{ |
|
|
|
if (pSource[x * 4] == 0) |
|
|
|
{ |
|
|
|
pDest[x / 8] |= (byte)(1 << (x % 8)); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
pSource += sourceData.Stride; |
|
|
|
pDest += destData.Stride; |
|
|
|
} |
|
|
|
|
|
|
|
return dest; |
|
|
|
} |
|
|
|
finally |
|
|
|
{ |
|
|
|
source.UnlockBits(sourceData); |
|
|
|
dest.UnlockBits(destData); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|