Adjust project structure
This commit is contained in:
1 parent
d38912f5da
commit
e3c436f939
2111 files changed
+14028
-47199
No files matched your search
@@ -0,0 +1,294 @@
|
||||
using System;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Security;
|
||||
using System.Windows;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
using HandyControl.Tools.Interop;
|
||||
|
||||
namespace HandyControl.Tools
|
||||
{
|
||||
internal static class IconHelper
|
||||
{
|
||||
private static Size SmallIconSize;
|
||||
|
||||
private static Size IconSize;
|
||||
|
||||
private static int SystemBitDepth;
|
||||
|
||||
[SecurityCritical, SecuritySafeCritical]
|
||||
public static void GetIconHandlesFromImageSource(ImageSource image, out IconHandle largeIconHandle, out IconHandle smallIconHandle)
|
||||
{
|
||||
EnsureSystemMetrics();
|
||||
largeIconHandle = CreateIconHandleFromImageSource(image, IconSize);
|
||||
smallIconHandle = CreateIconHandleFromImageSource(image, SmallIconSize);
|
||||
}
|
||||
|
||||
[SecurityCritical]
|
||||
public static IconHandle CreateIconHandleFromImageSource(ImageSource image, Size size)
|
||||
{
|
||||
EnsureSystemMetrics();
|
||||
|
||||
var asGoodAsItGets = false;
|
||||
|
||||
var bf = image as BitmapFrame;
|
||||
if (bf?.Decoder?.Frames != null)
|
||||
{
|
||||
bf = GetBestMatch(bf.Decoder.Frames, size);
|
||||
|
||||
asGoodAsItGets = bf.Decoder is IconBitmapDecoder || bf.PixelWidth == (int)size.Width && bf.PixelHeight == (int)size.Height;
|
||||
|
||||
image = bf;
|
||||
}
|
||||
|
||||
if (!asGoodAsItGets)
|
||||
{
|
||||
bf = BitmapFrame.Create(GenerateBitmapSource(image, size));
|
||||
}
|
||||
|
||||
return CreateIconHandleFromBitmapFrame(bf);
|
||||
}
|
||||
|
||||
[SecurityCritical]
|
||||
private static IconHandle CreateIconHandleFromBitmapFrame(BitmapFrame sourceBitmapFrame)
|
||||
{
|
||||
BitmapSource bitmapSource = sourceBitmapFrame;
|
||||
|
||||
if (bitmapSource.Format != PixelFormats.Bgra32 && bitmapSource.Format != PixelFormats.Pbgra32)
|
||||
{
|
||||
bitmapSource = new FormatConvertedBitmap(bitmapSource, PixelFormats.Bgra32, null, 0.0);
|
||||
}
|
||||
|
||||
var w = bitmapSource.PixelWidth;
|
||||
var h = bitmapSource.PixelHeight;
|
||||
var bpp = bitmapSource.Format.BitsPerPixel;
|
||||
var stride = (bpp * w + 31) / 32 * 4;
|
||||
var sizeCopyPixels = stride * h;
|
||||
var xor = new byte[sizeCopyPixels];
|
||||
bitmapSource.CopyPixels(xor, stride, 0);
|
||||
|
||||
return CreateIconCursor(xor, w, h, 0, 0, true);
|
||||
}
|
||||
|
||||
[SecurityCritical]
|
||||
internal static IconHandle CreateIconCursor(byte[] colorArray, int width, int height, int xHotspot, int yHotspot, bool isIcon)
|
||||
{
|
||||
BitmapHandle colorBitmap = null;
|
||||
BitmapHandle maskBitmap = null;
|
||||
|
||||
try
|
||||
{
|
||||
var bi = new BITMAPINFO(width, -height, 32)
|
||||
{
|
||||
bmiHeader_biCompression = NativeMethods.BI_RGB
|
||||
};
|
||||
|
||||
var bits = IntPtr.Zero;
|
||||
colorBitmap = UnsafeNativeMethods.CreateDIBSection(new HandleRef(null, IntPtr.Zero), ref bi, NativeMethods.DIB_RGB_COLORS, ref bits, null, 0);
|
||||
|
||||
if (colorBitmap.IsInvalid || bits == IntPtr.Zero)
|
||||
{
|
||||
return IconHandle.GetInvalidIcon();
|
||||
}
|
||||
|
||||
Marshal.Copy(colorArray, 0, bits, colorArray.Length);
|
||||
var maskArray = GenerateMaskArray(width, height, colorArray);
|
||||
|
||||
maskBitmap = UnsafeNativeMethods.CreateBitmap(width, height, 1, 1, maskArray);
|
||||
if (maskBitmap.IsInvalid)
|
||||
{
|
||||
return IconHandle.GetInvalidIcon();
|
||||
}
|
||||
|
||||
var iconInfo = new ICONINFO
|
||||
{
|
||||
fIcon = isIcon,
|
||||
xHotspot = xHotspot,
|
||||
yHotspot = yHotspot,
|
||||
hbmMask = maskBitmap,
|
||||
hbmColor = colorBitmap
|
||||
};
|
||||
|
||||
return UnsafeNativeMethods.CreateIconIndirect(iconInfo);
|
||||
}
|
||||
finally
|
||||
{
|
||||
colorBitmap?.Dispose();
|
||||
maskBitmap?.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
private static byte[] GenerateMaskArray(int width, int height, byte[] colorArray)
|
||||
{
|
||||
var nCount = width * height;
|
||||
var bytesPerScanLine = AlignToBytes(width, 2) / 8;
|
||||
var bitsMask = new byte[bytesPerScanLine * height];
|
||||
|
||||
for (var i = 0; i < nCount; i++)
|
||||
{
|
||||
var hPos = i % width;
|
||||
var vPos = i / width;
|
||||
var byteIndex = hPos / 8;
|
||||
var offsetBit = (byte)(0x80 >> (hPos % 8));
|
||||
|
||||
if (colorArray[i * 4 + 3] == 0x00)
|
||||
{
|
||||
bitsMask[byteIndex + bytesPerScanLine * vPos] |= offsetBit;
|
||||
}
|
||||
else
|
||||
{
|
||||
bitsMask[byteIndex + bytesPerScanLine * vPos] &= (byte)~offsetBit;
|
||||
}
|
||||
|
||||
if (hPos == width - 1 && width == 8)
|
||||
{
|
||||
bitsMask[1 + bytesPerScanLine * vPos] = 0xff;
|
||||
}
|
||||
}
|
||||
|
||||
return bitsMask;
|
||||
}
|
||||
|
||||
internal static int AlignToBytes(double original, int nBytesCount)
|
||||
{
|
||||
var nBitsCount = 8 << (nBytesCount - 1);
|
||||
return ((int)Math.Ceiling(original) + (nBitsCount - 1)) / nBitsCount * nBitsCount;
|
||||
}
|
||||
|
||||
private static BitmapSource GenerateBitmapSource(ImageSource img, Size renderSize)
|
||||
{
|
||||
var drawingDimensions = new Rect(0, 0, renderSize.Width, renderSize.Height);
|
||||
|
||||
var renderRatio = renderSize.Width / renderSize.Height;
|
||||
var aspectRatio = img.Width / img.Height;
|
||||
|
||||
if (img.Width <= renderSize.Width && img.Height <= renderSize.Height)
|
||||
{
|
||||
drawingDimensions = new Rect((renderSize.Width - img.Width) / 2, (renderSize.Height - img.Height) / 2, img.Width, img.Height);
|
||||
}
|
||||
else if (renderRatio > aspectRatio)
|
||||
{
|
||||
var scaledRenderWidth = (img.Width / img.Height) * renderSize.Width;
|
||||
drawingDimensions = new Rect((renderSize.Width - scaledRenderWidth) / 2, 0, scaledRenderWidth, renderSize.Height);
|
||||
}
|
||||
else if (renderRatio < aspectRatio)
|
||||
{
|
||||
var scaledRenderHeight = img.Height / img.Width * renderSize.Height;
|
||||
drawingDimensions = new Rect(0, (renderSize.Height - scaledRenderHeight) / 2, renderSize.Width, scaledRenderHeight);
|
||||
}
|
||||
|
||||
var dv = new DrawingVisual();
|
||||
var dc = dv.RenderOpen();
|
||||
dc.DrawImage(img, drawingDimensions);
|
||||
dc.Close();
|
||||
|
||||
var bmp = new RenderTargetBitmap((int)renderSize.Width, (int)renderSize.Height, 96, 96, PixelFormats.Pbgra32);
|
||||
bmp.Render(dv);
|
||||
|
||||
return bmp;
|
||||
}
|
||||
|
||||
private static BitmapFrame GetBestMatch(ReadOnlyCollection<BitmapFrame> frames, Size size)
|
||||
{
|
||||
var bestScore = int.MaxValue;
|
||||
var bestBpp = 0;
|
||||
var bestIndex = 0;
|
||||
|
||||
var isBitmapIconDecoder = frames[0].Decoder is IconBitmapDecoder;
|
||||
|
||||
for (int i = 0; i < frames.Count && bestScore != 0; ++i)
|
||||
{
|
||||
var currentIconBitDepth = isBitmapIconDecoder ? frames[i].Thumbnail.Format.BitsPerPixel : frames[i].Format.BitsPerPixel;
|
||||
|
||||
if (currentIconBitDepth == 0)
|
||||
{
|
||||
currentIconBitDepth = 8;
|
||||
}
|
||||
|
||||
var score = MatchImage(frames[i], size, currentIconBitDepth);
|
||||
if (score < bestScore)
|
||||
{
|
||||
bestIndex = i;
|
||||
bestBpp = currentIconBitDepth;
|
||||
bestScore = score;
|
||||
}
|
||||
else if (score == bestScore)
|
||||
{
|
||||
if (bestBpp < currentIconBitDepth)
|
||||
{
|
||||
bestIndex = i;
|
||||
bestBpp = currentIconBitDepth;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return frames[bestIndex];
|
||||
}
|
||||
|
||||
private static int MatchImage(BitmapFrame frame, Size size, int bpp)
|
||||
{
|
||||
var score = 2 * MyAbs(bpp, SystemBitDepth, false) +
|
||||
MyAbs(frame.PixelWidth, (int)size.Width, true) +
|
||||
MyAbs(frame.PixelHeight, (int)size.Height, true);
|
||||
|
||||
return score;
|
||||
}
|
||||
|
||||
private static int MyAbs(int valueHave, int valueWant, bool fPunish)
|
||||
{
|
||||
var diff = (valueHave - valueWant);
|
||||
|
||||
if (diff < 0)
|
||||
{
|
||||
diff = (fPunish ? -2 : -1) * diff;
|
||||
}
|
||||
|
||||
return diff;
|
||||
}
|
||||
|
||||
[SecurityCritical, SecuritySafeCritical]
|
||||
private static void EnsureSystemMetrics()
|
||||
{
|
||||
if (SystemBitDepth == 0)
|
||||
{
|
||||
var hdcDesktop = new HandleRef(null, UnsafeNativeMethods.GetDC(new HandleRef()));
|
||||
try
|
||||
{
|
||||
var sysBitDepth = UnsafeNativeMethods.GetDeviceCaps(hdcDesktop, NativeMethods.BITSPIXEL);
|
||||
sysBitDepth *= UnsafeNativeMethods.GetDeviceCaps(hdcDesktop, NativeMethods.PLANES);
|
||||
|
||||
if (sysBitDepth == 8)
|
||||
{
|
||||
sysBitDepth = 4;
|
||||
}
|
||||
|
||||
var cxSmallIcon = UnsafeNativeMethods.GetSystemMetrics(SM.CXSMICON);
|
||||
var cySmallIcon = UnsafeNativeMethods.GetSystemMetrics(SM.CYSMICON);
|
||||
var cxIcon = UnsafeNativeMethods.GetSystemMetrics(SM.CXICON);
|
||||
var cyIcon = UnsafeNativeMethods.GetSystemMetrics(SM.CYICON);
|
||||
|
||||
SmallIconSize = new Size(cxSmallIcon, cySmallIcon);
|
||||
IconSize = new Size(cxIcon, cyIcon);
|
||||
SystemBitDepth = sysBitDepth;
|
||||
}
|
||||
finally
|
||||
{
|
||||
UnsafeNativeMethods.ReleaseDC(new HandleRef(), hdcDesktop);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[SecurityCritical, SecuritySafeCritical]
|
||||
public static void GetDefaultIconHandles(out IconHandle largeIconHandle, out IconHandle smallIconHandle)
|
||||
{
|
||||
largeIconHandle = null;
|
||||
smallIconHandle = null;
|
||||
|
||||
SecurityHelper.DemandUIWindowPermission();
|
||||
|
||||
var iconModuleFile = UnsafeNativeMethods.GetModuleFileName(new HandleRef());
|
||||
UnsafeNativeMethods.ExtractIconEx(iconModuleFile, 0, out largeIconHandle, out smallIconHandle, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user