fixed a bug of Screenshot on win7

This commit is contained in:
NaBian committed 2020-04-18 23:22:39 +08:00
1 parent dc64d5cacb
commit f4087574c0
11 files changed
+850 -450

No files matched your search

@@ -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;
}
}
}
}