fixed a bug of Screenshot on win7
This commit is contained in:
1 parent
dc64d5cacb
commit
f4087574c0
11 files changed
+850
-450
No files matched your search
@@ -13,6 +13,7 @@ using System.Windows.Media.Imaging;
|
||||
using System.Windows.Resources;
|
||||
using HandyControl.Data;
|
||||
using HandyControl.Tools;
|
||||
using HandyControl.Tools.Interop;
|
||||
|
||||
namespace HandyControl.Controls
|
||||
{
|
||||
@@ -123,7 +124,7 @@ namespace HandyControl.Controls
|
||||
try
|
||||
{
|
||||
StopAnimate();
|
||||
ExternDllHelper.Gdip.GdipDisposeImage(new HandleRef(this, NativeImage));
|
||||
InteropMethods.Gdip.GdipDisposeImage(new HandleRef(this, NativeImage));
|
||||
}
|
||||
catch
|
||||
{
|
||||
@@ -139,17 +140,17 @@ namespace HandyControl.Controls
|
||||
{
|
||||
filename = Path.GetFullPath(filename);
|
||||
|
||||
var status = ExternDllHelper.Gdip.GdipCreateBitmapFromFile(filename, out var bitmap);
|
||||
var status = InteropMethods.Gdip.GdipCreateBitmapFromFile(filename, out var bitmap);
|
||||
|
||||
if (status != ExternDllHelper.Gdip.Ok)
|
||||
throw ExternDllHelper.Gdip.StatusException(status);
|
||||
if (status != InteropMethods.Gdip.Ok)
|
||||
throw InteropMethods.Gdip.StatusException(status);
|
||||
|
||||
status = ExternDllHelper.Gdip.GdipImageForceValidation(new HandleRef(null, bitmap));
|
||||
status = InteropMethods.Gdip.GdipImageForceValidation(new HandleRef(null, bitmap));
|
||||
|
||||
if (status != ExternDllHelper.Gdip.Ok)
|
||||
if (status != InteropMethods.Gdip.Ok)
|
||||
{
|
||||
ExternDllHelper.Gdip.GdipDisposeImage(new HandleRef(null, bitmap));
|
||||
throw ExternDllHelper.Gdip.StatusException(status);
|
||||
InteropMethods.Gdip.GdipDisposeImage(new HandleRef(null, bitmap));
|
||||
throw InteropMethods.Gdip.StatusException(status);
|
||||
}
|
||||
|
||||
SetNativeImage(bitmap);
|
||||
@@ -162,17 +163,17 @@ namespace HandyControl.Controls
|
||||
if (stream == null)
|
||||
throw new ArgumentException("stream null");
|
||||
|
||||
var status = ExternDllHelper.Gdip.GdipCreateBitmapFromStream(new GPStream(stream), out var bitmap);
|
||||
var status = InteropMethods.Gdip.GdipCreateBitmapFromStream(new GPStream(stream), out var bitmap);
|
||||
|
||||
if (status != ExternDllHelper.Gdip.Ok)
|
||||
throw ExternDllHelper.Gdip.StatusException(status);
|
||||
if (status != InteropMethods.Gdip.Ok)
|
||||
throw InteropMethods.Gdip.StatusException(status);
|
||||
|
||||
status = ExternDllHelper.Gdip.GdipImageForceValidation(new HandleRef(null, bitmap));
|
||||
status = InteropMethods.Gdip.GdipImageForceValidation(new HandleRef(null, bitmap));
|
||||
|
||||
if (status != ExternDllHelper.Gdip.Ok)
|
||||
if (status != InteropMethods.Gdip.Ok)
|
||||
{
|
||||
ExternDllHelper.Gdip.GdipDisposeImage(new HandleRef(null, bitmap));
|
||||
throw ExternDllHelper.Gdip.StatusException(status);
|
||||
InteropMethods.Gdip.GdipDisposeImage(new HandleRef(null, bitmap));
|
||||
throw InteropMethods.Gdip.StatusException(status);
|
||||
}
|
||||
|
||||
SetNativeImage(bitmap);
|
||||
@@ -296,10 +297,10 @@ namespace HandyControl.Controls
|
||||
{
|
||||
var guid = new Guid();
|
||||
|
||||
var status = ExternDllHelper.Gdip.GdipGetImageRawFormat(new HandleRef(this, NativeImage), ref guid);
|
||||
var status = InteropMethods.Gdip.GdipGetImageRawFormat(new HandleRef(this, NativeImage), ref guid);
|
||||
|
||||
if (status != ExternDllHelper.Gdip.Ok)
|
||||
throw ExternDllHelper.Gdip.StatusException(status);
|
||||
if (status != InteropMethods.Gdip.Ok)
|
||||
throw InteropMethods.Gdip.StatusException(status);
|
||||
|
||||
return guid;
|
||||
}
|
||||
@@ -321,11 +322,11 @@ namespace HandyControl.Controls
|
||||
{
|
||||
get
|
||||
{
|
||||
var status = ExternDllHelper.Gdip.GdipImageGetFrameDimensionsCount(new HandleRef(this, NativeImage), out var count);
|
||||
var status = InteropMethods.Gdip.GdipImageGetFrameDimensionsCount(new HandleRef(this, NativeImage), out var count);
|
||||
|
||||
if (status != ExternDllHelper.Gdip.Ok)
|
||||
if (status != InteropMethods.Gdip.Ok)
|
||||
{
|
||||
throw ExternDllHelper.Gdip.StatusException(status);
|
||||
throw InteropMethods.Gdip.StatusException(status);
|
||||
}
|
||||
|
||||
if (count <= 0)
|
||||
@@ -338,15 +339,15 @@ namespace HandyControl.Controls
|
||||
var buffer = Marshal.AllocHGlobal(checked(size * count));
|
||||
if (buffer == IntPtr.Zero)
|
||||
{
|
||||
throw ExternDllHelper.Gdip.StatusException(ExternDllHelper.Gdip.OutOfMemory);
|
||||
throw InteropMethods.Gdip.StatusException(InteropMethods.Gdip.OutOfMemory);
|
||||
}
|
||||
|
||||
status = ExternDllHelper.Gdip.GdipImageGetFrameDimensionsList(new HandleRef(this, NativeImage), buffer, count);
|
||||
status = InteropMethods.Gdip.GdipImageGetFrameDimensionsList(new HandleRef(this, NativeImage), buffer, count);
|
||||
|
||||
if (status != ExternDllHelper.Gdip.Ok)
|
||||
if (status != InteropMethods.Gdip.Ok)
|
||||
{
|
||||
Marshal.FreeHGlobal(buffer);
|
||||
throw ExternDllHelper.Gdip.StatusException(status);
|
||||
throw InteropMethods.Gdip.StatusException(status);
|
||||
}
|
||||
|
||||
var guids = new Guid[count];
|
||||
@@ -355,7 +356,7 @@ namespace HandyControl.Controls
|
||||
{
|
||||
for (var i = 0; i < count; i++)
|
||||
{
|
||||
guids[i] = (Guid)ExternDllHelper.PtrToStructure((IntPtr)((long)buffer + size * i), typeof(Guid));
|
||||
guids[i] = (Guid)InteropMethods.PtrToStructure((IntPtr)((long)buffer + size * i), typeof(Guid));
|
||||
}
|
||||
}
|
||||
finally
|
||||
@@ -372,10 +373,10 @@ namespace HandyControl.Controls
|
||||
var count = new[] { 0 };
|
||||
|
||||
var dimensionId = dimension.Guid;
|
||||
var status = ExternDllHelper.Gdip.GdipImageGetFrameCount(new HandleRef(this, NativeImage), ref dimensionId, count);
|
||||
var status = InteropMethods.Gdip.GdipImageGetFrameCount(new HandleRef(this, NativeImage), ref dimensionId, count);
|
||||
|
||||
if (status != ExternDllHelper.Gdip.Ok)
|
||||
throw ExternDllHelper.Gdip.StatusException(status);
|
||||
if (status != InteropMethods.Gdip.Ok)
|
||||
throw InteropMethods.Gdip.StatusException(status);
|
||||
|
||||
return count[0];
|
||||
}
|
||||
@@ -384,10 +385,10 @@ namespace HandyControl.Controls
|
||||
{
|
||||
GifPropertyItem propitem;
|
||||
|
||||
var status = ExternDllHelper.Gdip.GdipGetPropertyItemSize(new HandleRef(this, NativeImage), propid, out var size);
|
||||
var status = InteropMethods.Gdip.GdipGetPropertyItemSize(new HandleRef(this, NativeImage), propid, out var size);
|
||||
|
||||
if (status != ExternDllHelper.Gdip.Ok)
|
||||
throw ExternDllHelper.Gdip.StatusException(status);
|
||||
if (status != InteropMethods.Gdip.Ok)
|
||||
throw InteropMethods.Gdip.StatusException(status);
|
||||
|
||||
if (size == 0)
|
||||
return null;
|
||||
@@ -395,15 +396,15 @@ namespace HandyControl.Controls
|
||||
var propdata = Marshal.AllocHGlobal(size);
|
||||
|
||||
if (propdata == IntPtr.Zero)
|
||||
throw ExternDllHelper.Gdip.StatusException(ExternDllHelper.Gdip.OutOfMemory);
|
||||
throw InteropMethods.Gdip.StatusException(InteropMethods.Gdip.OutOfMemory);
|
||||
|
||||
status = ExternDllHelper.Gdip.GdipGetPropertyItem(new HandleRef(this, NativeImage), propid, size, propdata);
|
||||
status = InteropMethods.Gdip.GdipGetPropertyItem(new HandleRef(this, NativeImage), propid, size, propdata);
|
||||
|
||||
try
|
||||
{
|
||||
if (status != ExternDllHelper.Gdip.Ok)
|
||||
if (status != InteropMethods.Gdip.Ok)
|
||||
{
|
||||
throw ExternDllHelper.Gdip.StatusException(status);
|
||||
throw InteropMethods.Gdip.StatusException(status);
|
||||
}
|
||||
|
||||
propitem = GifPropertyItemInternal.ConvertFromMemory(propdata, 1)[0];
|
||||
@@ -421,10 +422,10 @@ namespace HandyControl.Controls
|
||||
var count = new[] { 0 };
|
||||
|
||||
var dimensionId = dimension.Guid;
|
||||
var status = ExternDllHelper.Gdip.GdipImageSelectActiveFrame(new HandleRef(this, NativeImage), ref dimensionId, frameIndex);
|
||||
var status = InteropMethods.Gdip.GdipImageSelectActiveFrame(new HandleRef(this, NativeImage), ref dimensionId, frameIndex);
|
||||
|
||||
if (status != ExternDllHelper.Gdip.Ok)
|
||||
throw ExternDllHelper.Gdip.StatusException(status);
|
||||
if (status != InteropMethods.Gdip.Ok)
|
||||
throw InteropMethods.Gdip.StatusException(status);
|
||||
|
||||
return count[0];
|
||||
}
|
||||
@@ -441,16 +442,16 @@ namespace HandyControl.Controls
|
||||
[ResourceConsumption(ResourceScope.Machine)]
|
||||
internal IntPtr GetHbitmap(Color background)
|
||||
{
|
||||
var status = ExternDllHelper.Gdip.GdipCreateHBITMAPFromBitmap(new HandleRef(this, NativeImage), out var hBitmap,
|
||||
var status = InteropMethods.Gdip.GdipCreateHBITMAPFromBitmap(new HandleRef(this, NativeImage), out var hBitmap,
|
||||
ColorHelper.ToWin32(background));
|
||||
if (status == 2 && (Width >= short.MaxValue || Height >= short.MaxValue))
|
||||
{
|
||||
throw new ArgumentException("GdiplusInvalidSize");
|
||||
}
|
||||
|
||||
if (status != ExternDllHelper.Gdip.Ok && NativeImage != IntPtr.Zero)
|
||||
if (status != InteropMethods.Gdip.Ok && NativeImage != IntPtr.Zero)
|
||||
{
|
||||
throw ExternDllHelper.Gdip.StatusException(status);
|
||||
throw InteropMethods.Gdip.StatusException(status);
|
||||
}
|
||||
|
||||
return hBitmap;
|
||||
@@ -474,7 +475,7 @@ namespace HandyControl.Controls
|
||||
{
|
||||
if (handle != IntPtr.Zero)
|
||||
{
|
||||
ExternDllHelper.DeleteObject(handle);
|
||||
InteropMethods.DeleteObject(handle);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Interop;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
using HandyControl.Data;
|
||||
@@ -31,6 +33,8 @@ namespace HandyControl.Controls
|
||||
|
||||
private BitmapSource _imageSource;
|
||||
|
||||
private static readonly Guid BmpGuid = new Guid("{b96b3cab-0728-11d3-9d7b-0000f81ef32e}");
|
||||
|
||||
#region const
|
||||
|
||||
private const int IntervalLength = 1;
|
||||
@@ -554,13 +558,63 @@ namespace HandyControl.Controls
|
||||
var desktopWindowWidth = _desktopWindowRect.Right - _desktopWindowRect.Left;
|
||||
var desktopWindowHeight = _desktopWindowRect.Bottom - _desktopWindowRect.Top;
|
||||
|
||||
var bitmap = InteropMethods.CreateCompatibleBitmap(hdcSrc, desktopWindowWidth, desktopWindowHeight);
|
||||
var hOld = InteropMethods.SelectObject(hdcDest, bitmap);
|
||||
var hbitmap = InteropMethods.CreateCompatibleBitmap(hdcSrc, desktopWindowWidth, desktopWindowHeight);
|
||||
var hOld = InteropMethods.SelectObject(hdcDest, hbitmap);
|
||||
InteropMethods.BitBlt(hdcDest, 0, 0, desktopWindowWidth, desktopWindowHeight, hdcSrc, 0, 0, InteropValues.SRCCOPY);
|
||||
InteropMethods.SelectObject(hdcDest, hOld);
|
||||
InteropMethods.DeleteDC(hdcDest);
|
||||
InteropMethods.ReleaseDC(_desktopWindowHandle, hdcSrc);
|
||||
return Imaging.CreateBitmapSourceFromHBitmap(bitmap, IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions());
|
||||
|
||||
var status = InteropMethods.Gdip.GdipCreateBitmapFromHBITMAP(new HandleRef(null, hbitmap), new HandleRef(null, IntPtr.Zero), out var bitmap);
|
||||
if (status != InteropMethods.Gdip.Ok) throw InteropMethods.Gdip.StatusException(status);
|
||||
|
||||
using var ms = new MemoryStream();
|
||||
status = InteropMethods.Gdip.GdipGetImageEncodersSize(out var numEncoders, out var size);
|
||||
if (status != InteropMethods.Gdip.Ok) throw InteropMethods.Gdip.StatusException(status);
|
||||
|
||||
var memory = Marshal.AllocHGlobal(size);
|
||||
try
|
||||
{
|
||||
status = InteropMethods.Gdip.GdipGetImageEncoders(numEncoders, size, memory);
|
||||
if (status != InteropMethods.Gdip.Ok) throw InteropMethods.Gdip.StatusException(status);
|
||||
|
||||
var codecInfo = ImageCodecInfo.ConvertFromMemory(memory, numEncoders).FirstOrDefault(item => item.FormatID.Equals(BmpGuid));
|
||||
if (codecInfo == null) throw new Exception("ImageCodecInfo is null");
|
||||
|
||||
var encoderParamsMemory = IntPtr.Zero;
|
||||
|
||||
try
|
||||
{
|
||||
var g = codecInfo.Clsid;
|
||||
status = InteropMethods.Gdip.GdipSaveImageToStream(new HandleRef(this, bitmap),
|
||||
new InteropValues.ComStreamFromDataStream(ms), ref g,
|
||||
new HandleRef(null, encoderParamsMemory));
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (encoderParamsMemory != IntPtr.Zero)
|
||||
{
|
||||
Marshal.FreeHGlobal(encoderParamsMemory);
|
||||
}
|
||||
}
|
||||
|
||||
if (status != InteropMethods.Gdip.Ok)
|
||||
{
|
||||
throw InteropMethods.Gdip.StatusException(status);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
Marshal.FreeHGlobal(memory);
|
||||
}
|
||||
|
||||
var bitmapImage = new BitmapImage();
|
||||
bitmapImage.BeginInit();
|
||||
bitmapImage.CacheOption = BitmapCacheOption.OnLoad;
|
||||
bitmapImage.StreamSource = ms;
|
||||
bitmapImage.EndInit();
|
||||
bitmapImage.Freeze();
|
||||
return bitmapImage;
|
||||
}
|
||||
|
||||
private void MoveElement(InteropValues.POINT point)
|
||||
|
||||
@@ -3,6 +3,7 @@ using System.Windows;
|
||||
using System.Windows.Media;
|
||||
using HandyControl.Data;
|
||||
using HandyControl.Tools;
|
||||
using HandyControl.Tools.Interop;
|
||||
|
||||
namespace HandyControl.Controls
|
||||
{
|
||||
@@ -33,12 +34,12 @@ namespace HandyControl.Controls
|
||||
return;
|
||||
}
|
||||
|
||||
var accentPolicy = new ExternDllHelper.ACCENTPOLICY();
|
||||
var accentPolicy = new InteropValues.ACCENTPOLICY();
|
||||
var accentPolicySize = Marshal.SizeOf(accentPolicy);
|
||||
|
||||
accentPolicy.AccentState = SystemVersionInfo < SystemVersionInfo.Windows10_1809
|
||||
? ExternDllHelper.ACCENTSTATE.ACCENT_ENABLE_BLURBEHIND
|
||||
: ExternDllHelper.ACCENTSTATE.ACCENT_ENABLE_ACRYLICBLURBEHIND;
|
||||
? InteropValues.ACCENTSTATE.ACCENT_ENABLE_BLURBEHIND
|
||||
: InteropValues.ACCENTSTATE.ACCENT_ENABLE_ACRYLICBLURBEHIND;
|
||||
|
||||
accentPolicy.AccentFlags = 2;
|
||||
accentPolicy.GradientColor = ResourceHelper.GetResource<uint>(ResourceToken.BlurGradientValue);
|
||||
@@ -46,14 +47,14 @@ namespace HandyControl.Controls
|
||||
var accentPtr = Marshal.AllocHGlobal(accentPolicySize);
|
||||
Marshal.StructureToPtr(accentPolicy, accentPtr, false);
|
||||
|
||||
var data = new ExternDllHelper.WINCOMPATTRDATA
|
||||
var data = new InteropValues.WINCOMPATTRDATA
|
||||
{
|
||||
Attribute = ExternDllHelper.WINDOWCOMPOSITIONATTRIB.WCA_ACCENT_POLICY,
|
||||
Attribute = InteropValues.WINDOWCOMPOSITIONATTRIB.WCA_ACCENT_POLICY,
|
||||
DataSize = accentPolicySize,
|
||||
Data = accentPtr
|
||||
};
|
||||
|
||||
ExternDllHelper.SetWindowCompositionAttribute(window.GetHandle(), ref data);
|
||||
InteropMethods.Gdip.SetWindowCompositionAttribute(window.GetHandle(), ref data);
|
||||
|
||||
Marshal.FreeHGlobal(accentPtr);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
using System;
|
||||
|
||||
namespace HandyControl.Data
|
||||
{
|
||||
[Flags]
|
||||
internal enum ImageCodecFlags
|
||||
{
|
||||
Encoder = 0x00000001,
|
||||
Decoder = 0x00000002,
|
||||
SupportBitmap = 0x00000004,
|
||||
SupportVector = 0x00000008,
|
||||
SeekableEncode = 0x00000010,
|
||||
BlockingDecode = 0x00000020,
|
||||
Builtin = 0x00010000,
|
||||
System = 0x00020000,
|
||||
User = 0x00040000
|
||||
}
|
||||
}
|
||||
@@ -3,12 +3,12 @@ using System.Diagnostics.CodeAnalysis;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Security.Permissions;
|
||||
using HandyControl.Tools;
|
||||
using HandyControl.Tools.Interop;
|
||||
|
||||
namespace HandyControl.Data
|
||||
{
|
||||
// ReSharper disable once InconsistentNaming
|
||||
internal class GPStream : ExternDllHelper.IStream
|
||||
internal class GPStream : InteropValues.IStream
|
||||
{
|
||||
protected Stream DataStream;
|
||||
|
||||
@@ -55,7 +55,7 @@ namespace HandyControl.Data
|
||||
_virtualPosition = -1;
|
||||
}
|
||||
|
||||
public virtual ExternDllHelper.IStream Clone()
|
||||
public virtual InteropValues.IStream Clone()
|
||||
{
|
||||
NotImplemented();
|
||||
return null;
|
||||
@@ -72,7 +72,7 @@ namespace HandyControl.Data
|
||||
UIPermission(SecurityAction.Demand, Window = UIPermissionWindow.AllWindows),
|
||||
SecurityPermission(SecurityAction.Assert, Flags = SecurityPermissionFlag.UnmanagedCode)
|
||||
]
|
||||
public virtual long CopyTo(ExternDllHelper.IStream pstm, long cb, long[] pcbRead)
|
||||
public virtual long CopyTo(InteropValues.IStream pstm, long cb, long[] pcbRead)
|
||||
{
|
||||
|
||||
const int bufsize = 4096;
|
||||
@@ -117,7 +117,7 @@ namespace HandyControl.Data
|
||||
|
||||
protected static ExternalException EFail(string msg)
|
||||
{
|
||||
throw new ExternalException(msg, ExternDllHelper.E_FAIL);
|
||||
throw new ExternalException(msg, InteropMethods.E_FAIL);
|
||||
}
|
||||
|
||||
protected static void NotImplemented()
|
||||
@@ -154,7 +154,7 @@ namespace HandyControl.Data
|
||||
var len = DataStream.Length;
|
||||
switch (origin)
|
||||
{
|
||||
case ExternDllHelper.StreamConsts.STREAM_SEEK_SET:
|
||||
case InteropValues.StreamConsts.STREAM_SEEK_SET:
|
||||
if (offset <= len)
|
||||
{
|
||||
DataStream.Position = offset;
|
||||
@@ -165,7 +165,7 @@ namespace HandyControl.Data
|
||||
_virtualPosition = offset;
|
||||
}
|
||||
break;
|
||||
case ExternDllHelper.StreamConsts.STREAM_SEEK_END:
|
||||
case InteropValues.StreamConsts.STREAM_SEEK_END:
|
||||
if (offset <= 0)
|
||||
{
|
||||
DataStream.Position = len + offset;
|
||||
@@ -176,7 +176,7 @@ namespace HandyControl.Data
|
||||
_virtualPosition = len + offset;
|
||||
}
|
||||
break;
|
||||
case ExternDllHelper.StreamConsts.STREAM_SEEK_CUR:
|
||||
case InteropValues.StreamConsts.STREAM_SEEK_CUR:
|
||||
if (offset + pos <= len)
|
||||
{
|
||||
DataStream.Position = pos + offset;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using HandyControl.Tools;
|
||||
using HandyControl.Tools.Interop;
|
||||
|
||||
namespace HandyControl.Data
|
||||
{
|
||||
@@ -85,7 +85,7 @@ namespace HandyControl.Data
|
||||
GifPropertyItemInternal propcopy = null;
|
||||
try
|
||||
{
|
||||
propcopy = (GifPropertyItemInternal) ExternDllHelper.PtrToStructure(propdata,
|
||||
propcopy = (GifPropertyItemInternal) InteropMethods.PtrToStructure(propdata,
|
||||
typeof(GifPropertyItemInternal));
|
||||
|
||||
props[i] = new GifPropertyItem
|
||||
|
||||
@@ -0,0 +1,158 @@
|
||||
using System;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Runtime.InteropServices;
|
||||
using HandyControl.Tools.Interop;
|
||||
|
||||
namespace HandyControl.Data
|
||||
{
|
||||
internal sealed class ImageCodecInfo
|
||||
{
|
||||
private string _dllName;
|
||||
|
||||
public Guid Clsid { get; set; }
|
||||
|
||||
public Guid FormatID { get; set; }
|
||||
|
||||
public string CodecName { get; set; }
|
||||
|
||||
public string DllName
|
||||
{
|
||||
[SuppressMessage("Microsoft.Security", "CA2103:ReviewImperativeSecurity")]
|
||||
get
|
||||
{
|
||||
if (_dllName != null)
|
||||
{
|
||||
new System.Security.Permissions.FileIOPermission(System.Security.Permissions.FileIOPermissionAccess.PathDiscovery, _dllName).Demand();
|
||||
}
|
||||
return _dllName;
|
||||
}
|
||||
[SuppressMessage("Microsoft.Security", "CA2103:ReviewImperativeSecurity")]
|
||||
set
|
||||
{
|
||||
if (value != null)
|
||||
{
|
||||
new System.Security.Permissions.FileIOPermission(System.Security.Permissions.FileIOPermissionAccess.PathDiscovery, value).Demand();
|
||||
}
|
||||
_dllName = value;
|
||||
}
|
||||
}
|
||||
|
||||
public string FormatDescription { get; set; }
|
||||
|
||||
public string FilenameExtension { get; set; }
|
||||
|
||||
public string MimeType { get; set; }
|
||||
|
||||
public ImageCodecFlags Flags { get; set; }
|
||||
|
||||
public int Version { get; set; }
|
||||
|
||||
public byte[][] SignaturePatterns { get; set; }
|
||||
|
||||
public byte[][] SignatureMasks { get; set; }
|
||||
|
||||
public static ImageCodecInfo[] GetImageDecoders()
|
||||
{
|
||||
ImageCodecInfo[] imageCodecs;
|
||||
|
||||
var status = InteropMethods.Gdip.GdipGetImageDecodersSize(out var numDecoders, out var size);
|
||||
|
||||
if (status != InteropMethods.Gdip.Ok)
|
||||
{
|
||||
throw InteropMethods.Gdip.StatusException(status);
|
||||
}
|
||||
|
||||
var memory = Marshal.AllocHGlobal(size);
|
||||
|
||||
try
|
||||
{
|
||||
status = InteropMethods.Gdip.GdipGetImageDecoders(numDecoders, size, memory);
|
||||
|
||||
if (status != InteropMethods.Gdip.Ok)
|
||||
{
|
||||
throw InteropMethods.Gdip.StatusException(status);
|
||||
}
|
||||
|
||||
imageCodecs = ConvertFromMemory(memory, numDecoders);
|
||||
}
|
||||
finally
|
||||
{
|
||||
Marshal.FreeHGlobal(memory);
|
||||
}
|
||||
|
||||
return imageCodecs;
|
||||
}
|
||||
|
||||
public static ImageCodecInfo[] GetImageEncoders()
|
||||
{
|
||||
ImageCodecInfo[] imageCodecs;
|
||||
|
||||
var status = InteropMethods.Gdip.GdipGetImageEncodersSize(out var numEncoders, out var size);
|
||||
|
||||
if (status != InteropMethods.Gdip.Ok)
|
||||
{
|
||||
throw InteropMethods.Gdip.StatusException(status);
|
||||
}
|
||||
|
||||
var memory = Marshal.AllocHGlobal(size);
|
||||
|
||||
try
|
||||
{
|
||||
status = InteropMethods.Gdip.GdipGetImageEncoders(numEncoders, size, memory);
|
||||
|
||||
if (status != InteropMethods.Gdip.Ok)
|
||||
{
|
||||
throw InteropMethods.Gdip.StatusException(status);
|
||||
}
|
||||
|
||||
imageCodecs = ConvertFromMemory(memory, numEncoders);
|
||||
}
|
||||
finally
|
||||
{
|
||||
Marshal.FreeHGlobal(memory);
|
||||
}
|
||||
|
||||
return imageCodecs;
|
||||
}
|
||||
|
||||
public static ImageCodecInfo[] ConvertFromMemory(IntPtr memoryStart, int numCodecs)
|
||||
{
|
||||
var codecs = new ImageCodecInfo[numCodecs];
|
||||
|
||||
int index;
|
||||
|
||||
for (index = 0; index < numCodecs; index++)
|
||||
{
|
||||
var curcodec = (IntPtr)((long)memoryStart + Marshal.SizeOf(typeof(InteropValues.ImageCodecInfoPrivate)) * index);
|
||||
var codecp = new InteropValues.ImageCodecInfoPrivate();
|
||||
InteropMethods.PtrToStructure(curcodec, codecp);
|
||||
|
||||
codecs[index] = new ImageCodecInfo
|
||||
{
|
||||
Clsid = codecp.Clsid,
|
||||
FormatID = codecp.FormatID,
|
||||
CodecName = Marshal.PtrToStringUni(codecp.CodecName),
|
||||
DllName = Marshal.PtrToStringUni(codecp.DllName),
|
||||
FormatDescription = Marshal.PtrToStringUni(codecp.FormatDescription),
|
||||
FilenameExtension = Marshal.PtrToStringUni(codecp.FilenameExtension),
|
||||
MimeType = Marshal.PtrToStringUni(codecp.MimeType),
|
||||
Flags = (ImageCodecFlags) codecp.Flags,
|
||||
Version = codecp.Version,
|
||||
SignaturePatterns = new byte[codecp.SigCount][],
|
||||
SignatureMasks = new byte[codecp.SigCount][]
|
||||
};
|
||||
|
||||
for (var j = 0; j < codecp.SigCount; j++)
|
||||
{
|
||||
codecs[index].SignaturePatterns[j] = new byte[codecp.SigSize];
|
||||
codecs[index].SignatureMasks[j] = new byte[codecp.SigSize];
|
||||
|
||||
Marshal.Copy((IntPtr)((long)codecp.SigMask + j * codecp.SigSize), codecs[index].SignatureMasks[j], 0, codecp.SigSize);
|
||||
Marshal.Copy((IntPtr)((long)codecp.SigPattern + j * codecp.SigSize), codecs[index].SignaturePatterns[j], 0, codecp.SigSize);
|
||||
}
|
||||
}
|
||||
|
||||
return codecs;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -51,6 +51,7 @@
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Data\Enum\DrawerShowMode.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Data\Enum\HatchStyle.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Data\Enum\HitMode.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Data\Enum\ImageCodecFlags.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Data\Enum\ShowAnimation.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Data\Enum\NotifyIconInfoType.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Data\Enum\StrokePosition.cs" />
|
||||
@@ -61,6 +62,7 @@
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Data\GlowWindow\GlowDrawingContext.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Data\GlowWindow\GlowEdge.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Data\HwndWrapper.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Data\ImageCodecInfo.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Interactivity\Commands\CloseWindowCommand.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Interactivity\Commands\OpenLinkCommand.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Interactivity\Commands\StartScreenshotCommand.cs" />
|
||||
@@ -317,7 +319,6 @@
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Tools\Helper\ConfigHelper.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Tools\Helper\DesignerHelper.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Tools\Helper\DpiHelper.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Tools\Helper\ExternDllHelper.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Tools\Helper\IconHelper.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Tools\Helper\ResourceHelper.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Tools\Helper\ScreenHelper.cs" />
|
||||
|
||||
@@ -1,362 +0,0 @@
|
||||
using System;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.IO;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.ConstrainedExecution;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Runtime.Versioning;
|
||||
using System.Security.Permissions;
|
||||
using System.Threading;
|
||||
|
||||
namespace HandyControl.Tools
|
||||
{
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
internal class ExternDllHelper
|
||||
{
|
||||
private const string Gdi32 = "gdi32.dll";
|
||||
|
||||
private const string User32 = "user32.dll";
|
||||
|
||||
public const int E_FAIL = unchecked((int) 0x80004005);
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal struct WINCOMPATTRDATA
|
||||
{
|
||||
public WINDOWCOMPOSITIONATTRIB Attribute;
|
||||
public IntPtr Data;
|
||||
public int DataSize;
|
||||
}
|
||||
|
||||
internal enum WINDOWCOMPOSITIONATTRIB
|
||||
{
|
||||
WCA_ACCENT_POLICY = 19
|
||||
}
|
||||
|
||||
internal enum ACCENTSTATE
|
||||
{
|
||||
ACCENT_DISABLED = 0,
|
||||
ACCENT_ENABLE_GRADIENT = 1,
|
||||
ACCENT_ENABLE_TRANSPARENTGRADIENT = 2,
|
||||
ACCENT_ENABLE_BLURBEHIND = 3,
|
||||
ACCENT_ENABLE_ACRYLICBLURBEHIND = 4,
|
||||
ACCENT_INVALID_STATE = 5
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal struct ACCENTPOLICY
|
||||
{
|
||||
public ACCENTSTATE AccentState;
|
||||
public int AccentFlags;
|
||||
public uint GradientColor;
|
||||
public int AnimationId;
|
||||
}
|
||||
|
||||
[DllImport(User32)]
|
||||
internal static extern int SetWindowCompositionAttribute(IntPtr hwnd, ref WINCOMPATTRDATA data);
|
||||
|
||||
[ReflectionPermission(SecurityAction.Assert, Unrestricted = true), SecurityPermission(SecurityAction.Assert, Flags = SecurityPermissionFlag.UnmanagedCode)]
|
||||
public static object PtrToStructure(IntPtr lparam, Type cls) => Marshal.PtrToStructure(lparam, cls);
|
||||
|
||||
[DllImport(Gdi32, CharSet = CharSet.Auto, SetLastError = true)]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
public static extern bool DeleteObject(IntPtr hObject);
|
||||
|
||||
[ComImport, Guid("0000000C-0000-0000-C000-000000000046"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
|
||||
public interface IStream
|
||||
{
|
||||
int Read(
|
||||
[In]
|
||||
IntPtr buf,
|
||||
[In]
|
||||
int len);
|
||||
|
||||
int Write(
|
||||
[In]
|
||||
IntPtr buf,
|
||||
[In]
|
||||
int len);
|
||||
|
||||
[return: MarshalAs(UnmanagedType.I8)]
|
||||
long Seek(
|
||||
[In, MarshalAs(UnmanagedType.I8)]
|
||||
long dlibMove,
|
||||
[In]
|
||||
int dwOrigin);
|
||||
|
||||
void SetSize(
|
||||
[In, MarshalAs(UnmanagedType.I8)]
|
||||
long libNewSize);
|
||||
|
||||
[return: MarshalAs(UnmanagedType.I8)]
|
||||
long CopyTo(
|
||||
[In, MarshalAs(UnmanagedType.Interface)]
|
||||
IStream pstm,
|
||||
[In, MarshalAs(UnmanagedType.I8)]
|
||||
long cb,
|
||||
[Out, MarshalAs(UnmanagedType.LPArray)]
|
||||
long[] pcbRead);
|
||||
|
||||
void Commit(
|
||||
[In]
|
||||
int grfCommitFlags);
|
||||
|
||||
void Revert();
|
||||
|
||||
void LockRegion(
|
||||
[In, MarshalAs(UnmanagedType.I8)]
|
||||
long libOffset,
|
||||
[In, MarshalAs(UnmanagedType.I8)]
|
||||
long cb,
|
||||
[In]
|
||||
int dwLockType);
|
||||
|
||||
void UnlockRegion(
|
||||
[In, MarshalAs(UnmanagedType.I8)]
|
||||
long libOffset,
|
||||
[In, MarshalAs(UnmanagedType.I8)]
|
||||
long cb,
|
||||
[In]
|
||||
int dwLockType);
|
||||
|
||||
void Stat(
|
||||
[In]
|
||||
IntPtr pStatstg,
|
||||
[In]
|
||||
int grfStatFlag);
|
||||
|
||||
[return: MarshalAs(UnmanagedType.Interface)]
|
||||
IStream Clone();
|
||||
}
|
||||
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
public class StreamConsts
|
||||
{
|
||||
public const int LOCK_WRITE = 0x1;
|
||||
public const int LOCK_EXCLUSIVE = 0x2;
|
||||
public const int LOCK_ONLYONCE = 0x4;
|
||||
public const int STATFLAG_DEFAULT = 0x0;
|
||||
public const int STATFLAG_NONAME = 0x1;
|
||||
public const int STATFLAG_NOOPEN = 0x2;
|
||||
public const int STGC_DEFAULT = 0x0;
|
||||
public const int STGC_OVERWRITE = 0x1;
|
||||
public const int STGC_ONLYIFCURRENT = 0x2;
|
||||
public const int STGC_DANGEROUSLYCOMMITMERELYTODISKCACHE = 0x4;
|
||||
public const int STREAM_SEEK_SET = 0x0;
|
||||
public const int STREAM_SEEK_CUR = 0x1;
|
||||
public const int STREAM_SEEK_END = 0x2;
|
||||
}
|
||||
|
||||
internal class Gdip
|
||||
{
|
||||
private const string Gdiplus = "gdiplus.dll";
|
||||
|
||||
private const string ThreadDataSlotName = "system.drawing.threaddata";
|
||||
|
||||
private static IntPtr InitToken;
|
||||
|
||||
private static bool Initialized => InitToken != IntPtr.Zero;
|
||||
|
||||
static Gdip()
|
||||
{
|
||||
Initialize();
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
private struct StartupInput
|
||||
{
|
||||
private int GdiplusVersion;
|
||||
|
||||
private readonly IntPtr DebugEventCallback;
|
||||
|
||||
private bool SuppressBackgroundThread;
|
||||
|
||||
private bool SuppressExternalCodecs;
|
||||
|
||||
public static StartupInput GetDefault()
|
||||
{
|
||||
var result = new StartupInput
|
||||
{
|
||||
GdiplusVersion = 1,
|
||||
SuppressBackgroundThread = false,
|
||||
SuppressExternalCodecs = false
|
||||
};
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
private struct StartupOutput
|
||||
{
|
||||
private readonly IntPtr hook;
|
||||
|
||||
private readonly IntPtr unhook;
|
||||
}
|
||||
|
||||
[ResourceExposure(ResourceScope.None)]
|
||||
[ResourceConsumption(ResourceScope.AppDomain, ResourceScope.AppDomain)]
|
||||
[SuppressMessage("Microsoft.Performance", "CA1804:RemoveUnusedLocals")]
|
||||
private static void Initialize()
|
||||
{
|
||||
var input = StartupInput.GetDefault();
|
||||
|
||||
var status = GdiplusStartup(out InitToken, ref input, out _);
|
||||
|
||||
if (status != Ok)
|
||||
{
|
||||
throw StatusException(status);
|
||||
}
|
||||
|
||||
var currentDomain = AppDomain.CurrentDomain;
|
||||
currentDomain.ProcessExit += OnProcessExit;
|
||||
|
||||
if (!currentDomain.IsDefaultAppDomain())
|
||||
{
|
||||
currentDomain.DomainUnload += OnProcessExit;
|
||||
}
|
||||
}
|
||||
|
||||
[PrePrepareMethod]
|
||||
[ResourceExposure(ResourceScope.AppDomain)]
|
||||
[ResourceConsumption(ResourceScope.AppDomain)]
|
||||
private static void OnProcessExit(object sender, EventArgs e) => Shutdown();
|
||||
|
||||
[SuppressMessage("Microsoft.Reliability", "CA2001:AvoidCallingProblematicMethods")]
|
||||
[ResourceExposure(ResourceScope.AppDomain)]
|
||||
[ResourceConsumption(ResourceScope.AppDomain)]
|
||||
private static void Shutdown()
|
||||
{
|
||||
if (Initialized)
|
||||
{
|
||||
ClearThreadData();
|
||||
// unhook our shutdown handlers as we do not need to shut down more than once
|
||||
var currentDomain = AppDomain.CurrentDomain;
|
||||
currentDomain.ProcessExit -= OnProcessExit;
|
||||
if (!currentDomain.IsDefaultAppDomain())
|
||||
{
|
||||
currentDomain.DomainUnload -= OnProcessExit;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||
private static void ClearThreadData()
|
||||
{
|
||||
var slot = Thread.GetNamedDataSlot(ThreadDataSlotName);
|
||||
Thread.SetData(slot, null);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------
|
||||
// Status codes
|
||||
//----------------------------------------------------------------------------------------
|
||||
internal const int Ok = 0;
|
||||
internal const int GenericError = 1;
|
||||
internal const int InvalidParameter = 2;
|
||||
internal const int OutOfMemory = 3;
|
||||
internal const int ObjectBusy = 4;
|
||||
internal const int InsufficientBuffer = 5;
|
||||
internal const int NotImplemented = 6;
|
||||
internal const int Win32Error = 7;
|
||||
internal const int WrongState = 8;
|
||||
internal const int Aborted = 9;
|
||||
internal const int FileNotFound = 10;
|
||||
internal const int ValueOverflow = 11;
|
||||
internal const int AccessDenied = 12;
|
||||
internal const int UnknownImageFormat = 13;
|
||||
internal const int FontFamilyNotFound = 14;
|
||||
internal const int FontStyleNotFound = 15;
|
||||
internal const int NotTrueTypeFont = 16;
|
||||
internal const int UnsupportedGdiplusVersion = 17;
|
||||
internal const int GdiplusNotInitialized = 18;
|
||||
internal const int PropertyNotFound = 19;
|
||||
internal const int PropertyNotSupported = 20;
|
||||
|
||||
[DllImport(Gdiplus, SetLastError = true, ExactSpelling = true, CharSet = CharSet.Unicode)]
|
||||
[ResourceExposure(ResourceScope.None)]
|
||||
internal static extern int GdipImageGetFrameDimensionsCount(HandleRef image, out int count);
|
||||
|
||||
internal static Exception StatusException(int status)
|
||||
{
|
||||
switch (status)
|
||||
{
|
||||
case GenericError: return new ExternalException("GdiplusGenericError");
|
||||
case InvalidParameter: return new ArgumentException("GdiplusInvalidParameter");
|
||||
case OutOfMemory: return new OutOfMemoryException("GdiplusOutOfMemory");
|
||||
case ObjectBusy: return new InvalidOperationException("GdiplusObjectBusy");
|
||||
case InsufficientBuffer: return new OutOfMemoryException("GdiplusInsufficientBuffer");
|
||||
case NotImplemented: return new NotImplementedException("GdiplusNotImplemented");
|
||||
case Win32Error: return new ExternalException("GdiplusGenericError");
|
||||
case WrongState: return new InvalidOperationException("GdiplusWrongState");
|
||||
case Aborted: return new ExternalException("GdiplusAborted");
|
||||
case FileNotFound: return new FileNotFoundException("GdiplusFileNotFound");
|
||||
case ValueOverflow: return new OverflowException("GdiplusOverflow");
|
||||
case AccessDenied: return new ExternalException("GdiplusAccessDenied");
|
||||
case UnknownImageFormat: return new ArgumentException("GdiplusUnknownImageFormat");
|
||||
case PropertyNotFound: return new ArgumentException("GdiplusPropertyNotFoundError");
|
||||
case PropertyNotSupported: return new ArgumentException("GdiplusPropertyNotSupportedError");
|
||||
case FontFamilyNotFound: return new ArgumentException("GdiplusFontFamilyNotFound");
|
||||
case FontStyleNotFound: return new ArgumentException("GdiplusFontStyleNotFound");
|
||||
case NotTrueTypeFont: return new ArgumentException("GdiplusNotTrueTypeFont_NoName");
|
||||
case UnsupportedGdiplusVersion: return new ExternalException("GdiplusUnsupportedGdiplusVersion");
|
||||
case GdiplusNotInitialized: return new ExternalException("GdiplusNotInitialized");
|
||||
}
|
||||
|
||||
return new ExternalException("GdiplusUnknown");
|
||||
}
|
||||
|
||||
[DllImport(Gdiplus, SetLastError = true, ExactSpelling = true, CharSet = CharSet.Unicode)]
|
||||
[ResourceExposure(ResourceScope.None)]
|
||||
internal static extern int GdipImageGetFrameDimensionsList(HandleRef image, IntPtr buffer, int count);
|
||||
|
||||
[DllImport(Gdiplus, SetLastError = true, ExactSpelling = true, CharSet = CharSet.Unicode)]
|
||||
[ResourceExposure(ResourceScope.None)]
|
||||
internal static extern int GdipImageGetFrameCount(HandleRef image, ref Guid dimensionId, int[] count);
|
||||
|
||||
[DllImport(Gdiplus, SetLastError = true, ExactSpelling = true, CharSet = CharSet.Unicode)]
|
||||
[ResourceExposure(ResourceScope.None)]
|
||||
internal static extern int GdipGetPropertyItemSize(HandleRef image, int propid, out int size);
|
||||
|
||||
[DllImport(Gdiplus, SetLastError = true, ExactSpelling = true, CharSet = CharSet.Unicode)]
|
||||
[ResourceExposure(ResourceScope.None)]
|
||||
internal static extern int GdipGetPropertyItem(HandleRef image, int propid, int size, IntPtr buffer);
|
||||
|
||||
[DllImport(Gdiplus, SetLastError = true, ExactSpelling = true, CharSet = CharSet.Unicode)]
|
||||
[ResourceExposure(ResourceScope.Machine)]
|
||||
internal static extern int GdipCreateHBITMAPFromBitmap(HandleRef nativeBitmap, out IntPtr hbitmap, int argbBackground);
|
||||
|
||||
[DllImport(Gdiplus, SetLastError = true, ExactSpelling = true, CharSet = CharSet.Unicode)]
|
||||
[ResourceExposure(ResourceScope.None)]
|
||||
internal static extern int GdipImageSelectActiveFrame(HandleRef image, ref Guid dimensionId, int frameIndex);
|
||||
|
||||
[DllImport(Gdiplus, SetLastError = true, ExactSpelling = true, CharSet = CharSet.Unicode)]
|
||||
[ResourceExposure(ResourceScope.Machine)]
|
||||
internal static extern int GdipCreateBitmapFromFile(string filename, out IntPtr bitmap);
|
||||
|
||||
[DllImport(Gdiplus, SetLastError = true, ExactSpelling = true, CharSet = CharSet.Unicode)]
|
||||
[ResourceExposure(ResourceScope.None)]
|
||||
internal static extern int GdipImageForceValidation(HandleRef image);
|
||||
|
||||
[DllImport(Gdiplus, SetLastError = true, ExactSpelling = true, EntryPoint = "GdipDisposeImage", CharSet = CharSet.Unicode)]
|
||||
[ResourceExposure(ResourceScope.None)]
|
||||
private static extern int IntGdipDisposeImage(HandleRef image);
|
||||
|
||||
internal static int GdipDisposeImage(HandleRef image)
|
||||
{
|
||||
if (!Initialized) return Ok;
|
||||
var result = IntGdipDisposeImage(image);
|
||||
return result;
|
||||
}
|
||||
|
||||
[DllImport(Gdiplus, SetLastError = true, ExactSpelling = true, CharSet = CharSet.Unicode)]
|
||||
[ResourceExposure(ResourceScope.Process)]
|
||||
private static extern int GdiplusStartup(out IntPtr token, ref StartupInput input, out StartupOutput output);
|
||||
|
||||
[DllImport(Gdiplus, SetLastError = true, ExactSpelling = true, CharSet = CharSet.Unicode)]
|
||||
[ResourceExposure(ResourceScope.None)]
|
||||
internal static extern int GdipGetImageRawFormat(HandleRef image, ref Guid format);
|
||||
|
||||
[DllImport(Gdiplus, SetLastError = true, ExactSpelling = true, CharSet = CharSet.Unicode)]
|
||||
[ResourceExposure(ResourceScope.Machine)]
|
||||
internal static extern int GdipCreateBitmapFromStream(IStream stream, out IntPtr bitmap);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,15 +1,24 @@
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.IO;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.ConstrainedExecution;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Runtime.Versioning;
|
||||
using System.Security;
|
||||
using System.Security.Permissions;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
|
||||
namespace HandyControl.Tools.Interop
|
||||
{
|
||||
internal class InteropMethods
|
||||
{
|
||||
#region common
|
||||
|
||||
public const int E_FAIL = unchecked((int)0x80004005);
|
||||
|
||||
internal static readonly IntPtr HRGN_NONE = new IntPtr(-1);
|
||||
|
||||
[DllImport(InteropValues.ExternDll.User32, CharSet = CharSet.Auto)]
|
||||
@@ -101,7 +110,7 @@ namespace HandyControl.Tools.Interop
|
||||
[SecurityCritical]
|
||||
internal static int ReleaseDC(HandleRef hWnd, HandleRef hDC)
|
||||
{
|
||||
HandleCollector.Remove((IntPtr) hDC, CommonHandles.HDC);
|
||||
HandleCollector.Remove((IntPtr)hDC, CommonHandles.HDC);
|
||||
return IntReleaseDC(hWnd, hDC);
|
||||
}
|
||||
|
||||
@@ -280,7 +289,7 @@ namespace HandyControl.Tools.Interop
|
||||
[DllImport(InteropValues.ExternDll.User32, SetLastError = true)]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
private static extern bool GetWindowPlacement(IntPtr hwnd, InteropValues.WINDOWPLACEMENT lpwndpl);
|
||||
|
||||
|
||||
internal static InteropValues.WINDOWPLACEMENT GetWindowPlacement(IntPtr hwnd)
|
||||
{
|
||||
InteropValues.WINDOWPLACEMENT wINDOWPLACEMENT = new InteropValues.WINDOWPLACEMENT();
|
||||
@@ -298,18 +307,18 @@ namespace HandyControl.Tools.Interop
|
||||
internal static int HiWord(int value) => (short)(value >> 16);
|
||||
|
||||
internal static int LoWord(int value) => (short)(value & 65535);
|
||||
|
||||
|
||||
[DllImport(InteropValues.ExternDll.User32)]
|
||||
internal static extern IntPtr MonitorFromWindow(IntPtr handle, int flags);
|
||||
|
||||
|
||||
[DllImport(InteropValues.ExternDll.User32)]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
internal static extern bool EnumThreadWindows(uint dwThreadId, InteropValues.EnumWindowsProc lpfn, IntPtr lParam);
|
||||
|
||||
|
||||
[DllImport(InteropValues.ExternDll.Gdi32)]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
internal static extern bool DeleteDC(IntPtr hdc);
|
||||
|
||||
|
||||
[DllImport(InteropValues.ExternDll.Gdi32, SetLastError = true)]
|
||||
internal static extern IntPtr CreateCompatibleDC(IntPtr hdc);
|
||||
|
||||
@@ -321,26 +330,26 @@ namespace HandyControl.Tools.Interop
|
||||
|
||||
[DllImport(InteropValues.ExternDll.User32)]
|
||||
internal static extern IntPtr MonitorFromPoint(InteropValues.POINT pt, int flags);
|
||||
|
||||
|
||||
[DllImport(InteropValues.ExternDll.User32)]
|
||||
internal static extern IntPtr GetWindow(IntPtr hwnd, int nCmd);
|
||||
|
||||
[DllImport(InteropValues.ExternDll.User32)]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
internal static extern bool IsWindowVisible(IntPtr hwnd);
|
||||
|
||||
|
||||
[DllImport(InteropValues.ExternDll.User32)]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
internal static extern bool IsIconic(IntPtr hwnd);
|
||||
|
||||
|
||||
[DllImport(InteropValues.ExternDll.User32)]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
internal static extern bool IsZoomed(IntPtr hwnd);
|
||||
|
||||
|
||||
[DllImport(InteropValues.ExternDll.User32, CharSet = CharSet.Auto, ExactSpelling = true)]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
internal static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int x, int y, int cx, int cy, int flags);
|
||||
|
||||
|
||||
internal static System.Windows.Point GetCursorPos()
|
||||
{
|
||||
var result = default(System.Windows.Point);
|
||||
@@ -365,19 +374,19 @@ namespace HandyControl.Tools.Interop
|
||||
}
|
||||
return SetWindowLongPtr64(hWnd, nIndex, dwNewLong);
|
||||
}
|
||||
|
||||
|
||||
[DllImport(InteropValues.ExternDll.User32, CharSet = CharSet.Auto, EntryPoint = "SetWindowLong")]
|
||||
internal static extern IntPtr SetWindowLongPtr32(IntPtr hWnd, int nIndex, IntPtr dwNewLong);
|
||||
|
||||
|
||||
[DllImport(InteropValues.ExternDll.User32, CharSet = CharSet.Auto, EntryPoint = "SetWindowLongPtr")]
|
||||
internal static extern IntPtr SetWindowLongPtr64(IntPtr hWnd, int nIndex, IntPtr dwNewLong);
|
||||
|
||||
[DllImport(InteropValues.ExternDll.User32, CharSet = CharSet.Unicode)]
|
||||
private static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);
|
||||
|
||||
|
||||
[DllImport(InteropValues.ExternDll.User32, CharSet = CharSet.Unicode)]
|
||||
private static extern IntPtr SetWindowLongPtr(IntPtr hWnd, int nIndex, IntPtr dwNewLong);
|
||||
|
||||
|
||||
internal static IntPtr SetWindowLongPtr(IntPtr hWnd, InteropValues.GWLP nIndex, IntPtr dwNewLong)
|
||||
{
|
||||
if (IntPtr.Size == 8)
|
||||
@@ -386,7 +395,7 @@ namespace HandyControl.Tools.Interop
|
||||
}
|
||||
return new IntPtr(SetWindowLong(hWnd, (int)nIndex, dwNewLong.ToInt32()));
|
||||
}
|
||||
|
||||
|
||||
internal static int SetWindowLong(IntPtr hWnd, InteropValues.GWL nIndex, int dwNewLong) => SetWindowLong(hWnd, (int)nIndex, dwNewLong);
|
||||
|
||||
[DllImport(InteropValues.ExternDll.User32, CharSet = CharSet.Unicode)]
|
||||
@@ -401,37 +410,37 @@ namespace HandyControl.Tools.Interop
|
||||
[DllImport(InteropValues.ExternDll.User32)]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
internal static extern bool DestroyWindow(IntPtr hwnd);
|
||||
|
||||
|
||||
[DllImport(InteropValues.ExternDll.User32)]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
internal static extern bool UnregisterClass(IntPtr classAtom, IntPtr hInstance);
|
||||
|
||||
|
||||
[DllImport(InteropValues.ExternDll.User32)]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
internal static extern bool UpdateLayeredWindow(IntPtr hwnd, IntPtr hdcDest, ref InteropValues.POINT pptDest, ref InteropValues.SIZE psize, IntPtr hdcSrc, ref InteropValues.POINT pptSrc, uint crKey, [In] ref InteropValues.BLENDFUNCTION pblend, uint dwFlags);
|
||||
|
||||
|
||||
[DllImport(InteropValues.ExternDll.User32)]
|
||||
internal static extern bool RedrawWindow(IntPtr hWnd, IntPtr lprcUpdate, IntPtr hrgnUpdate, InteropValues.RedrawWindowFlags flags);
|
||||
|
||||
[DllImport(InteropValues.ExternDll.User32)]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
internal static extern bool EnumDisplayMonitors(IntPtr hdc, IntPtr lprcClip, InteropValues.EnumMonitorsDelegate lpfnEnum, IntPtr dwData);
|
||||
|
||||
|
||||
[DllImport(InteropValues.ExternDll.User32)]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
internal static extern bool IntersectRect(out InteropValues.RECT lprcDst, [In] ref InteropValues.RECT lprcSrc1, [In] ref InteropValues.RECT lprcSrc2);
|
||||
|
||||
|
||||
[DllImport(InteropValues.ExternDll.User32)]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
internal static extern bool GetMonitorInfo(IntPtr hMonitor, ref InteropValues.MONITORINFO monitorInfo);
|
||||
|
||||
|
||||
[DllImport(InteropValues.ExternDll.Gdi32, SetLastError = true)]
|
||||
internal static extern IntPtr CreateDIBSection(IntPtr hdc, ref InteropValues.BITMAPINFO pbmi, uint iUsage, out IntPtr ppvBits, IntPtr hSection, uint dwOffset);
|
||||
|
||||
|
||||
[DllImport(InteropValues.ExternDll.MsImg)]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
internal static extern bool AlphaBlend(IntPtr hdcDest, int xoriginDest, int yoriginDest, int wDest, int hDest, IntPtr hdcSrc, int xoriginSrc, int yoriginSrc, int wSrc, int hSrc, InteropValues.BLENDFUNCTION pfn);
|
||||
|
||||
|
||||
internal static int GET_SC_WPARAM(IntPtr wParam) => (int)wParam & 65520;
|
||||
|
||||
[DllImport(InteropValues.ExternDll.User32)]
|
||||
@@ -446,5 +455,251 @@ namespace HandyControl.Tools.Interop
|
||||
[DllImport(InteropValues.ExternDll.User32)]
|
||||
[ResourceExposure(ResourceScope.None)]
|
||||
internal static extern bool EnableWindow(IntPtr hWnd, bool enable);
|
||||
|
||||
[ReflectionPermission(SecurityAction.Assert, Unrestricted = true), SecurityPermission(SecurityAction.Assert, Flags = SecurityPermissionFlag.UnmanagedCode)]
|
||||
internal static object PtrToStructure(IntPtr lparam, Type cls) => Marshal.PtrToStructure(lparam, cls);
|
||||
|
||||
[ReflectionPermission(SecurityAction.Assert, Unrestricted = true),
|
||||
SecurityPermission(SecurityAction.Assert, Flags = SecurityPermissionFlag.UnmanagedCode)]
|
||||
public static void PtrToStructure(IntPtr lparam, object data) => Marshal.PtrToStructure(lparam, data);
|
||||
|
||||
#endregion
|
||||
|
||||
internal class Gdip
|
||||
{
|
||||
private const string ThreadDataSlotName = "system.drawing.threaddata";
|
||||
|
||||
private static IntPtr InitToken;
|
||||
|
||||
private static bool Initialized => InitToken != IntPtr.Zero;
|
||||
|
||||
internal const int
|
||||
Ok = 0,
|
||||
GenericError = 1,
|
||||
InvalidParameter = 2,
|
||||
OutOfMemory = 3,
|
||||
ObjectBusy = 4,
|
||||
InsufficientBuffer = 5,
|
||||
NotImplemented = 6,
|
||||
Win32Error = 7,
|
||||
WrongState = 8,
|
||||
Aborted = 9,
|
||||
FileNotFound = 10,
|
||||
ValueOverflow = 11,
|
||||
AccessDenied = 12,
|
||||
UnknownImageFormat = 13,
|
||||
FontFamilyNotFound = 14,
|
||||
FontStyleNotFound = 15,
|
||||
NotTrueTypeFont = 16,
|
||||
UnsupportedGdiplusVersion = 17,
|
||||
GdiplusNotInitialized = 18,
|
||||
PropertyNotFound = 19,
|
||||
PropertyNotSupported = 20,
|
||||
E_UNEXPECTED = unchecked((int)0x8000FFFF);
|
||||
|
||||
static Gdip()
|
||||
{
|
||||
Initialize();
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
private struct StartupInput
|
||||
{
|
||||
private int GdiplusVersion;
|
||||
|
||||
private readonly IntPtr DebugEventCallback;
|
||||
|
||||
private bool SuppressBackgroundThread;
|
||||
|
||||
private bool SuppressExternalCodecs;
|
||||
|
||||
public static StartupInput GetDefault()
|
||||
{
|
||||
var result = new StartupInput
|
||||
{
|
||||
GdiplusVersion = 1,
|
||||
SuppressBackgroundThread = false,
|
||||
SuppressExternalCodecs = false
|
||||
};
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
private struct StartupOutput
|
||||
{
|
||||
private readonly IntPtr hook;
|
||||
|
||||
private readonly IntPtr unhook;
|
||||
}
|
||||
|
||||
[ResourceExposure(ResourceScope.None)]
|
||||
[ResourceConsumption(ResourceScope.AppDomain, ResourceScope.AppDomain)]
|
||||
[SuppressMessage("Microsoft.Performance", "CA1804:RemoveUnusedLocals")]
|
||||
private static void Initialize()
|
||||
{
|
||||
var input = StartupInput.GetDefault();
|
||||
|
||||
var status = GdiplusStartup(out InitToken, ref input, out _);
|
||||
|
||||
if (status != Ok)
|
||||
{
|
||||
throw StatusException(status);
|
||||
}
|
||||
|
||||
var currentDomain = AppDomain.CurrentDomain;
|
||||
currentDomain.ProcessExit += OnProcessExit;
|
||||
|
||||
if (!currentDomain.IsDefaultAppDomain())
|
||||
{
|
||||
currentDomain.DomainUnload += OnProcessExit;
|
||||
}
|
||||
}
|
||||
|
||||
[PrePrepareMethod]
|
||||
[ResourceExposure(ResourceScope.AppDomain)]
|
||||
[ResourceConsumption(ResourceScope.AppDomain)]
|
||||
private static void OnProcessExit(object sender, EventArgs e) => Shutdown();
|
||||
|
||||
[SuppressMessage("Microsoft.Reliability", "CA2001:AvoidCallingProblematicMethods")]
|
||||
[ResourceExposure(ResourceScope.AppDomain)]
|
||||
[ResourceConsumption(ResourceScope.AppDomain)]
|
||||
private static void Shutdown()
|
||||
{
|
||||
if (Initialized)
|
||||
{
|
||||
ClearThreadData();
|
||||
// unhook our shutdown handlers as we do not need to shut down more than once
|
||||
var currentDomain = AppDomain.CurrentDomain;
|
||||
currentDomain.ProcessExit -= OnProcessExit;
|
||||
if (!currentDomain.IsDefaultAppDomain())
|
||||
{
|
||||
currentDomain.DomainUnload -= OnProcessExit;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||
private static void ClearThreadData()
|
||||
{
|
||||
var slot = Thread.GetNamedDataSlot(ThreadDataSlotName);
|
||||
Thread.SetData(slot, null);
|
||||
}
|
||||
|
||||
[DllImport(InteropValues.ExternDll.GdiPlus, SetLastError = true, ExactSpelling = true, CharSet = CharSet.Unicode)]
|
||||
[ResourceExposure(ResourceScope.None)]
|
||||
internal static extern int GdipImageGetFrameDimensionsCount(HandleRef image, out int count);
|
||||
|
||||
internal static Exception StatusException(int status)
|
||||
{
|
||||
switch (status)
|
||||
{
|
||||
case GenericError: return new ExternalException("GdiplusGenericError");
|
||||
case InvalidParameter: return new ArgumentException("GdiplusInvalidParameter");
|
||||
case OutOfMemory: return new OutOfMemoryException("GdiplusOutOfMemory");
|
||||
case ObjectBusy: return new InvalidOperationException("GdiplusObjectBusy");
|
||||
case InsufficientBuffer: return new OutOfMemoryException("GdiplusInsufficientBuffer");
|
||||
case NotImplemented: return new NotImplementedException("GdiplusNotImplemented");
|
||||
case Win32Error: return new ExternalException("GdiplusGenericError");
|
||||
case WrongState: return new InvalidOperationException("GdiplusWrongState");
|
||||
case Aborted: return new ExternalException("GdiplusAborted");
|
||||
case FileNotFound: return new FileNotFoundException("GdiplusFileNotFound");
|
||||
case ValueOverflow: return new OverflowException("GdiplusOverflow");
|
||||
case AccessDenied: return new ExternalException("GdiplusAccessDenied");
|
||||
case UnknownImageFormat: return new ArgumentException("GdiplusUnknownImageFormat");
|
||||
case PropertyNotFound: return new ArgumentException("GdiplusPropertyNotFoundError");
|
||||
case PropertyNotSupported: return new ArgumentException("GdiplusPropertyNotSupportedError");
|
||||
case FontFamilyNotFound: return new ArgumentException("GdiplusFontFamilyNotFound");
|
||||
case FontStyleNotFound: return new ArgumentException("GdiplusFontStyleNotFound");
|
||||
case NotTrueTypeFont: return new ArgumentException("GdiplusNotTrueTypeFont_NoName");
|
||||
case UnsupportedGdiplusVersion: return new ExternalException("GdiplusUnsupportedGdiplusVersion");
|
||||
case GdiplusNotInitialized: return new ExternalException("GdiplusNotInitialized");
|
||||
}
|
||||
|
||||
return new ExternalException("GdiplusUnknown");
|
||||
}
|
||||
|
||||
[DllImport(InteropValues.ExternDll.GdiPlus, SetLastError = true, ExactSpelling = true, CharSet = CharSet.Unicode)]
|
||||
[ResourceExposure(ResourceScope.None)]
|
||||
internal static extern int GdipImageGetFrameDimensionsList(HandleRef image, IntPtr buffer, int count);
|
||||
|
||||
[DllImport(InteropValues.ExternDll.GdiPlus, SetLastError = true, ExactSpelling = true, CharSet = CharSet.Unicode)]
|
||||
[ResourceExposure(ResourceScope.None)]
|
||||
internal static extern int GdipImageGetFrameCount(HandleRef image, ref Guid dimensionId, int[] count);
|
||||
|
||||
[DllImport(InteropValues.ExternDll.GdiPlus, SetLastError = true, ExactSpelling = true, CharSet = CharSet.Unicode)]
|
||||
[ResourceExposure(ResourceScope.None)]
|
||||
internal static extern int GdipGetPropertyItemSize(HandleRef image, int propid, out int size);
|
||||
|
||||
[DllImport(InteropValues.ExternDll.GdiPlus, SetLastError = true, ExactSpelling = true, CharSet = CharSet.Unicode)]
|
||||
[ResourceExposure(ResourceScope.None)]
|
||||
internal static extern int GdipGetPropertyItem(HandleRef image, int propid, int size, IntPtr buffer);
|
||||
|
||||
[DllImport(InteropValues.ExternDll.GdiPlus, SetLastError = true, ExactSpelling = true, CharSet = CharSet.Unicode)]
|
||||
[ResourceExposure(ResourceScope.Machine)]
|
||||
internal static extern int GdipCreateHBITMAPFromBitmap(HandleRef nativeBitmap, out IntPtr hbitmap, int argbBackground);
|
||||
|
||||
[DllImport(InteropValues.ExternDll.GdiPlus, SetLastError = true, ExactSpelling = true, CharSet = CharSet.Unicode)]
|
||||
[ResourceExposure(ResourceScope.None)]
|
||||
internal static extern int GdipImageSelectActiveFrame(HandleRef image, ref Guid dimensionId, int frameIndex);
|
||||
|
||||
[DllImport(InteropValues.ExternDll.GdiPlus, SetLastError = true, ExactSpelling = true, CharSet = CharSet.Unicode)]
|
||||
[ResourceExposure(ResourceScope.Machine)]
|
||||
internal static extern int GdipCreateBitmapFromFile(string filename, out IntPtr bitmap);
|
||||
|
||||
[DllImport(InteropValues.ExternDll.GdiPlus, SetLastError = true, ExactSpelling = true, CharSet = CharSet.Unicode)]
|
||||
[ResourceExposure(ResourceScope.None)]
|
||||
internal static extern int GdipImageForceValidation(HandleRef image);
|
||||
|
||||
[DllImport(InteropValues.ExternDll.GdiPlus, SetLastError = true, ExactSpelling = true, EntryPoint = "GdipDisposeImage", CharSet = CharSet.Unicode)]
|
||||
[ResourceExposure(ResourceScope.None)]
|
||||
private static extern int IntGdipDisposeImage(HandleRef image);
|
||||
|
||||
internal static int GdipDisposeImage(HandleRef image)
|
||||
{
|
||||
if (!Initialized) return Ok;
|
||||
var result = IntGdipDisposeImage(image);
|
||||
return result;
|
||||
}
|
||||
|
||||
[DllImport(InteropValues.ExternDll.GdiPlus, SetLastError = true, ExactSpelling = true, CharSet = CharSet.Unicode)]
|
||||
[ResourceExposure(ResourceScope.Process)]
|
||||
private static extern int GdiplusStartup(out IntPtr token, ref StartupInput input, out StartupOutput output);
|
||||
|
||||
[DllImport(InteropValues.ExternDll.GdiPlus, SetLastError = true, ExactSpelling = true, CharSet = CharSet.Unicode)]
|
||||
[ResourceExposure(ResourceScope.None)]
|
||||
internal static extern int GdipGetImageRawFormat(HandleRef image, ref Guid format);
|
||||
|
||||
[DllImport(InteropValues.ExternDll.User32)]
|
||||
internal static extern int SetWindowCompositionAttribute(IntPtr hwnd, ref InteropValues.WINCOMPATTRDATA data);
|
||||
|
||||
[DllImport(InteropValues.ExternDll.GdiPlus, SetLastError = true, ExactSpelling = true, CharSet = CharSet.Unicode)]
|
||||
[ResourceExposure(ResourceScope.Machine)]
|
||||
internal static extern int GdipCreateBitmapFromStream(InteropValues.IStream stream, out IntPtr bitmap);
|
||||
|
||||
[DllImport(InteropValues.ExternDll.GdiPlus, SetLastError = true, ExactSpelling = true, CharSet = CharSet.Unicode)]
|
||||
[ResourceExposure(ResourceScope.Machine)]
|
||||
internal static extern int GdipCreateBitmapFromHBITMAP(HandleRef hbitmap, HandleRef hpalette, out IntPtr bitmap);
|
||||
|
||||
[DllImport(InteropValues.ExternDll.GdiPlus, SetLastError = true, ExactSpelling = true, CharSet = CharSet.Unicode)]
|
||||
[ResourceExposure(ResourceScope.None)]
|
||||
internal static extern int GdipGetImageEncodersSize(out int numEncoders, out int size);
|
||||
|
||||
[DllImport(InteropValues.ExternDll.GdiPlus, SetLastError = true, ExactSpelling = true, CharSet = CharSet.Unicode)]
|
||||
[ResourceExposure(ResourceScope.None)]
|
||||
internal static extern int GdipGetImageDecodersSize(out int numDecoders, out int size);
|
||||
|
||||
[DllImport(InteropValues.ExternDll.GdiPlus, SetLastError = true, ExactSpelling = true, CharSet = CharSet.Unicode)]
|
||||
[ResourceExposure(ResourceScope.None)]
|
||||
internal static extern int GdipGetImageDecoders(int numDecoders, int size, IntPtr decoders);
|
||||
|
||||
[DllImport(InteropValues.ExternDll.GdiPlus, SetLastError = true, ExactSpelling = true, CharSet = CharSet.Unicode)]
|
||||
[ResourceExposure(ResourceScope.None)]
|
||||
internal static extern int GdipGetImageEncoders(int numEncoders, int size, IntPtr encoders);
|
||||
|
||||
[DllImport(InteropValues.ExternDll.GdiPlus, SetLastError = true, ExactSpelling = true, CharSet = CharSet.Unicode)]
|
||||
[ResourceExposure(ResourceScope.None)]
|
||||
internal static extern int GdipSaveImageToStream(HandleRef image, InteropValues.IStream stream, ref Guid classId, HandleRef encoderParams);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,6 @@
|
||||
using System;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Security;
|
||||
using System.Windows;
|
||||
@@ -12,6 +14,7 @@ namespace HandyControl.Tools.Interop
|
||||
public const string
|
||||
User32 = "user32.dll",
|
||||
Gdi32 = "gdi32.dll",
|
||||
GdiPlus = "gdiplus.dll",
|
||||
Kernel32 = "kernel32.dll",
|
||||
Shell32 = "shell32.dll",
|
||||
MsImg = "msimg32.dll";
|
||||
@@ -31,6 +34,7 @@ namespace HandyControl.Tools.Interop
|
||||
PLANES = 14,
|
||||
BI_RGB = 0,
|
||||
DIB_RGB_COLORS = 0,
|
||||
E_FAIL = unchecked((int)0x80004005),
|
||||
NIF_MESSAGE = 0x00000001,
|
||||
NIF_ICON = 0x00000002,
|
||||
NIF_TIP = 0x00000004,
|
||||
@@ -659,5 +663,275 @@ namespace HandyControl.Tools.Interop
|
||||
public BitmapHandle hbmMask = null;
|
||||
public BitmapHandle hbmColor = null;
|
||||
}
|
||||
|
||||
internal enum WINDOWCOMPOSITIONATTRIB
|
||||
{
|
||||
WCA_ACCENT_POLICY = 19
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal struct WINCOMPATTRDATA
|
||||
{
|
||||
public WINDOWCOMPOSITIONATTRIB Attribute;
|
||||
public IntPtr Data;
|
||||
public int DataSize;
|
||||
}
|
||||
|
||||
internal enum ACCENTSTATE
|
||||
{
|
||||
ACCENT_DISABLED = 0,
|
||||
ACCENT_ENABLE_GRADIENT = 1,
|
||||
ACCENT_ENABLE_TRANSPARENTGRADIENT = 2,
|
||||
ACCENT_ENABLE_BLURBEHIND = 3,
|
||||
ACCENT_ENABLE_ACRYLICBLURBEHIND = 4,
|
||||
ACCENT_INVALID_STATE = 5
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal struct ACCENTPOLICY
|
||||
{
|
||||
public ACCENTSTATE AccentState;
|
||||
public int AccentFlags;
|
||||
public uint GradientColor;
|
||||
public int AnimationId;
|
||||
}
|
||||
|
||||
[ComImport, Guid("0000000C-0000-0000-C000-000000000046"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
|
||||
internal interface IStream
|
||||
{
|
||||
int Read([In] IntPtr buf, [In] int len);
|
||||
|
||||
int Write([In] IntPtr buf, [In] int len);
|
||||
|
||||
[return: MarshalAs(UnmanagedType.I8)]
|
||||
long Seek([In, MarshalAs(UnmanagedType.I8)] long dlibMove, [In] int dwOrigin);
|
||||
|
||||
void SetSize([In, MarshalAs(UnmanagedType.I8)] long libNewSize);
|
||||
|
||||
[return: MarshalAs(UnmanagedType.I8)]
|
||||
long CopyTo([In, MarshalAs(UnmanagedType.Interface)] IStream pstm, [In, MarshalAs(UnmanagedType.I8)] long cb, [Out, MarshalAs(UnmanagedType.LPArray)] long[] pcbRead);
|
||||
|
||||
void Commit([In]int grfCommitFlags);
|
||||
|
||||
void Revert();
|
||||
|
||||
void LockRegion([In, MarshalAs(UnmanagedType.I8)]long libOffset, [In, MarshalAs(UnmanagedType.I8)] long cb, [In] int dwLockType);
|
||||
|
||||
void UnlockRegion([In, MarshalAs(UnmanagedType.I8)] long libOffset, [In, MarshalAs(UnmanagedType.I8)] long cb, [In] int dwLockType);
|
||||
|
||||
void Stat([In] IntPtr pStatstg, [In] int grfStatFlag);
|
||||
|
||||
[return: MarshalAs(UnmanagedType.Interface)]
|
||||
IStream Clone();
|
||||
}
|
||||
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
internal class StreamConsts
|
||||
{
|
||||
public const int LOCK_WRITE = 0x1;
|
||||
public const int LOCK_EXCLUSIVE = 0x2;
|
||||
public const int LOCK_ONLYONCE = 0x4;
|
||||
public const int STATFLAG_DEFAULT = 0x0;
|
||||
public const int STATFLAG_NONAME = 0x1;
|
||||
public const int STATFLAG_NOOPEN = 0x2;
|
||||
public const int STGC_DEFAULT = 0x0;
|
||||
public const int STGC_OVERWRITE = 0x1;
|
||||
public const int STGC_ONLYIFCURRENT = 0x2;
|
||||
public const int STGC_DANGEROUSLYCOMMITMERELYTODISKCACHE = 0x4;
|
||||
public const int STREAM_SEEK_SET = 0x0;
|
||||
public const int STREAM_SEEK_CUR = 0x1;
|
||||
public const int STREAM_SEEK_END = 0x2;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 8)]
|
||||
internal class ImageCodecInfoPrivate
|
||||
{
|
||||
[MarshalAs(UnmanagedType.Struct)]
|
||||
public Guid Clsid;
|
||||
[MarshalAs(UnmanagedType.Struct)]
|
||||
public Guid FormatID;
|
||||
|
||||
public IntPtr CodecName = IntPtr.Zero;
|
||||
public IntPtr DllName = IntPtr.Zero;
|
||||
public IntPtr FormatDescription = IntPtr.Zero;
|
||||
public IntPtr FilenameExtension = IntPtr.Zero;
|
||||
public IntPtr MimeType = IntPtr.Zero;
|
||||
|
||||
public int Flags;
|
||||
public int Version;
|
||||
public int SigCount;
|
||||
public int SigSize;
|
||||
|
||||
public IntPtr SigPattern = IntPtr.Zero;
|
||||
public IntPtr SigMask = IntPtr.Zero;
|
||||
}
|
||||
|
||||
internal class ComStreamFromDataStream : IStream
|
||||
{
|
||||
protected Stream DataStream;
|
||||
|
||||
// to support seeking ahead of the stream length...
|
||||
private long _virtualPosition = -1;
|
||||
|
||||
internal ComStreamFromDataStream(Stream dataStream)
|
||||
{
|
||||
this.DataStream = dataStream ?? throw new ArgumentNullException(nameof(dataStream));
|
||||
}
|
||||
|
||||
private void ActualizeVirtualPosition()
|
||||
{
|
||||
if (_virtualPosition == -1) return;
|
||||
|
||||
if (_virtualPosition > DataStream.Length)
|
||||
DataStream.SetLength(_virtualPosition);
|
||||
|
||||
DataStream.Position = _virtualPosition;
|
||||
|
||||
_virtualPosition = -1;
|
||||
}
|
||||
|
||||
public virtual IStream Clone()
|
||||
{
|
||||
NotImplemented();
|
||||
return null;
|
||||
}
|
||||
|
||||
public virtual void Commit(int grfCommitFlags)
|
||||
{
|
||||
DataStream.Flush();
|
||||
ActualizeVirtualPosition();
|
||||
}
|
||||
|
||||
public virtual long CopyTo(IStream pstm, long cb, long[] pcbRead)
|
||||
{
|
||||
const int bufsize = 4096; // one page
|
||||
var buffer = Marshal.AllocHGlobal(bufsize);
|
||||
if (buffer == IntPtr.Zero) throw new OutOfMemoryException();
|
||||
long written = 0;
|
||||
|
||||
try
|
||||
{
|
||||
while (written < cb)
|
||||
{
|
||||
var toRead = bufsize;
|
||||
if (written + toRead > cb) toRead = (int)(cb - written);
|
||||
var read = Read(buffer, toRead);
|
||||
if (read == 0) break;
|
||||
if (pstm.Write(buffer, read) != read)
|
||||
{
|
||||
throw EFail("Wrote an incorrect number of bytes");
|
||||
}
|
||||
written += read;
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
Marshal.FreeHGlobal(buffer);
|
||||
}
|
||||
if (pcbRead != null && pcbRead.Length > 0)
|
||||
{
|
||||
pcbRead[0] = written;
|
||||
}
|
||||
|
||||
return written;
|
||||
}
|
||||
|
||||
public virtual Stream GetDataStream() => DataStream;
|
||||
|
||||
public virtual void LockRegion(long libOffset, long cb, int dwLockType)
|
||||
{
|
||||
}
|
||||
|
||||
protected static ExternalException EFail(string msg) => throw new ExternalException(msg, E_FAIL);
|
||||
|
||||
protected static void NotImplemented() => throw new NotImplementedException();
|
||||
|
||||
public virtual int Read(IntPtr buf, int length)
|
||||
{
|
||||
var buffer = new byte[length];
|
||||
var count = Read(buffer, length);
|
||||
Marshal.Copy(buffer, 0, buf, length);
|
||||
return count;
|
||||
}
|
||||
|
||||
public virtual int Read(byte[] buffer, int length)
|
||||
{
|
||||
ActualizeVirtualPosition();
|
||||
return DataStream.Read(buffer, 0, length);
|
||||
}
|
||||
|
||||
public virtual void Revert() => NotImplemented();
|
||||
|
||||
public virtual long Seek(long offset, int origin)
|
||||
{
|
||||
var pos = _virtualPosition;
|
||||
if (_virtualPosition == -1)
|
||||
{
|
||||
pos = DataStream.Position;
|
||||
}
|
||||
var len = DataStream.Length;
|
||||
|
||||
switch (origin)
|
||||
{
|
||||
case StreamConsts.STREAM_SEEK_SET:
|
||||
if (offset <= len)
|
||||
{
|
||||
DataStream.Position = offset;
|
||||
_virtualPosition = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
_virtualPosition = offset;
|
||||
}
|
||||
break;
|
||||
case StreamConsts.STREAM_SEEK_END:
|
||||
if (offset <= 0)
|
||||
{
|
||||
DataStream.Position = len + offset;
|
||||
_virtualPosition = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
_virtualPosition = len + offset;
|
||||
}
|
||||
break;
|
||||
case StreamConsts.STREAM_SEEK_CUR:
|
||||
if (offset + pos <= len)
|
||||
{
|
||||
DataStream.Position = pos + offset;
|
||||
_virtualPosition = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
_virtualPosition = offset + pos;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return _virtualPosition != -1 ? _virtualPosition : DataStream.Position;
|
||||
}
|
||||
|
||||
public virtual void SetSize(long value) => DataStream.SetLength(value);
|
||||
|
||||
public virtual void Stat(IntPtr pstatstg, int grfStatFlag) => NotImplemented();
|
||||
|
||||
public virtual void UnlockRegion(long libOffset, long cb, int dwLockType)
|
||||
{
|
||||
}
|
||||
|
||||
public virtual int Write(IntPtr buf, int length)
|
||||
{
|
||||
var buffer = new byte[length];
|
||||
Marshal.Copy(buf, buffer, 0, length);
|
||||
return Write(buffer, length);
|
||||
}
|
||||
|
||||
public virtual int Write(byte[] buffer, int length)
|
||||
{
|
||||
ActualizeVirtualPosition();
|
||||
DataStream.Write(buffer, 0, length);
|
||||
return length;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user