Browse Source

Apewer-6.3.2:修正兼容性。

dev
Elivo 4 years ago
parent
commit
ebbd354821
  1. 2
      Apewer/Apewer.csproj
  2. 21
      Apewer/Internals/FontCollection.cs
  3. 2
      Apewer/Internals/Interop/Constant.cs
  4. 41
      Apewer/Internals/Interop/Gdi32.cs
  5. 25
      Apewer/Internals/Interop/GdiPlus.cs
  6. 20
      Apewer/NetworkUtility.cs
  7. 43
      Apewer/RuntimeUtility.cs
  8. 7
      Apewer/Source/ColumnAttribute.cs
  9. 21
      Apewer/Source/Record.cs
  10. 2
      Apewer/Surface/FontInstance.cs
  11. 764
      Apewer/Surface/FormsUtility.cs
  12. 8
      Apewer/Web/ApiProcessor.cs
  13. 6
      Apewer/_ChangeLog.md

2
Apewer/Apewer.csproj

@ -20,7 +20,7 @@
<Description></Description>
<RootNamespace>Apewer</RootNamespace>
<Product>Apewer Libraries</Product>
<Version>6.3.1</Version>
<Version>6.3.2</Version>
</PropertyGroup>
<!-- NuGet -->

21
Apewer/Internals/FontCollection.cs

@ -0,0 +1,21 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Apewer.Internals
{
internal sealed class FontCollection : IDisposable
{
public IntPtr NativePointer = IntPtr.Zero;
~FontCollection() { Dispose(false); }
public void Dispose() { Dispose(true); GC.SuppressFinalize(this); }
private void Dispose(bool disposing) { }
}
}

2
Apewer/Internals/Interop/Constant.cs

@ -72,6 +72,8 @@ namespace Apewer.Internals.Interop
/// <summary></summary>
public const int GWL_EXSTYLE = -20;
public const uint GGI_MARK_NONEXISTING_GLYPHS = 0x01;
/// <summary></summary>
public const int INVALID_HANDLE_VALUE = -1;

41
Apewer/Internals/Interop/Gdi32.cs

@ -8,62 +8,27 @@ namespace Apewer.Internals.Interop
internal class Gdi32
{
/// <summary>
///
/// </summary>
/// <param name="hdc"></param>
/// <returns></returns>
[DllImport("gdi32.dll", ExactSpelling = true, SetLastError = true)]
public static extern IntPtr CreateCompatibleDC(IntPtr hdc);
/// <summary>
///
/// </summary>
/// <param name="x1"></param>
/// <param name="y1"></param>
/// <param name="x2"></param>
/// <param name="y2"></param>
/// <param name="x3"></param>
/// <param name="y3"></param>
/// <returns></returns>
[DllImport("gdi32.dll")]
public static extern int CreateRoundRectRgn(int x1, int y1, int x2, int y2, int x3, int y3);
/// <summary>
///
/// </summary>
/// <param name="hdc"></param>
/// <returns></returns>
[DllImport("gdi32.dll", ExactSpelling = true, SetLastError = true)]
public static extern int DeleteDC(IntPtr hdc);
/// <summary>
///
/// </summary>
/// <param name="hobj"></param>
/// <returns></returns>
[DllImport("gdi32.dll", ExactSpelling = true, SetLastError = true)]
public static extern int DeleteObject(IntPtr hobj);
/// <summary>
///
/// </summary>
/// <param name="lpxform"></param>
/// <param name="ncount"></param>
/// <param name="rgndata"></param>
/// <returns></returns>
[DllImport("gdi32.dll", ExactSpelling = true, SetLastError = true)]
public static extern IntPtr ExtCreateRegion(IntPtr lpxform, uint ncount, IntPtr rgndata);
/// <summary>
///
/// </summary>
/// <param name="hdc"></param>
/// <param name="hobj"></param>
/// <returns></returns>
[DllImport("gdi32.dll", ExactSpelling = true)]
public static extern IntPtr SelectObject(IntPtr hdc, IntPtr hobj);
[DllImport("gdi32.dll", EntryPoint = "GetGlyphIndicesW")]
public static extern uint GetGlyphIndices([In] IntPtr hdc, [In][MarshalAs(UnmanagedType.LPTStr)] string lpsz, int c, [Out] ushort[] pgi, uint fl);
}
}

25
Apewer/Internals/Interop/GdiPlus.cs

@ -0,0 +1,25 @@
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Text;
namespace Apewer.Internals.Interop
{
internal class GdiPlus
{
[DllImport("gdiplus.dll", CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)]
internal static extern int GdipCloneFontFamily(HandleRef fontfamily, out IntPtr clonefontfamily);
[DllImport("gdiplus.dll", CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)]
internal static extern int GdipGetFontCollectionFamilyCount(HandleRef fontCollection, out int numFound);
[DllImport("gdiplus.dll", CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)]
internal static extern int GdipGetFontCollectionFamilyList(HandleRef fontCollection, int numSought, IntPtr[] gpfamilies, out int numFound);
[DllImport("gdiplus.dll", CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)]
internal static extern int GdipNewInstalledFontCollection(out IntPtr fontCollection);
}
}

20
Apewer/NetworkUtility.cs

@ -46,6 +46,18 @@ namespace Apewer
}
/// <summary>从 NTP 服务器获取 UTC 时间。</summary>
/// <remarks>
/// Worldwide: pool.ntp.org<br/>
/// Asia: asia.pool.ntp.org<br/>
/// Europe: europe.pool.ntp.org<br/>
/// North: America north-america.pool.ntp.org<br/>
/// Oceania: oceania.pool.ntp.org<br/>
/// South America: south-america.pool.ntp.org<br/>
/// Windows: time.windows.com<br/>
/// Windows: time.nist.gov<br/>
/// China: us.ntp.org.cn<br/>
/// China: edu.ntp.org.cn<br/>
/// </remarks>
public static DateTime GetUtcFromNtp(string server = "pool.ntp.org", int port = 123, int timeout = 1000)
{
try
@ -57,7 +69,9 @@ namespace Apewer
return GetUtcFromNtp(endpoint, timeout);
}
}
catch { }
catch (Exception ex)
{
}
return ClockUtility.Zero;
}
@ -89,7 +103,9 @@ namespace Apewer
var utc = (new DateTime(1900, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc)).AddMilliseconds(milliseconds);
return utc;
}
catch { }
catch (Exception ex)
{
}
return ClockUtility.Zero;
}

43
Apewer/RuntimeUtility.cs

@ -750,32 +750,43 @@ namespace Apewer
#region Assembly
/// <summary>获取当前进程程序集的资源。</summary>
public static byte[] GetAssemblyResource(string name)
/// <summary>列出当前域中的程序集。</summary>
public static Assembly[] ListLoadedAssemblies()
{
var assembly = Assembly.GetExecutingAssembly();
return GetAssemblyResource(assembly, name);
return AppDomain.CurrentDomain.GetAssemblies();
}
/// <summary>获取指定程序集的资源。</summary>
public static byte[] GetAssemblyResource(Assembly assembly, string name)
/// <summary>从指定的程序集加载资源。</summary>
/// <param name="name">资源的名称。</param>
/// <param name="assembly">程序集,为 NULL 值时指向 CallingAssembly。</param>
/// <returns>该资源的流,发生错误时返回 NULL 值。</returns>
/// <remarks>此方法不引发异常。</remarks>
public static Stream OpenResource(string name, Assembly assembly = null)
{
var result = Constant.EmptyBytes;
if (assembly == null) return null;
var stream = null as Stream;
try
{
var source = assembly.GetManifestResourceStream(name);
result = StreamHelper.Read(source);
Dispose(source);
var asm = assembly ?? Assembly.GetCallingAssembly();
stream = asm.GetManifestResourceStream(name);
}
finally { }
return result;
catch { }
return null;
}
/// <summary>获取已加载的程序集。</summary>
public static Assembly[] GetLoadedAssemblies()
/// <summary>从程序集获取资源,读取到内存流。发生错误时返回 NULL 值,不引发异常。</summary>
/// <param name="name">资源的名称。</param>
/// <param name="assembly">程序集,为 NULL 值时指向 CallingAssembly。</param>
/// <returns>该资源的流,发生错误时返回 NULL 值。</returns>
/// <remarks>此方法不引发异常。</remarks>
public static MemoryStream GetResource(string name, Assembly assembly = null)
{
return AppDomain.CurrentDomain.GetAssemblies();
var res = OpenResource(name, assembly);
if (res == null) return null;
var memory = new MemoryStream();
BinaryUtility.Read(res, memory);
res.Dispose();
return memory;
}
#endregion

7
Apewer/Source/ColumnAttribute.cs

@ -7,7 +7,7 @@ using System.Text;
namespace Apewer.Source
{
/// <summary>数据库中的列,类型默认为 NVarChar(255),错误类型将修正为 NText。</summary>
/// <summary>数据库中的列,类型默认为 NVarChar(191),错误类型将修正为 NText。</summary>
[Serializable]
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = true)]
public sealed class ColumnAttribute : Attribute
@ -25,14 +25,14 @@ namespace Apewer.Source
/// <summary>使用自动的列名称。当类型为 VarChar 或 NVarChar 时必须指定长度。</summary>
/// <exception cref="System.ArgumentException"></exception>
public ColumnAttribute(ColumnType type = ColumnType.NVarChar255, int length = 0)
public ColumnAttribute(ColumnType type = ColumnType.NVarChar, int length = 191)
{
New(null, type, length, true);
}
/// <summary>使用指定的列名称。当类型为 VarChar 或 NVarChar 时必须指定长度。</summary>
/// <exception cref="System.ArgumentException"></exception>
public ColumnAttribute(string field, ColumnType type = ColumnType.NVarChar255, int length = 0)
public ColumnAttribute(string field, ColumnType type = ColumnType.NVarChar, int length = 191)
{
New(field, type, length, false);
}
@ -113,6 +113,7 @@ namespace Apewer.Source
_length = length;
break;
}
Lock();
}
/// <summary>锁定属性,阻止修改。</summary>

21
Apewer/Source/Record.cs

@ -11,6 +11,9 @@ namespace Apewer.Source
public class Record : IRecord
{
private const int DefaultLength = 191;
private const int KeyLength = 128;
[NonSerialized]
private string _created = "";
@ -26,13 +29,13 @@ namespace Apewer.Source
[NonSerialized]
private string _key = GenerateKey();
/// <summary>记录的创建时间,NVarChar 255 类型,值为执行 INSERT INTO 语句时的时间。</summary>
[Column("_created", ColumnType.NVarChar255)]
public virtual string Created { get { return _created; } set { _created = TextModifier.Compact(value, 255); } }
/// <summary>记录的创建时间,值为执行 INSERT INTO 语句时的时间。</summary>
[Column("_created", ColumnType.NVarChar, DefaultLength)]
public virtual string Created { get { return _created; } set { _created = TextModifier.Compact(value, DefaultLength); } }
/// <summary>记录的更新时间,NVarChar 255 类型,每次对此记录执行 UPDATE 时应更新此值为当前系统时间。</summary>
[Column("_updated", ColumnType.NVarChar255)]
public virtual string Updated { get { return _updated; } set { _updated = TextModifier.Compact(value, 255); } }
/// <summary>记录的更新时间,类型,每次对此记录执行 UPDATE 时应更新此值为当前系统时间。</summary>
[Column("_updated", ColumnType.NVarChar, DefaultLength)]
public virtual string Updated { get { return _updated; } set { _updated = TextModifier.Compact(value, DefaultLength); } }
/// <summary>记录的标记,Int64 类型,区分记录的状态。</summary>
[Column("_flag", ColumnType.Integer)]
@ -42,9 +45,9 @@ namespace Apewer.Source
[Column("_remark", ColumnType.NText)]
public virtual string Remark { get { return _remark; } set { _remark = TextModifier.Compact(value); } }
/// <summary>记录唯一键,NVarChar 128 类型,一般使用 GUID 的字符串形式。</summary>
[Column("_key", ColumnType.NVarChar, 128)]
public virtual string Key { get { return _key; } set { _key = TextModifier.Compact(value, 128); } }
/// <summary>记录唯一键,一般使用 GUID 的字符串形式。</summary>
[Column("_key", ColumnType.NVarChar, KeyLength)]
public virtual string Key { get { return _key; } set { _key = TextModifier.Compact(value, KeyLength); } }
/// <summary>重置主键。</summary>
internal static void ResetKey(Record record)

2
Apewer/Surface/FontInstance.cs

@ -10,7 +10,7 @@ namespace Apewer.Surface
{
/// <summary></summary>
public class FontInstance
internal class FontInstance
{
private FontFamily _fontfamily = null;

764
Apewer/Surface/FormsUtility.cs

@ -1,5 +1,4 @@
using Apewer;
using Apewer.Internals.Interop;
using Apewer.Internals.Interop;
using System;
using System.Collections.Generic;
using System.Drawing;
@ -23,35 +22,30 @@ namespace Apewer.Surface
public class FormsUtility
{
private const string FontYahei = "Microsoft Yahei";
private const string FontSimsun = "Simsun";
private static string _fontname = "";
/// <summary>线程锁。</summary>
public static object ThreadLocker = new object();
/// <summary>存在微软雅黑字体。</summary>
public static bool MsyhExist
#if NETFX || NETCORE
/// <summary>窗体启动初始化。</summary>
[STAThread]
public static void StartInitialization()
{
get { return File.Exists("c:\\windows\\fonts\\msyh.ttc"); }
Control.CheckForIllegalCrossThreadCalls = false;
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
}
/// <summary>获取默认字体名称。</summary>
public static string DefaultFontName
/// <summary>禁用跨线程调用检查。</summary>
public static void CrossThread()
{
get
{
if (!string.IsNullOrEmpty(_fontname)) return _fontname;
try
{
if (File.Exists("c:\\windows\\fonts\\msyh.ttc")) return FontYahei;
else return FontSimsun;
}
catch { return FontSimsun; }
}
Control.CheckForIllegalCrossThreadCalls = false;
}
#endif
#region 颜色。
/// <summary>获取所有可枚举的颜色。</summary>
public static Color[] EnumerableColor
{
@ -284,7 +278,7 @@ namespace Apewer.Surface
/// <param name="fore">前景色(基色)。</param>
/// <param name="depth">颜色深度,最大值。</param>
/// <returns>合成后的颜色(基色)。</returns>
public static int AlphaColor(int alpha, int fore, int back, int depth = 255)
public static int MixAlpha(int alpha, int fore, int back, int depth = 255)
{
int b = back, f = fore;
if (b > depth) b = depth; if (b < 0) b = 0;
@ -294,81 +288,97 @@ namespace Apewer.Surface
return v;
}
/// <summary>从程序集获取资源。发生错误时返回 NULL 值,不引发异常。</summary>
public static Stream OpenResourceStream(string name, Assembly assembly = null)
/// <summary>按 Alpha 混合不透明的颜色。</summary>
/// <param name="backColor">背景色。</param>
/// <param name="foreColor">前景色。</param>
/// <param name="foreAlpha">前景 Alpha 值。</param>
/// <returns>混合后的颜色。</returns>
public static Color MixAlpha(Color backColor, Color foreColor, int foreAlpha)
{
var stream = null as Stream;
try
{
if (assembly == null) assembly = Assembly.GetCallingAssembly();
stream = assembly.GetManifestResourceStream(name);
}
catch { }
return null;
var r = MixAlpha(backColor.R, foreColor.R, foreAlpha);
var g = MixAlpha(backColor.G, foreColor.G, foreAlpha);
var b = MixAlpha(backColor.B, foreColor.B, foreAlpha);
var a = MixAlpha(backColor.A, foreColor.A, foreAlpha);
return Color.FromArgb(a, r, g, b);
}
/// <summary>从程序集获取资源,读取到内存流。发生错误时返回 NULL 值,不引发异常。</summary>
public static MemoryStream GetResourceStream(string name, Assembly assembly = null)
{
var stream = OpenResourceStream(name, assembly);
if (stream == null) return null;
var memory = new MemoryStream();
BinaryUtility.Read(stream, memory);
stream.Dispose();
memory.ResetPosition();
return memory;
}
#endregion
/// <summary>从程序集获取资源,读取到内存流。发生错误时返回 NULL 值,不引发异常。</summary>
public static byte[] GetResource(string name, Assembly assembly = null)
{
var stream = OpenResourceStream(name, assembly);
if (stream == null) return null;
var bytes = BinaryUtility.Read(stream);
stream.Dispose();
return bytes;
}
#region 屏幕。
#if NETFX || NETCORE
/// <summary>获取默认字体。</summary>
public static Font DefaultFont
/// <summary>获取屏幕的截图。</summary>
public static Bitmap[] ScreenShot()
{
get { return new Font(DefaultFontName, 9); }
var list = new List<Bitmap>();
var all = Screen.AllScreens;
foreach (var screen in all)
{
int vw = screen.Bounds.Width;
int vh = screen.Bounds.Height;
int vd = screen.BitsPerPixel;
Bitmap b = new Bitmap(vw, vh, PixelFormat.Format32bppArgb);
Graphics g = Graphics.FromImage(b);
g.CopyFromScreen(0, 0, 0, 0, new System.Drawing.Size(vw, vh));
g.Dispose();
list.Add(b);
}
return list.ToArray();
}
/// <summary>获取大小为 9 的默认字体。</summary>
public static Font NewFont()
/// <summary>获取指定屏幕的截图。</summary>
/// <param name="screen">屏幕号。</param>
internal static Bitmap ScreenShot(int screen)
{
return new Font(DefaultFontName, 9);
var a = Screen.AllScreens;
if ((a.Length > 0) && (screen >= 0) && (screen < a.Length))
{
try
{
int w = a[screen].Bounds.Width;
int h = a[screen].Bounds.Height;
int d = a[screen].BitsPerPixel;
Bitmap b = new Bitmap(w, h, PixelFormat.Format32bppArgb);
Graphics g = Graphics.FromImage(b);
g.CopyFromScreen(0, 0, 0, 0, new System.Drawing.Size(w, h));
g.Dispose();
return b;
}
catch { }
}
return new Bitmap(0, 0, PixelFormat.Format32bppArgb);
}
/// <summary>获取指定大小的默认字体。</summary>
public static Font NewFont(float size)
/// <summary>获取指定屏幕的截图。</summary>
/// <param name="screen">屏幕,若为 Null 则选择主屏幕。</param>
internal static Bitmap ScreenShot(Screen screen)
{
return new Font(DefaultFontName, size);
if (screen == null)
{
try
{
int w = Screen.PrimaryScreen.Bounds.Width;
int h = Screen.PrimaryScreen.Bounds.Height;
int d = Screen.PrimaryScreen.BitsPerPixel;
Bitmap b = new Bitmap(w, h, PixelFormat.Format32bppArgb);
Graphics g = Graphics.FromImage(b);
g.CopyFromScreen(0, 0, 0, 0, new System.Drawing.Size(w, h));
g.Dispose();
return b;
}
catch { }
}
return new Bitmap(0, 0, PixelFormat.Format32bppArgb);
}
/// <summary>获取指定大小的默认字体。</summary>
public static Font NewFont(float size, bool bold)
{
return new Font(DefaultFontName, size, bold ? FontStyle.Bold : FontStyle.Regular);
}
#endif
/// <summary>窗体启动初始化。</summary>
[STAThread]
public static void StartInitialization()
{
Control.CheckForIllegalCrossThreadCalls = false;
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
}
#endregion
/// <summary>禁用跨线程调用检查。</summary>
public static void CrossThread()
{
Control.CheckForIllegalCrossThreadCalls = false;
}
#region 窗体。
#if NETFX || NETCORE
/// <summary>移动窗体。</summary>
public static void MoveForm(Form form)
@ -396,85 +406,72 @@ namespace Apewer.Surface
int oldGWLEx = User32.SetWindowLong(form, Constant.GWL_EXSTYLE, Constant.WS_EX_TRANSPARENT | Constant.WS_EX_LAYERED);
}
/// <summary>绘制内边框。</summary>
/// <param name="image">源图像。</param>
/// <param name="border">边框颜色。</param>
public static bool PaintBorder(ref Image image, Color border)
/// <summary>将窗体最大化,不覆盖任务栏。</summary>
/// <param name="form">窗体。</param>
public static void ToMaximum(Form form)
{
if (image != null)
if (form != null)
{
var g = Graphics.FromImage(image);
var p = new Pen(border);
g.DrawRectangle(p, 0, 0, image.Width - 1, image.Height - 1);
p.Dispose();
g.Dispose();
return true;
var s = Screen.FromControl(form);
var r = s.WorkingArea;
if ((form.MaximumSize.Width < r.Width) || (form.MaximumSize.Height < r.Height))
{
form.MaximumSize = r.Size;
}
form.Location = r.Location;
form.Size = r.Size;
}
else return false;
}
/// <summary>绘制内边框。</summary>
/// <param name="image">源图像。</param>
/// <param name="border">边框颜色。</param>
public static bool PaintBorder(ref Bitmap image, Color border)
/// <summary>用指定图像绘制窗体,窗体与图像的大小必须一致。</summary>
/// <param name="form">要绘制的窗体。</param>
/// <param name="image">要使用的图像。</param>
public static void UpdateShadow(Form form, Image image)
{
if (image != null)
if ((form != null) && (image != null))
{
var g = Graphics.FromImage(image);
var p = new Pen(border);
g.DrawRectangle(p, 0, 0, image.Width - 1, image.Height - 1);
p.Dispose();
g.Dispose();
return true;
}
else return false;
}
Bitmap vbitmap;
if ((form.Width != image.Width) || (form.Height != image.Height))
{
vbitmap = new Bitmap(image.GetThumbnailImage(form.Width, form.Height, null, IntPtr.Zero));
}
else
{
vbitmap = new Bitmap(image);
}
/// <summary>绘制内边框。</summary>
/// <param name="image">源图像。</param>
/// <param name="border">边框颜色。</param>
/// <param name="wall">背景颜色。</param>
public static bool PaintBorder(ref Image image, Color border, Color wall)
{
if (image != null)
{
var g = Graphics.FromImage(image);
var p = new Pen(border);
var screendc = User32.GetDC(IntPtr.Zero);
var location = new Internals.Interop.Point(form.Left, form.Top);
var size = new Internals.Interop.Size(form.Width, form.Height);
var compatibledc = Gdi32.CreateCompatibleDC(screendc);
var handle = vbitmap.GetHbitmap(Color.FromArgb(0));
var oldbitmap = Gdi32.SelectObject(compatibledc, handle);
var srcloc = new Internals.Interop.Point(0, 0);
var blendfunction = new BlendFunction();
g.Clear(wall);
blendfunction.blendop = Constant.AC_SRC_OVER;
blendfunction.sourceconstantalpha = byte.Parse("255");
blendfunction.alphaformat = Constant.AC_SRC_ALPHA;
blendfunction.blendflags = 0;
User32.UpdateLayeredWindow(form.Handle, screendc, ref location, ref size, compatibledc, ref srcloc, 0, ref blendfunction, Constant.ULW_ALPHA);
g.DrawRectangle(p, 0, 0, image.Width - 1, image.Height - 1);
p.Dispose();
g.Dispose();
return true;
if (handle != IntPtr.Zero)
{
Gdi32.SelectObject(compatibledc, oldbitmap);
Gdi32.DeleteObject(handle);
}
User32.ReleaseDC(IntPtr.Zero, screendc);
Gdi32.DeleteDC(compatibledc);
}
else return false;
}
/// <summary>建立带有圆角样式的路径。</summary>
/// <param name="rect">建立矩形路径的区域。</param>
/// <param name="radius">圆角的大小。</param>
/// <returns>建立的路径。</returns>
public static GraphicsPath CreatePath(Rectangle rect, int radius = 0)
/// <summary>为窗体启用阴影。</summary>
/// <param name="form">要启用阴影的窗体。</param>
public static void EnableShadow(Form form)
{
GraphicsPath path = new GraphicsPath();
int r = (radius < 0) ? 0 : radius;
switch (r)
{
case 0:
path.AddRectangle(rect);
break;
default:
path.AddArc(rect.X, rect.Y, r, r, 180, 90);
path.AddArc(rect.Right - r - 1, rect.Y, r, r, 270, 90);
path.AddArc(rect.Right - r - 1, rect.Bottom - r - 1, r, r, 0, 90);
path.AddArc(rect.X, rect.Bottom - r - 1, r, r, 90, 90);
break;
}
path.CloseFigure();
return path;
if (form == null) return;
int vformclass = User32.GetClassLong(form.Handle, Constant.GCL_STYLE);
User32.SetClassLong(form.Handle, Constant.GCL_STYLE, vformclass | Constant.CS_DROPSHADOW);
}
/// <summary>恢复任务栏中窗体标题的右键菜单。</summary>
@ -489,6 +486,14 @@ namespace Apewer.Surface
}
}
#endif
#endregion
#region 控件。
#if NETFX || NETCORE
/// <summary>在主界面中移动控件,由目标控件取代当前控件,形成切换控件的动画。</summary>
/// <param name="current">当前显示的控件。</param>
/// <param name="target">将要显示的目标控件。</param>
@ -556,136 +561,138 @@ namespace Apewer.Surface
current.Visible = false;
}
/// <summary>将窗体最大化,不覆盖任务栏。</summary>
/// <param name="form">窗体。</param>
public static void ToMaximum(Form form)
/// <summary></summary>
public static void Invoke(Control control, Action action, bool async = false)
{
if (form != null)
if (control == null || action == null) return;
// control.Invoke(action);
if (async)
{
var s = Screen.FromControl(form);
var r = s.WorkingArea;
if ((form.MaximumSize.Width < r.Width) || (form.MaximumSize.Height < r.Height))
control.BeginInvoke(new Action(delegate ()
{
form.MaximumSize = r.Size;
}
form.Location = r.Location;
form.Size = r.Size;
action.Invoke();
}));
}
else
{
control.Invoke(new Action(delegate ()
{
action.Invoke();
}));
}
}
/// <summary>用指定图像绘制窗体,窗体与图像的大小必须一致。</summary>
/// <param name="form">要绘制的窗体。</param>
/// <param name="image">要使用的图像。</param>
public static void UpdateShadow(Form form, Image image)
/// <summary></summary>
public static void BeginInvoke(Control control, Action action)
{
if ((form != null) && (image != null))
{
Bitmap vbitmap;
if ((form.Width != image.Width) || (form.Height != image.Height))
{
vbitmap = new Bitmap(image.GetThumbnailImage(form.Width, form.Height, null, IntPtr.Zero));
}
else
{
vbitmap = new Bitmap(image);
}
if (control == null || action == null) return;
var screendc = User32.GetDC(IntPtr.Zero);
var location = new Internals.Interop.Point(form.Left, form.Top);
var size = new Internals.Interop.Size(form.Width, form.Height);
var compatibledc = Gdi32.CreateCompatibleDC(screendc);
var handle = vbitmap.GetHbitmap(Color.FromArgb(0));
var oldbitmap = Gdi32.SelectObject(compatibledc, handle);
var srcloc = new Internals.Interop.Point(0, 0);
var blendfunction = new BlendFunction();
control.BeginInvoke(new Action(delegate ()
{
action.Invoke();
}));
}
blendfunction.blendop = Constant.AC_SRC_OVER;
blendfunction.sourceconstantalpha = byte.Parse("255");
blendfunction.alphaformat = Constant.AC_SRC_ALPHA;
blendfunction.blendflags = 0;
User32.UpdateLayeredWindow(form.Handle, screendc, ref location, ref size, compatibledc, ref srcloc, 0, ref blendfunction, Constant.ULW_ALPHA);
/// <summary>设置窗体置顶。</summary>
public static void SetTopMost(IntPtr form, bool value = true)
{
if (form == null || form == IntPtr.Zero) return;
User32.SetWindowPos(form, new IntPtr(value ? -1 : -2), 0, 0, 0, 0, 3);
}
if (handle != IntPtr.Zero)
{
Gdi32.SelectObject(compatibledc, oldbitmap);
Gdi32.DeleteObject(handle);
}
User32.ReleaseDC(IntPtr.Zero, screendc);
Gdi32.DeleteDC(compatibledc);
}
/// <summary>设置窗体置顶。</summary>
public static void SetTopMost(Form form, bool value = true)
{
if (form != null) SetTopMost(form.Handle, value);
}
/// <summary>为窗体启用阴影。</summary>
/// <param name="form">要启用阴影的窗体。</param>
public static void EnableShadow(Form form)
#endif
#endregion
#region 绘图。
#if NETFX || NETCORE
/// <summary>绘制内边框。</summary>
/// <param name="image">源图像。</param>
/// <param name="border">边框颜色。</param>
public static bool PaintBorder(ref Image image, Color border)
{
if (form == null) return;
int vformclass = User32.GetClassLong(form.Handle, Constant.GCL_STYLE);
User32.SetClassLong(form.Handle, Constant.GCL_STYLE, vformclass | Constant.CS_DROPSHADOW);
if (image != null)
{
var g = Graphics.FromImage(image);
var p = new Pen(border);
g.DrawRectangle(p, 0, 0, image.Width - 1, image.Height - 1);
p.Dispose();
g.Dispose();
return true;
}
else return false;
}
/// <summary>获取屏幕的截图。</summary>
public static Bitmap[] ScreenShot()
/// <summary>绘制内边框。</summary>
/// <param name="image">源图像。</param>
/// <param name="border">边框颜色。</param>
public static bool PaintBorder(ref Bitmap image, Color border)
{
var list = new List<Bitmap>();
var all = Screen.AllScreens;
foreach (var screen in all)
if (image != null)
{
int vw = screen.Bounds.Width;
int vh = screen.Bounds.Height;
int vd = screen.BitsPerPixel;
Bitmap b = new Bitmap(vw, vh, PixelFormat.Format32bppArgb);
Graphics g = Graphics.FromImage(b);
g.CopyFromScreen(0, 0, 0, 0, new System.Drawing.Size(vw, vh));
var g = Graphics.FromImage(image);
var p = new Pen(border);
g.DrawRectangle(p, 0, 0, image.Width - 1, image.Height - 1);
p.Dispose();
g.Dispose();
list.Add(b);
return true;
}
return list.ToArray();
else return false;
}
/// <summary>获取指定屏幕的截图。</summary>
/// <param name="screen">屏幕号。</param>
internal static Bitmap ScreenShot(int screen)
/// <summary>绘制内边框。</summary>
/// <param name="image">源图像。</param>
/// <param name="border">边框颜色。</param>
/// <param name="wall">背景颜色。</param>
public static bool PaintBorder(ref Image image, Color border, Color wall)
{
var a = Screen.AllScreens;
if ((a.Length > 0) && (screen >= 0) && (screen < a.Length))
if (image != null)
{
try
{
int w = a[screen].Bounds.Width;
int h = a[screen].Bounds.Height;
int d = a[screen].BitsPerPixel;
Bitmap b = new Bitmap(w, h, PixelFormat.Format32bppArgb);
Graphics g = Graphics.FromImage(b);
g.CopyFromScreen(0, 0, 0, 0, new System.Drawing.Size(w, h));
g.Dispose();
return b;
}
catch { }
var g = Graphics.FromImage(image);
var p = new Pen(border);
g.Clear(wall);
g.DrawRectangle(p, 0, 0, image.Width - 1, image.Height - 1);
p.Dispose();
g.Dispose();
return true;
}
return new Bitmap(0, 0, PixelFormat.Format32bppArgb);
else return false;
}
/// <summary>获取指定屏幕的截图。</summary>
/// <param name="screen">屏幕,若为 Null 则选择主屏幕。</param>
internal static Bitmap ScreenShot(Screen screen)
/// <summary>建立带有圆角样式的路径。</summary>
/// <param name="rect">建立矩形路径的区域。</param>
/// <param name="radius">圆角的大小。</param>
/// <returns>建立的路径。</returns>
public static GraphicsPath CreatePath(Rectangle rect, int radius = 0)
{
if (screen == null)
GraphicsPath path = new GraphicsPath();
int r = (radius < 0) ? 0 : radius;
switch (r)
{
try
{
int w = Screen.PrimaryScreen.Bounds.Width;
int h = Screen.PrimaryScreen.Bounds.Height;
int d = Screen.PrimaryScreen.BitsPerPixel;
Bitmap b = new Bitmap(w, h, PixelFormat.Format32bppArgb);
Graphics g = Graphics.FromImage(b);
g.CopyFromScreen(0, 0, 0, 0, new System.Drawing.Size(w, h));
g.Dispose();
return b;
}
catch { }
case 0:
path.AddRectangle(rect);
break;
default:
path.AddArc(rect.X, rect.Y, r, r, 180, 90);
path.AddArc(rect.Right - r - 1, rect.Y, r, r, 270, 90);
path.AddArc(rect.Right - r - 1, rect.Bottom - r - 1, r, r, 0, 90);
path.AddArc(rect.X, rect.Bottom - r - 1, r, r, 90, 90);
break;
}
return new Bitmap(0, 0, PixelFormat.Format32bppArgb);
path.CloseFigure();
return path;
}
/// <summary></summary>
@ -731,61 +738,6 @@ namespace Apewer.Surface
return path;
}
/// <summary>从文件加载字体,并获取字体。</summary>
public static FontFamily LoadFont(string path)
{
if (!File.Exists(path)) return null;
var vpfc = new PrivateFontCollection();
vpfc.AddFontFile(path);
var vff = vpfc.Families[0];
return vff;
}
/// <summary></summary>
public static void Invoke(Control control, Action action, bool async = false)
{
if (control == null || action == null) return;
// control.Invoke(action);
if (async)
{
control.BeginInvoke(new Action(delegate ()
{
action.Invoke();
}));
}
else
{
control.Invoke(new Action(delegate ()
{
action.Invoke();
}));
}
}
/// <summary></summary>
public static void BeginInvoke(Control control, Action action)
{
if (control == null || action == null) return;
control.BeginInvoke(new Action(delegate ()
{
action.Invoke();
}));
}
/// <summary>设置窗体置顶。</summary>
public static void SetTopMost(IntPtr form, bool value = true)
{
if (form == null || form == IntPtr.Zero) return;
User32.SetWindowPos(form, new IntPtr(value ? -1 : -2), 0, 0, 0, 0, 3);
}
/// <summary>设置窗体置顶。</summary>
public static void SetTopMost(Form form, bool value = true)
{
if (form != null) SetTopMost(form.Handle, value);
}
/// <summary>获取指定文件中的图标总数。</summary>
public static int GetIconsCount(string path)
{
@ -830,6 +782,216 @@ namespace Apewer.Surface
#endif
#endregion
#region 字体。
private const string FontYahei = "Microsoft Yahei";
private const string FontSimsun = "Simsun";
private static string _fontname = "";
/// <summary>存在微软雅黑字体。</summary>
public static bool MsyhExist
{
get { return File.Exists("c:\\windows\\fonts\\msyh.ttc"); }
}
/// <summary>获取默认字体名称。</summary>
public static string DefaultFontName
{
get
{
if (!string.IsNullOrEmpty(_fontname)) return _fontname;
try
{
if (File.Exists("c:\\windows\\fonts\\msyh.ttc")) return FontYahei;
else return FontSimsun;
}
catch { return FontSimsun; }
}
}
#if NETFX || NETCORE
/// <summary>获取默认字体。</summary>
public static Font DefaultFont
{
get { return new Font(DefaultFontName, 9); }
}
/// <summary>获取大小为 9 的默认字体。</summary>
public static Font NewFont()
{
return new Font(DefaultFontName, 9);
}
/// <summary>获取指定大小的默认字体。</summary>
public static Font NewFont(float size)
{
return new Font(DefaultFontName, size);
}
/// <summary>获取指定大小的默认字体。</summary>
public static Font NewFont(float size, bool bold)
{
return new Font(DefaultFontName, size, bold ? FontStyle.Bold : FontStyle.Regular);
}
/// <summary>从文件加载字体,并获取指定字体。</summary>
/// <param name="path">文件路径。</param>
/// <param name="index">文件中的 Font Family 索引,默认取第一个(索引 0)。</param>
/// <returns>已存在的 Font Family,如果指定的索引处不存在 Font Family,则返回 NULL 值。</returns>
public static FontFamily LoadFont(string path, int index = 0)
{
if (index < 0) return null;
if (string.IsNullOrEmpty(path)) return null;
if (!File.Exists(path)) return null;
try
{
var pfc = new PrivateFontCollection();
pfc.AddFontFile(path);
var fs = pfc.Families;
if (fs.Length > 0 && index < fs.Length) return fs[index];
}
catch { }
return null;
}
#if NET40 || NET461
/// <summary></summary>
public static List<System.Windows.Media.FontFamily> ListFileFont(string path)
{
try
{
var collection = System.Windows.Media.Fonts.GetFontFamilies(path);
var list = new List<System.Windows.Media.FontFamily>(collection.Count);
foreach (var item in collection) list.Add(item);
return list;
}
catch { }
return new List<System.Windows.Media.FontFamily>();
}
/// <summary></summary>
public static List<System.Windows.Media.FontFamily> ListSystemFont()
{
var collection = System.Windows.Media.Fonts.SystemFontFamilies;
var list = new List<System.Windows.Media.FontFamily>(collection.Count);
foreach (var item in collection) list.Add(item);
return list;
}
/// <summary>枚举指定字体中的所有字符。</summary>
public static List<char> EnumerateFontChars(IEnumerable<System.Windows.Media.Typeface> typefaces)
{
var chars = new List<char>();
if (typefaces != null)
{
foreach (var typeface in typefaces)
{
var subs = EnumerateFontChars(typeface);
if (subs != null) chars.AddRange(subs);
}
}
return chars;
}
/// <summary>枚举指定字体中的所有字符。</summary>
public static List<char> EnumerateFontChars(System.Windows.Media.Typeface typeface)
{
System.Windows.Media.GlyphTypeface glyph;
var tried = typeface.TryGetGlyphTypeface(out glyph);
if (glyph == null) return null;
var map = glyph.CharacterToGlyphMap;
var keys = map.Keys;
var chars = new List<char>(keys.Count);
for (int i = 0; i < keys.Count; i++)
{
var index = System.Linq.Enumerable.ElementAt(keys, i);
try
{
var c = Convert.ToChar(index);
chars.Add(c.ToString());
}
catch { }
}
return chars;
}
#endif
/// <summary>获取已安装的字体。</summary>
public static List<FontFamily> ListInstalledFonts()
{
var list = new List<FontFamily>();
int ret = 0; // Win32 API 返回值,非零值均为异常。
// 初始化 FontCollection。
var collection = new Internals.FontCollection();
ret = GdiPlus.GdipNewInstalledFontCollection(out collection.NativePointer);
if (ret != 0) return list;
// 获取字体总数。
int found1 = 0;
ret = GdiPlus.GdipGetFontCollectionFamilyCount(new HandleRef(collection, collection.NativePointer), out found1);
if (ret != 0) return list;
// 获取字体指针。
var ptrs = new IntPtr[found1];
int found2 = 0;
ret = GdiPlus.GdipGetFontCollectionFamilyList(new HandleRef(collection, collection.NativePointer), found1, ptrs, out found2);
if (ret != 0) return list;
// 获取字体列表。
list.Capacity = found2;
for (int i = 0; i < found2; i++)
{
IntPtr cloned;
GdiPlus.GdipCloneFontFamily(new HandleRef(null, ptrs[i]), out cloned);
try
{
var flags = BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.CreateInstance;
var args = new object[] { cloned };
var instance = Activator.CreateInstance(typeof(FontFamily), flags, null, args, null, null);
var item = instance as FontFamily;
if (item != null) list.Add(item);
}
catch { }
}
list.Capacity = list.Count;
return list;
}
private static bool GlyphExists(char c, Font font)
{
using (var dummy = Graphics.FromImage(new Bitmap(1, 1)))
{
IntPtr hdc = dummy.GetHdc();
var pgi = new ushort[1];
try
{
IntPtr hfont = font.ToHfont();
Gdi32.SelectObject(hdc, hfont);
string str = c.ToString();
Gdi32.GetGlyphIndices(hdc, str, str.Length, pgi, Constant.GGI_MARK_NONEXISTING_GLYPHS);
}
catch { }
dummy.ReleaseHdc(hdc);
// 0xFFFF 表示字形不存在。
return (pgi[0] != 0xffff);
}
}
#endif
#endregion
}
}

8
Apewer/Web/ApiProcessor.cs

@ -452,15 +452,15 @@ namespace Apewer.Web
var ps = new List<string>();
foreach (var kvp in cookies)
{
var k = kvp.Key;
var v = kvp.Value;
var k = kvp.Key ?? "";
var v = kvp.Value ?? "";
if (k.IsEmpty()) continue;
ps.Add(TextUtility.Merge(k, "="), v);
ps.Add(TextUtility.Merge(k, "=", v));
}
if (ps.Count < 1) return null;
var value = TextUtility.Merge("; ", ps);
var value = TextUtility.Join("; ", ps);
return AddHeader("Set-Cookie", value);
}

6
Apewer/_ChangeLog.md

@ -1,6 +1,12 @@

### 最新提交
### 6.3.2
- RuntimeUtility:调整了 Assembly 的方法名称;
- Surface:迁移获取字形的方法到 FormsUtility,不再提供 FontInstance 类;
- Source:调整 ColumnAttribute 和 Record 的默认字段长度从 255 到 191;
- Web:修正无法设置 Cookie 的问题。
### 6.3.1
- Source:修正了多次获取 Access 密码会报错的问题;
- Web:对 ApiResponse 中增加 Indented,支持对单个 API 的响应强制缩进排版。

Loading…
Cancel
Save