123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113 |
- using System;
- using System.Runtime.InteropServices;
- using System.Windows.Media;
- using System.Windows.Media.Imaging;
- using HandyControl.Tools.Interop;
- namespace HandyControl.Data;
- internal class GlowBitmap : DisposableObject
- {
- internal const int GlowBitmapPartCount = 16;
- private const int BytesPerPixelBgra32 = 4;
- private static readonly CachedBitmapInfo[] _transparencyMasks = new CachedBitmapInfo[GlowBitmapPartCount];
- private readonly InteropValues.BITMAPINFO _bitmapInfo;
- private readonly IntPtr _pbits;
- internal GlowBitmap(IntPtr hdcScreen, int width, int height)
- {
- _bitmapInfo.biSize = Marshal.SizeOf(typeof(InteropValues.BITMAPINFOHEADER));
- _bitmapInfo.biPlanes = 1;
- _bitmapInfo.biBitCount = 32;
- _bitmapInfo.biCompression = 0;
- _bitmapInfo.biXPelsPerMeter = 0;
- _bitmapInfo.biYPelsPerMeter = 0;
- _bitmapInfo.biWidth = width;
- _bitmapInfo.biHeight = -height;
- Handle = InteropMethods.CreateDIBSection(
- hdcScreen,
- ref _bitmapInfo,
- 0u,
- out _pbits,
- IntPtr.Zero,
- 0u);
- }
- internal IntPtr Handle { get; }
- internal IntPtr DIBits => _pbits;
- internal int Width => _bitmapInfo.biWidth;
- internal int Height => -_bitmapInfo.biHeight;
- protected override void DisposeNativeResources() => InteropMethods.DeleteObject(Handle);
- private static byte PremultiplyAlpha(byte channel, byte alpha) => (byte) (channel * alpha / 255.0);
- internal static GlowBitmap Create(GlowDrawingContext drawingContext, GlowBitmapPart bitmapPart, Color color)
- {
- var orCreateAlphaMask =
- GetOrCreateAlphaMask(bitmapPart);
- var glowBitmap =
- new GlowBitmap(
- drawingContext.ScreenDC,
- orCreateAlphaMask.Width,
- orCreateAlphaMask.Height);
- for (var i = 0; i < orCreateAlphaMask.DIBits.Length; i += BytesPerPixelBgra32)
- {
- var b = orCreateAlphaMask.DIBits[i + 3];
- var val = PremultiplyAlpha(color.R, b);
- var val2 = PremultiplyAlpha(color.G, b);
- var val3 = PremultiplyAlpha(color.B, b);
- Marshal.WriteByte(glowBitmap.DIBits, i, val3);
- Marshal.WriteByte(glowBitmap.DIBits, i + 1, val2);
- Marshal.WriteByte(glowBitmap.DIBits, i + 2, val);
- Marshal.WriteByte(glowBitmap.DIBits, i + 3, b);
- }
- return glowBitmap;
- }
- private static CachedBitmapInfo GetOrCreateAlphaMask(GlowBitmapPart bitmapPart)
- {
- if (_transparencyMasks[(int) bitmapPart] == null)
- {
- var bitmapImage = new BitmapImage(new Uri($"pack://application:,,,/HandyControl;Component/Resources/Images/GlowWindow/{bitmapPart}.png"));
- var array = new byte[BytesPerPixelBgra32 * bitmapImage.PixelWidth * bitmapImage.PixelHeight];
- var stride = BytesPerPixelBgra32 * bitmapImage.PixelWidth;
- bitmapImage.CopyPixels(array, stride, 0);
- bitmapImage.Freeze();
- _transparencyMasks[(int) bitmapPart] =
- new CachedBitmapInfo(
- array,
- bitmapImage.PixelWidth,
- bitmapImage.PixelHeight);
- }
- return _transparencyMasks[(int) bitmapPart];
- }
- private sealed class CachedBitmapInfo
- {
- internal readonly byte[] DIBits;
- internal readonly int Height;
- internal readonly int Width;
- internal CachedBitmapInfo(byte[] diBits, int width, int height)
- {
- Width = width;
- Height = height;
- DIBits = diBits;
- }
- }
- }
|