diff --git a/Apewer/Apewer.csproj b/Apewer/Apewer.csproj
index f5d3a33..ed44a85 100644
--- a/Apewer/Apewer.csproj
+++ b/Apewer/Apewer.csproj
@@ -20,7 +20,7 @@
Apewer
Apewer Libraries
- 6.3.1
+ 6.3.2
diff --git a/Apewer/Internals/FontCollection.cs b/Apewer/Internals/FontCollection.cs
new file mode 100644
index 0000000..e296bfe
--- /dev/null
+++ b/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) { }
+
+ }
+
+}
diff --git a/Apewer/Internals/Interop/Constant.cs b/Apewer/Internals/Interop/Constant.cs
index 7032671..934a7c9 100644
--- a/Apewer/Internals/Interop/Constant.cs
+++ b/Apewer/Internals/Interop/Constant.cs
@@ -72,6 +72,8 @@ namespace Apewer.Internals.Interop
///
public const int GWL_EXSTYLE = -20;
+ public const uint GGI_MARK_NONEXISTING_GLYPHS = 0x01;
+
///
public const int INVALID_HANDLE_VALUE = -1;
diff --git a/Apewer/Internals/Interop/Gdi32.cs b/Apewer/Internals/Interop/Gdi32.cs
index 8ce37d9..54b1203 100644
--- a/Apewer/Internals/Interop/Gdi32.cs
+++ b/Apewer/Internals/Interop/Gdi32.cs
@@ -8,62 +8,27 @@ namespace Apewer.Internals.Interop
internal class Gdi32
{
- ///
- ///
- ///
- ///
- ///
[DllImport("gdi32.dll", ExactSpelling = true, SetLastError = true)]
public static extern IntPtr CreateCompatibleDC(IntPtr hdc);
- ///
- ///
- ///
- ///
- ///
- ///
- ///
- ///
- ///
- ///
[DllImport("gdi32.dll")]
public static extern int CreateRoundRectRgn(int x1, int y1, int x2, int y2, int x3, int y3);
- ///
- ///
- ///
- ///
- ///
[DllImport("gdi32.dll", ExactSpelling = true, SetLastError = true)]
public static extern int DeleteDC(IntPtr hdc);
- ///
- ///
- ///
- ///
- ///
[DllImport("gdi32.dll", ExactSpelling = true, SetLastError = true)]
public static extern int DeleteObject(IntPtr hobj);
- ///
- ///
- ///
- ///
- ///
- ///
- ///
[DllImport("gdi32.dll", ExactSpelling = true, SetLastError = true)]
public static extern IntPtr ExtCreateRegion(IntPtr lpxform, uint ncount, IntPtr rgndata);
- ///
- ///
- ///
- ///
- ///
- ///
[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);
+
}
}
diff --git a/Apewer/Internals/Interop/GdiPlus.cs b/Apewer/Internals/Interop/GdiPlus.cs
new file mode 100644
index 0000000..75e7fb0
--- /dev/null
+++ b/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);
+
+ }
+
+}
diff --git a/Apewer/NetworkUtility.cs b/Apewer/NetworkUtility.cs
index bf59c37..ac3caba 100644
--- a/Apewer/NetworkUtility.cs
+++ b/Apewer/NetworkUtility.cs
@@ -46,6 +46,18 @@ namespace Apewer
}
/// 从 NTP 服务器获取 UTC 时间。
+ ///
+ /// Worldwide: pool.ntp.org
+ /// Asia: asia.pool.ntp.org
+ /// Europe: europe.pool.ntp.org
+ /// North: America north-america.pool.ntp.org
+ /// Oceania: oceania.pool.ntp.org
+ /// South America: south-america.pool.ntp.org
+ /// Windows: time.windows.com
+ /// Windows: time.nist.gov
+ /// China: us.ntp.org.cn
+ /// China: edu.ntp.org.cn
+ ///
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;
}
diff --git a/Apewer/RuntimeUtility.cs b/Apewer/RuntimeUtility.cs
index 2e40033..5116277 100644
--- a/Apewer/RuntimeUtility.cs
+++ b/Apewer/RuntimeUtility.cs
@@ -750,32 +750,43 @@ namespace Apewer
#region Assembly
- /// 获取当前进程程序集的资源。
- public static byte[] GetAssemblyResource(string name)
+ /// 列出当前域中的程序集。
+ public static Assembly[] ListLoadedAssemblies()
{
- var assembly = Assembly.GetExecutingAssembly();
- return GetAssemblyResource(assembly, name);
+ return AppDomain.CurrentDomain.GetAssemblies();
}
- /// 获取指定程序集的资源。
- public static byte[] GetAssemblyResource(Assembly assembly, string name)
+ /// 从指定的程序集加载资源。
+ /// 资源的名称。
+ /// 程序集,为 NULL 值时指向 CallingAssembly。
+ /// 该资源的流,发生错误时返回 NULL 值。
+ /// 此方法不引发异常。
+ 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;
}
- /// 获取已加载的程序集。
- public static Assembly[] GetLoadedAssemblies()
+ /// 从程序集获取资源,读取到内存流。发生错误时返回 NULL 值,不引发异常。
+ /// 资源的名称。
+ /// 程序集,为 NULL 值时指向 CallingAssembly。
+ /// 该资源的流,发生错误时返回 NULL 值。
+ /// 此方法不引发异常。
+ 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
diff --git a/Apewer/Source/ColumnAttribute.cs b/Apewer/Source/ColumnAttribute.cs
index 6c9e04d..da82bf6 100644
--- a/Apewer/Source/ColumnAttribute.cs
+++ b/Apewer/Source/ColumnAttribute.cs
@@ -7,7 +7,7 @@ using System.Text;
namespace Apewer.Source
{
- /// 数据库中的列,类型默认为 NVarChar(255),错误类型将修正为 NText。
+ /// 数据库中的列,类型默认为 NVarChar(191),错误类型将修正为 NText。
[Serializable]
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = true)]
public sealed class ColumnAttribute : Attribute
@@ -25,14 +25,14 @@ namespace Apewer.Source
/// 使用自动的列名称。当类型为 VarChar 或 NVarChar 时必须指定长度。
///
- public ColumnAttribute(ColumnType type = ColumnType.NVarChar255, int length = 0)
+ public ColumnAttribute(ColumnType type = ColumnType.NVarChar, int length = 191)
{
New(null, type, length, true);
}
/// 使用指定的列名称。当类型为 VarChar 或 NVarChar 时必须指定长度。
///
- 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();
}
/// 锁定属性,阻止修改。
diff --git a/Apewer/Source/Record.cs b/Apewer/Source/Record.cs
index e754bfa..dfbb189 100644
--- a/Apewer/Source/Record.cs
+++ b/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();
- /// 记录的创建时间,NVarChar 255 类型,值为执行 INSERT INTO 语句时的时间。
- [Column("_created", ColumnType.NVarChar255)]
- public virtual string Created { get { return _created; } set { _created = TextModifier.Compact(value, 255); } }
+ /// 记录的创建时间,值为执行 INSERT INTO 语句时的时间。
+ [Column("_created", ColumnType.NVarChar, DefaultLength)]
+ public virtual string Created { get { return _created; } set { _created = TextModifier.Compact(value, DefaultLength); } }
- /// 记录的更新时间,NVarChar 255 类型,每次对此记录执行 UPDATE 时应更新此值为当前系统时间。
- [Column("_updated", ColumnType.NVarChar255)]
- public virtual string Updated { get { return _updated; } set { _updated = TextModifier.Compact(value, 255); } }
+ /// 记录的更新时间,类型,每次对此记录执行 UPDATE 时应更新此值为当前系统时间。
+ [Column("_updated", ColumnType.NVarChar, DefaultLength)]
+ public virtual string Updated { get { return _updated; } set { _updated = TextModifier.Compact(value, DefaultLength); } }
/// 记录的标记,Int64 类型,区分记录的状态。
[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); } }
- /// 记录唯一键,NVarChar 128 类型,一般使用 GUID 的字符串形式。
- [Column("_key", ColumnType.NVarChar, 128)]
- public virtual string Key { get { return _key; } set { _key = TextModifier.Compact(value, 128); } }
+ /// 记录唯一键,一般使用 GUID 的字符串形式。
+ [Column("_key", ColumnType.NVarChar, KeyLength)]
+ public virtual string Key { get { return _key; } set { _key = TextModifier.Compact(value, KeyLength); } }
/// 重置主键。
internal static void ResetKey(Record record)
diff --git a/Apewer/Surface/FontInstance.cs b/Apewer/Surface/FontInstance.cs
index 4ea4675..eafec2a 100644
--- a/Apewer/Surface/FontInstance.cs
+++ b/Apewer/Surface/FontInstance.cs
@@ -10,7 +10,7 @@ namespace Apewer.Surface
{
///
- public class FontInstance
+ internal class FontInstance
{
private FontFamily _fontfamily = null;
diff --git a/Apewer/Surface/FormsUtility.cs b/Apewer/Surface/FormsUtility.cs
index fa708bb..a701b47 100644
--- a/Apewer/Surface/FormsUtility.cs
+++ b/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 = "";
-
/// 线程锁。
public static object ThreadLocker = new object();
- /// 存在微软雅黑字体。
- public static bool MsyhExist
+#if NETFX || NETCORE
+
+ /// 窗体启动初始化。
+ [STAThread]
+ public static void StartInitialization()
{
- get { return File.Exists("c:\\windows\\fonts\\msyh.ttc"); }
+ Control.CheckForIllegalCrossThreadCalls = false;
+ Application.EnableVisualStyles();
+ Application.SetCompatibleTextRenderingDefault(false);
}
- /// 获取默认字体名称。
- public static string DefaultFontName
+ /// 禁用跨线程调用检查。
+ 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 颜色。
+
/// 获取所有可枚举的颜色。
public static Color[] EnumerableColor
{
@@ -284,7 +278,7 @@ namespace Apewer.Surface
/// 前景色(基色)。
/// 颜色深度,最大值。
/// 合成后的颜色(基色)。
- 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;
}
- /// 从程序集获取资源。发生错误时返回 NULL 值,不引发异常。
- public static Stream OpenResourceStream(string name, Assembly assembly = null)
+ /// 按 Alpha 混合不透明的颜色。
+ /// 背景色。
+ /// 前景色。
+ /// 前景 Alpha 值。
+ /// 混合后的颜色。
+ 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);
}
- /// 从程序集获取资源,读取到内存流。发生错误时返回 NULL 值,不引发异常。
- 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
- /// 从程序集获取资源,读取到内存流。发生错误时返回 NULL 值,不引发异常。
- 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
- /// 获取默认字体。
- public static Font DefaultFont
+ /// 获取屏幕的截图。
+ public static Bitmap[] ScreenShot()
{
- get { return new Font(DefaultFontName, 9); }
+ var list = new List();
+ 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();
}
- /// 获取大小为 9 的默认字体。
- public static Font NewFont()
+ /// 获取指定屏幕的截图。
+ /// 屏幕号。
+ 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);
}
- /// 获取指定大小的默认字体。
- public static Font NewFont(float size)
+ /// 获取指定屏幕的截图。
+ /// 屏幕,若为 Null 则选择主屏幕。
+ 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);
}
- /// 获取指定大小的默认字体。
- public static Font NewFont(float size, bool bold)
- {
- return new Font(DefaultFontName, size, bold ? FontStyle.Bold : FontStyle.Regular);
- }
+#endif
- /// 窗体启动初始化。
- [STAThread]
- public static void StartInitialization()
- {
- Control.CheckForIllegalCrossThreadCalls = false;
- Application.EnableVisualStyles();
- Application.SetCompatibleTextRenderingDefault(false);
- }
+ #endregion
- /// 禁用跨线程调用检查。
- public static void CrossThread()
- {
- Control.CheckForIllegalCrossThreadCalls = false;
- }
+ #region 窗体。
+
+#if NETFX || NETCORE
/// 移动窗体。
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);
}
- /// 绘制内边框。
- /// 源图像。
- /// 边框颜色。
- public static bool PaintBorder(ref Image image, Color border)
+ /// 将窗体最大化,不覆盖任务栏。
+ /// 窗体。
+ 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;
}
- /// 绘制内边框。
- /// 源图像。
- /// 边框颜色。
- public static bool PaintBorder(ref Bitmap image, Color border)
+ /// 用指定图像绘制窗体,窗体与图像的大小必须一致。
+ /// 要绘制的窗体。
+ /// 要使用的图像。
+ 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);
+ }
- /// 绘制内边框。
- /// 源图像。
- /// 边框颜色。
- /// 背景颜色。
- 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;
}
- /// 建立带有圆角样式的路径。
- /// 建立矩形路径的区域。
- /// 圆角的大小。
- /// 建立的路径。
- public static GraphicsPath CreatePath(Rectangle rect, int radius = 0)
+ /// 为窗体启用阴影。
+ /// 要启用阴影的窗体。
+ 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);
}
/// 恢复任务栏中窗体标题的右键菜单。
@@ -489,6 +486,14 @@ namespace Apewer.Surface
}
}
+#endif
+
+ #endregion
+
+ #region 控件。
+
+#if NETFX || NETCORE
+
/// 在主界面中移动控件,由目标控件取代当前控件,形成切换控件的动画。
/// 当前显示的控件。
/// 将要显示的目标控件。
@@ -556,136 +561,138 @@ namespace Apewer.Surface
current.Visible = false;
}
- /// 将窗体最大化,不覆盖任务栏。
- /// 窗体。
- public static void ToMaximum(Form form)
+ ///
+ 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();
+ }));
}
}
- /// 用指定图像绘制窗体,窗体与图像的大小必须一致。
- /// 要绘制的窗体。
- /// 要使用的图像。
- public static void UpdateShadow(Form form, Image image)
+ ///
+ 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);
+ /// 设置窗体置顶。
+ 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);
- }
+ /// 设置窗体置顶。
+ public static void SetTopMost(Form form, bool value = true)
+ {
+ if (form != null) SetTopMost(form.Handle, value);
}
- /// 为窗体启用阴影。
- /// 要启用阴影的窗体。
- public static void EnableShadow(Form form)
+#endif
+
+ #endregion
+
+ #region 绘图。
+
+#if NETFX || NETCORE
+
+ /// 绘制内边框。
+ /// 源图像。
+ /// 边框颜色。
+ 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;
}
- /// 获取屏幕的截图。
- public static Bitmap[] ScreenShot()
+ /// 绘制内边框。
+ /// 源图像。
+ /// 边框颜色。
+ public static bool PaintBorder(ref Bitmap image, Color border)
{
- var list = new List();
- 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;
}
- /// 获取指定屏幕的截图。
- /// 屏幕号。
- internal static Bitmap ScreenShot(int screen)
+ /// 绘制内边框。
+ /// 源图像。
+ /// 边框颜色。
+ /// 背景颜色。
+ 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;
}
- /// 获取指定屏幕的截图。
- /// 屏幕,若为 Null 则选择主屏幕。
- internal static Bitmap ScreenShot(Screen screen)
+ /// 建立带有圆角样式的路径。
+ /// 建立矩形路径的区域。
+ /// 圆角的大小。
+ /// 建立的路径。
+ 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;
}
///
@@ -731,61 +738,6 @@ namespace Apewer.Surface
return path;
}
- /// 从文件加载字体,并获取字体。
- 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;
- }
-
- ///
- 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();
- }));
- }
- }
-
- ///
- public static void BeginInvoke(Control control, Action action)
- {
- if (control == null || action == null) return;
-
- control.BeginInvoke(new Action(delegate ()
- {
- action.Invoke();
- }));
- }
-
- /// 设置窗体置顶。
- 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);
- }
-
- /// 设置窗体置顶。
- public static void SetTopMost(Form form, bool value = true)
- {
- if (form != null) SetTopMost(form.Handle, value);
- }
-
/// 获取指定文件中的图标总数。
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 = "";
+
+ /// 存在微软雅黑字体。
+ public static bool MsyhExist
+ {
+ get { return File.Exists("c:\\windows\\fonts\\msyh.ttc"); }
+ }
+
+ /// 获取默认字体名称。
+ 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
+
+ /// 获取默认字体。
+ public static Font DefaultFont
+ {
+ get { return new Font(DefaultFontName, 9); }
+ }
+
+ /// 获取大小为 9 的默认字体。
+ public static Font NewFont()
+ {
+ return new Font(DefaultFontName, 9);
+ }
+
+ /// 获取指定大小的默认字体。
+ public static Font NewFont(float size)
+ {
+ return new Font(DefaultFontName, size);
+ }
+
+ /// 获取指定大小的默认字体。
+ public static Font NewFont(float size, bool bold)
+ {
+ return new Font(DefaultFontName, size, bold ? FontStyle.Bold : FontStyle.Regular);
+ }
+
+ /// 从文件加载字体,并获取指定字体。
+ /// 文件路径。
+ /// 文件中的 Font Family 索引,默认取第一个(索引 0)。
+ /// 已存在的 Font Family,如果指定的索引处不存在 Font Family,则返回 NULL 值。
+ 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
+
+ ///
+ public static List ListFileFont(string path)
+ {
+ try
+ {
+ var collection = System.Windows.Media.Fonts.GetFontFamilies(path);
+ var list = new List(collection.Count);
+ foreach (var item in collection) list.Add(item);
+ return list;
+ }
+ catch { }
+ return new List();
+ }
+
+ ///
+ public static List ListSystemFont()
+ {
+ var collection = System.Windows.Media.Fonts.SystemFontFamilies;
+ var list = new List(collection.Count);
+ foreach (var item in collection) list.Add(item);
+ return list;
+ }
+
+ /// 枚举指定字体中的所有字符。
+ public static List EnumerateFontChars(IEnumerable typefaces)
+ {
+ var chars = new List();
+ if (typefaces != null)
+ {
+ foreach (var typeface in typefaces)
+ {
+ var subs = EnumerateFontChars(typeface);
+ if (subs != null) chars.AddRange(subs);
+ }
+ }
+ return chars;
+ }
+
+ /// 枚举指定字体中的所有字符。
+ public static List 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(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
+
+ /// 获取已安装的字体。
+ public static List ListInstalledFonts()
+ {
+ var list = new List();
+ 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
+
}
}
diff --git a/Apewer/Web/ApiProcessor.cs b/Apewer/Web/ApiProcessor.cs
index bcbef68..89a51c6 100644
--- a/Apewer/Web/ApiProcessor.cs
+++ b/Apewer/Web/ApiProcessor.cs
@@ -452,15 +452,15 @@ namespace Apewer.Web
var ps = new List();
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);
}
diff --git a/Apewer/_ChangeLog.md b/Apewer/_ChangeLog.md
index 6f12933..183a601 100644
--- a/Apewer/_ChangeLog.md
+++ b/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 的响应强制缩进排版。