整理代码
This commit is contained in:
21
ShrlAlgoToolkit.RevitAddins/Assists/EnumAssist.cs
Normal file
21
ShrlAlgoToolkit.RevitAddins/Assists/EnumAssist.cs
Normal file
@@ -0,0 +1,21 @@
|
||||
using System.Reflection;
|
||||
|
||||
using ShrlAlgoToolkit.Core.Assists;
|
||||
using ShrlAlgoToolkit;
|
||||
using ShrlAlgoToolkit.Core;
|
||||
|
||||
namespace ShrlAlgoToolkit.RevitAddins.Assists;
|
||||
|
||||
public static class EnumAssist
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取当前枚举值的描述,没有描述则返回空字符串
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
/// <returns></returns>
|
||||
public static T GetAttribute<T>(this Enum value) where T : Attribute
|
||||
{
|
||||
var fieldInfo = value.GetType().GetField(value.ToString());
|
||||
return fieldInfo.GetCustomAttribute<T>();
|
||||
}
|
||||
}
|
||||
142
ShrlAlgoToolkit.RevitAddins/Assists/ImageAssist.cs
Normal file
142
ShrlAlgoToolkit.RevitAddins/Assists/ImageAssist.cs
Normal file
@@ -0,0 +1,142 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Text;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Interop;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
|
||||
using ShrlAlgoToolkit.Core.Assists;
|
||||
using ShrlAlgoToolkit;
|
||||
using ShrlAlgoToolkit.Core;
|
||||
|
||||
namespace ShrlAlgoToolkit.RevitAddins.Assists;
|
||||
|
||||
public static class ImageAssist
|
||||
{
|
||||
/// <summary>
|
||||
/// 提取资源
|
||||
/// </summary>
|
||||
/// <param name="resourceName"></param>
|
||||
/// <param name="path"></param>
|
||||
public static void ExtractResource(string resourceName, string path)
|
||||
{
|
||||
using var manifestResourceStream = Assembly.GetExecutingAssembly().GetManifestResourceStream(resourceName);
|
||||
using var stream = File.Create(path);
|
||||
var array = new byte[8192];
|
||||
int count;
|
||||
while ((count = manifestResourceStream.Read(array, 0, array.Length)) > 0)
|
||||
{
|
||||
stream.Write(array, 0, count);
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 资源的方式转换
|
||||
///<c>var bitmap16 = ImageAssist.CreateIconBitmapSource(BoxIconFont.BxDownload, FontFamily, 16, Brushes.Black, 16, 16);</c>
|
||||
///<c>var floorFinishesPbd = new PushButtonData(</c>
|
||||
///<c> "房间饰面",</c>
|
||||
///<c> "房间饰面",</c>
|
||||
///<c> Variables.AddInPath,</c>
|
||||
///<c> typeof(FloorFinishesCmd).FullName)</c>
|
||||
///<c>{
|
||||
///<c> Image = bitmap16,</c>
|
||||
///<c> LargeImage = bitmap16,</c>
|
||||
///<c>};</c>
|
||||
/// </summary>
|
||||
/// <param name="iconText"></param>
|
||||
/// <param name="fontFamily"></param>
|
||||
/// <param name="fontSize">字体大小</param>
|
||||
/// <param name="foreground">前景色</param>
|
||||
/// <param name="width">宽度</param>
|
||||
/// <param name="height">高度</param>
|
||||
/// <returns></returns>
|
||||
public static BitmapSource CreateIconBitmapSource(string iconText,
|
||||
System.Windows.Media.FontFamily fontFamily,
|
||||
double fontSize,
|
||||
System.Windows.Media.Brush foreground,
|
||||
double width,
|
||||
double height)
|
||||
{
|
||||
var formattedText = new FormattedText(
|
||||
iconText,
|
||||
CultureInfo.InvariantCulture,
|
||||
FlowDirection.LeftToRight,
|
||||
new Typeface(fontFamily, FontStyles.Normal, FontWeights.Normal, FontStretches.Normal),
|
||||
fontSize,
|
||||
foreground,
|
||||
1.0);
|
||||
|
||||
var drawingVisual = new DrawingVisual();
|
||||
using (var drawingContext = drawingVisual.RenderOpen())
|
||||
{
|
||||
var x = (width - formattedText.Width) / 2;
|
||||
var y = (height - formattedText.Height) / 2;
|
||||
drawingContext.DrawText(formattedText, new System.Windows.Point(x, y));
|
||||
}
|
||||
|
||||
var renderTarget = new RenderTargetBitmap((int)Math.Ceiling(width), (int)Math.Ceiling(height), 96, 96, PixelFormats.Pbgra32);
|
||||
renderTarget.Render(drawingVisual);
|
||||
return renderTarget;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 资源管理器缩略图读取
|
||||
/// </summary>
|
||||
/// <param name="filename"></param>
|
||||
/// <param name="width"></param>
|
||||
/// <param name="height"></param>
|
||||
/// <returns></returns>
|
||||
public static BitmapSource LoadFileImage(string filename, int width, int height)
|
||||
{
|
||||
var bm = Assists.WindowsThumbnailProvider.GetThumbnail(filename, width, height, Assists.ThumbnailOptions.None);
|
||||
return Imaging.CreateBitmapSourceFromHBitmap(
|
||||
bm.GetHbitmap(),
|
||||
IntPtr.Zero,
|
||||
Int32Rect.Empty,
|
||||
BitmapSizeOptions.FromEmptyOptions());
|
||||
}
|
||||
/// <summary>
|
||||
/// 输出字体文件的方式转换
|
||||
/// </summary>
|
||||
/// <param name="fontPath">tff文件路径,如Fonts/boxicons.tff</param>
|
||||
/// <param name="unicodeChar">图标的unicode字符串</param>
|
||||
/// <param name="width"></param>
|
||||
/// <param name="height"></param>
|
||||
/// <returns></returns>
|
||||
public static Bitmap RenderIconFontToBitmap(string fontPath, string unicodeChar, int width, int height)
|
||||
{
|
||||
// 加载字体
|
||||
PrivateFontCollection fontCollection = new PrivateFontCollection();
|
||||
fontCollection.AddFontFile(fontPath);
|
||||
System.Drawing.FontFamily fontFamily = fontCollection.Families[0];
|
||||
|
||||
// 创建位图
|
||||
Bitmap bitmap = new Bitmap(width, height);
|
||||
using (Graphics g = Graphics.FromImage(bitmap))
|
||||
{
|
||||
g.Clear(System.Drawing.Color.Transparent);
|
||||
using (Font font = new Font(fontFamily, Math.Min(width, height) / 2))
|
||||
{
|
||||
g.TextRenderingHint = TextRenderingHint.AntiAlias;
|
||||
StringFormat format = new StringFormat
|
||||
{
|
||||
Alignment = StringAlignment.Center,
|
||||
LineAlignment = StringAlignment.Center
|
||||
};
|
||||
g.DrawString(unicodeChar, font, System.Drawing.Brushes.Black, new RectangleF(0, 0, width, height), format);
|
||||
}
|
||||
}
|
||||
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
142
ShrlAlgoToolkit.RevitAddins/Assists/LogAssist.cs
Normal file
142
ShrlAlgoToolkit.RevitAddins/Assists/LogAssist.cs
Normal file
@@ -0,0 +1,142 @@
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
|
||||
using ShrlAlgoToolkit.Core.Assists;
|
||||
using ShrlAlgoToolkit;
|
||||
using ShrlAlgoToolkit.Core;
|
||||
|
||||
namespace ShrlAlgoToolkit.RevitAddins.Assists;
|
||||
|
||||
public static class LogAssist
|
||||
{
|
||||
//public static void WriteSeriLog(string path, string message)
|
||||
//{
|
||||
// Log.Logger = new LoggerConfiguration().WriteTo.File(path).CreateLogger();
|
||||
// Log.Error(message);
|
||||
// Log.CloseAndFlush();
|
||||
//}
|
||||
public static void ToLog(this string strLog, string logFolder = default)
|
||||
{
|
||||
if (logFolder == default)
|
||||
{
|
||||
var assemblyPath = typeof(Assists.LogAssist).Assembly.Location;
|
||||
var directory = Path.GetDirectoryName(assemblyPath);
|
||||
logFolder = Path.Combine(directory, "Logs");
|
||||
}
|
||||
|
||||
if (!Directory.Exists(logFolder))
|
||||
{
|
||||
Directory.CreateDirectory(logFolder);
|
||||
}
|
||||
//logFolder = Directory.GetCurrentDirectory();返回是Revit目录
|
||||
var logFile = Path.Combine(logFolder, DateTime.Now.ToString("yyyy-MM-dd") + ".log");
|
||||
|
||||
var fs = File.Exists(logFile)
|
||||
? new FileStream(logFile, FileMode.Append, FileAccess.Write)
|
||||
: new FileStream(logFile, FileMode.Create, FileAccess.Write);
|
||||
|
||||
using StreamWriter sw = new(fs);
|
||||
sw.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH-mm-ss-ffff : ") + strLog);
|
||||
sw.Close();
|
||||
fs.Close();
|
||||
}
|
||||
|
||||
public static void ToLog(this Exception execption, string logFolder = default)
|
||||
{
|
||||
if (logFolder == default)
|
||||
{
|
||||
var assemblyPath = typeof(Assists.LogAssist).Assembly.Location;
|
||||
var directory = Path.GetDirectoryName(assemblyPath);
|
||||
logFolder = $"{directory}\\Logs";
|
||||
}
|
||||
|
||||
if (Directory.Exists(logFolder))
|
||||
{
|
||||
logFolder = Directory.GetCurrentDirectory();
|
||||
}
|
||||
else
|
||||
{
|
||||
Directory.CreateDirectory(logFolder);
|
||||
}
|
||||
|
||||
var logFile = Path.Combine(logFolder, DateTime.Now.ToString("yyyy-MM-dd") + ".log");
|
||||
|
||||
var fs = File.Exists(logFile)
|
||||
? new FileStream(logFile, FileMode.Append, FileAccess.Write)
|
||||
: new FileStream(logFile, FileMode.Create, FileAccess.Write);
|
||||
|
||||
using StreamWriter sw = new(fs);
|
||||
sw.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH-mm-ss-ffff : ") + execption.Message);
|
||||
sw.Close();
|
||||
fs.Close();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 输出到桌面
|
||||
/// </summary>
|
||||
/// <param name="sb"></param>
|
||||
/// <param name="fileName"></param>
|
||||
public static void WriteTextFile(this StringBuilder sb, string fileName = "输出日志")
|
||||
{
|
||||
var filePath = Environment.GetFolderPath(Environment.SpecialFolder.Desktop) + $"\\{fileName}.txt";
|
||||
File.WriteAllText(filePath, sb.ToString());
|
||||
System.Diagnostics.Process.Start(filePath);
|
||||
}
|
||||
|
||||
public static void WriteTextFile(this string lineContent, string filePath)
|
||||
{
|
||||
FileStream fs = new(filePath, FileMode.Create, FileAccess.Write);
|
||||
using StreamWriter sw = new(fs);
|
||||
sw.WriteLine(lineContent);
|
||||
sw.Close();
|
||||
fs.Close();
|
||||
}
|
||||
|
||||
public static string GetCurrentMethodFullName()
|
||||
{
|
||||
string str1;
|
||||
try
|
||||
{
|
||||
var num = 2;
|
||||
StackTrace stackTrace = new();
|
||||
var length = stackTrace.GetFrames()!.Length;
|
||||
StackFrame frame;
|
||||
string str;
|
||||
bool flag;
|
||||
do
|
||||
{
|
||||
var num1 = num;
|
||||
num = num1 + 1;
|
||||
frame = stackTrace.GetFrame(num1);
|
||||
str = frame.GetMethod().DeclaringType?.ToString();
|
||||
flag = str!.EndsWith("Exception") && num < length;
|
||||
} while (flag);
|
||||
|
||||
var name = frame.GetMethod().Name;
|
||||
str1 = string.Concat(str, ".", name);
|
||||
}
|
||||
catch
|
||||
{
|
||||
str1 = null;
|
||||
}
|
||||
|
||||
return str1;
|
||||
}
|
||||
|
||||
public static string ToChineseMessage(this Exception ex)
|
||||
{
|
||||
while (ex.InnerException != null)
|
||||
{
|
||||
ex = ex.InnerException;
|
||||
}
|
||||
|
||||
var t = ex.GetType();
|
||||
var currentUICulture = System.Threading.Thread.CurrentThread.CurrentUICulture;
|
||||
System.Threading.Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo("zh-CN");
|
||||
var o = Activator.CreateInstance(t);
|
||||
System.Threading.Thread.CurrentThread.CurrentUICulture = currentUICulture;
|
||||
|
||||
return ((Exception)o).Message;
|
||||
}
|
||||
}
|
||||
37
ShrlAlgoToolkit.RevitAddins/Assists/SingletonViewAssist.cs
Normal file
37
ShrlAlgoToolkit.RevitAddins/Assists/SingletonViewAssist.cs
Normal file
@@ -0,0 +1,37 @@
|
||||
using System.Windows;
|
||||
|
||||
using ShrlAlgoToolkit.Core.Assists;
|
||||
using ShrlAlgoToolkit;
|
||||
using ShrlAlgoToolkit.Core;
|
||||
|
||||
namespace ShrlAlgoToolkit.RevitAddins.Assists;
|
||||
|
||||
public sealed record SingletonViewAssist<T>
|
||||
where T : Window, new()
|
||||
{
|
||||
private static T _instance;
|
||||
private static readonly object Padlock = new();
|
||||
|
||||
private SingletonViewAssist() { }
|
||||
|
||||
public static T GetInstance(out bool isNewCreate)
|
||||
{
|
||||
isNewCreate = false;
|
||||
//double-check locking
|
||||
if (_instance == null)
|
||||
{
|
||||
isNewCreate = true;
|
||||
lock (Padlock)
|
||||
{
|
||||
_instance ??= new T();
|
||||
_instance.Closed += OnWindowClosed;
|
||||
}
|
||||
}
|
||||
return _instance;
|
||||
}
|
||||
|
||||
private static void OnWindowClosed(object sender, EventArgs e)
|
||||
{
|
||||
_instance = null;
|
||||
}
|
||||
}
|
||||
339
ShrlAlgoToolkit.RevitAddins/Assists/StringAssist.cs
Normal file
339
ShrlAlgoToolkit.RevitAddins/Assists/StringAssist.cs
Normal file
@@ -0,0 +1,339 @@
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
using ShrlAlgoToolkit.Core.Assists;
|
||||
using ShrlAlgoToolkit;
|
||||
using ShrlAlgoToolkit.Core;
|
||||
|
||||
namespace ShrlAlgoToolkit.RevitAddins.Assists;
|
||||
|
||||
public class StringAssist
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取大写字母列表
|
||||
/// </summary>
|
||||
/// <param name="n"></param>
|
||||
/// <returns></returns>
|
||||
public List<string> GetChar(int n)
|
||||
{
|
||||
var list = new List<string>();
|
||||
if (n > 26)
|
||||
{
|
||||
n = 26;
|
||||
}
|
||||
|
||||
for (var i = 0; i < n; i++)
|
||||
{
|
||||
var c = ((char)(i + 65)).ToString();
|
||||
list.Add(c);
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 取得中文字符
|
||||
/// </summary>
|
||||
/// <param name="oriText"></param>
|
||||
/// <returns></returns>
|
||||
public static string GetChineseWord(string oriText)
|
||||
{
|
||||
var x = @"[\u4E00-\u9FFF]+";
|
||||
var matches = Regex.Matches(oriText, x, RegexOptions.IgnoreCase);
|
||||
var sb = new StringBuilder();
|
||||
foreach (Match nextMatch in matches)
|
||||
{
|
||||
sb.Append(nextMatch.Value);
|
||||
}
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 固定间隔插入字符
|
||||
/// </summary>
|
||||
/// <param name="input">源字符串</param>
|
||||
/// <param name="interval">间隔</param>
|
||||
/// <param name="value">插入字符</param>
|
||||
/// <returns></returns>
|
||||
public static string InsertFormat(string input, int interval, string value)
|
||||
{
|
||||
for (var i = interval - 1; i < input.Length; i += interval + 1)
|
||||
{
|
||||
input = input.Insert(i, value);
|
||||
}
|
||||
|
||||
return input;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 判断更严谨,包含的有空串("")、空白符(空格""," ",制表符"\t",回车符"\r","\n"等)以及null值;
|
||||
/// </summary>
|
||||
/// <param name="str"></param>
|
||||
/// <returns></returns>
|
||||
public static bool IsBlank(string str)
|
||||
{
|
||||
int strLen;
|
||||
if (str == null || (strLen = str.Length) == 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
for (var i = 0; i < strLen; i++)
|
||||
{
|
||||
if (char.IsWhiteSpace(str.ElementAt(i)) == false)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 是否为Double类型
|
||||
/// </summary>
|
||||
/// <param name="expression"></param>
|
||||
/// <returns></returns>
|
||||
public static bool IsDouble(object expression)
|
||||
{
|
||||
return expression != null && Regex.IsMatch(expression.ToString(), @"^([0-9])[0-9]*(\.\w*)?$");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 判断对象是否为Int32类型的数字
|
||||
/// </summary>
|
||||
/// <param name="expression">The expression<see cref="string" /></param>
|
||||
/// <returns></returns>
|
||||
public static bool IsNumeric(string expression)
|
||||
{
|
||||
if (expression != null)
|
||||
{
|
||||
var str = expression;
|
||||
if (str.Length > 0 && str.Length <= 11 && Regex.IsMatch(str, @"^[-]?[0-9]*[.]?[0-9]*$"))
|
||||
{
|
||||
if (str.Length < 10 || (str.Length == 10 && str[0] == '1') || (str.Length == 11 && str[0] == '-' && str[1] == '1'))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 比较字符串相似度
|
||||
/// </summary>
|
||||
/// <param name="str1"></param>
|
||||
/// <param name="str2"></param>
|
||||
/// <returns></returns>
|
||||
public static float Levenshtein(string str1, string str2)
|
||||
{
|
||||
var len1 = str1.Length;
|
||||
var len2 = str2.Length;
|
||||
var dif = new int[len1 + 1, len2 + 1];
|
||||
for (var a = 0; a <= len1; a++)
|
||||
{
|
||||
dif[a, 0] = a;
|
||||
}
|
||||
|
||||
for (var a = 0; a <= len2; a++)
|
||||
{
|
||||
dif[0, a] = a;
|
||||
}
|
||||
|
||||
int temp;
|
||||
for (var i = 1; i <= len1; i++)
|
||||
{
|
||||
for (var j = 1; j <= len2; j++)
|
||||
{
|
||||
temp = str1.ElementAt(i - 1) == str2.ElementAt(j - 1) ? 0 : 1;
|
||||
|
||||
dif[i, j] = Min(dif[i - 1, j - 1] + temp, dif[i, j - 1] + 1, dif[i - 1, j] + 1);
|
||||
}
|
||||
}
|
||||
|
||||
var similarity = 1 - ((float)dif[len1, len2] / Math.Max(len1, len2));
|
||||
return similarity;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取最短长度
|
||||
/// </summary>
|
||||
/// <param name="arr"></param>
|
||||
/// <returns></returns>
|
||||
private static int Min(params int[] arr)
|
||||
{
|
||||
var min = int.MaxValue;
|
||||
foreach (var i in arr)
|
||||
{
|
||||
if (min > i)
|
||||
{
|
||||
min = i;
|
||||
}
|
||||
}
|
||||
|
||||
return min;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 数字转字母
|
||||
/// </summary>
|
||||
/// <param name="index"></param>
|
||||
/// <returns></returns>
|
||||
public static string NumberToLetter(int index)
|
||||
{
|
||||
var str = string.Empty;
|
||||
if (index >= "ABCDEFGHIJKLMNOPQRSTUVWXYZ".Length)
|
||||
{
|
||||
var num = index / "ABCDEFGHIJKLMNOPQRSTUVWXYZ".Length;
|
||||
index %= "ABCDEFGHIJKLMNOPQRSTUVWXYZ".Length;
|
||||
str += num.ToString();
|
||||
}
|
||||
|
||||
return str + "ABCDEFGHIJKLMNOPQRSTUVWXYZ"[index];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 指定字符串的固定长度,如果字符串小于固定长度,
|
||||
/// 则在字符串的前面补足零,可设置的固定长度最大为9位
|
||||
/// </summary>
|
||||
/// <param name="text">原始字符串</param>
|
||||
/// <param name="limitedLength">字符串的固定长度</param>
|
||||
/// <returns>The <see cref="string" /></returns>
|
||||
public static string RepairZero(string text, int limitedLength)
|
||||
{
|
||||
//补足0的字符串
|
||||
var temp = string.Empty;
|
||||
|
||||
//补足0
|
||||
for (var i = 0; i < limitedLength - text.Length; i++)
|
||||
{
|
||||
temp += "0";
|
||||
}
|
||||
|
||||
//连接text
|
||||
temp += text;
|
||||
|
||||
//返回补足0的字符串
|
||||
return temp;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 使用指定字符集将string转换成byte[]
|
||||
/// </summary>
|
||||
/// <param name="text">要转换的字符串</param>
|
||||
/// <param name="encoding">字符编码</param>
|
||||
public static byte[] StringToBytes(string text, Encoding encoding)
|
||||
{
|
||||
return encoding.GetBytes(text);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// string型转换为decimal型
|
||||
/// </summary>
|
||||
/// <param name="expression">The expression<see cref="string" /></param>
|
||||
/// <param name="defValue">缺省值</param>
|
||||
/// <returns>转换后的decimal类型结果</returns>
|
||||
public static decimal StrToDecimal(string expression, decimal defValue)
|
||||
{
|
||||
if (expression == null || expression.Length > 10)
|
||||
{
|
||||
return defValue;
|
||||
}
|
||||
|
||||
var intValue = defValue;
|
||||
{
|
||||
var isDecimal = Regex.IsMatch(expression, @"^([-]|[0-9])[0-9]*(\.\w*)?$");
|
||||
if (isDecimal)
|
||||
{
|
||||
decimal.TryParse(expression, out intValue);
|
||||
}
|
||||
}
|
||||
|
||||
return intValue;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// string型转换为float型
|
||||
/// </summary>
|
||||
/// <param name="expression">The expression<see cref="string" /></param>
|
||||
/// <param name="defValue">缺省值</param>
|
||||
/// <returns>转换后的int类型结果</returns>
|
||||
public static float StrToFloat(string expression, float defValue)
|
||||
{
|
||||
if (expression == null || expression.Length > 10)
|
||||
{
|
||||
return defValue;
|
||||
}
|
||||
|
||||
var intValue = defValue;
|
||||
{
|
||||
var isFloat = Regex.IsMatch(expression, @"^([-]|[0-9])[0-9]*(\.\w*)?$");
|
||||
if (isFloat)
|
||||
{
|
||||
float.TryParse(expression, out intValue);
|
||||
}
|
||||
}
|
||||
|
||||
return intValue;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将字符串转换为Int32类型
|
||||
/// </summary>
|
||||
/// <param name="expression">要转换的字符串</param>
|
||||
/// <param name="defValue">缺省值</param>
|
||||
/// <returns>转换后的int类型结果</returns>
|
||||
public static int StrToInt(string expression, int defValue)
|
||||
{
|
||||
return string.IsNullOrEmpty(expression) || expression.Trim().Length >= 11 || !Regex.IsMatch(expression.Trim(), @"^([-]|[0-9])[0-9]*(\.\w*)?$")
|
||||
? defValue
|
||||
: int.TryParse(expression, out var rv)
|
||||
? rv
|
||||
: Convert.ToInt32(StrToFloat(expression, defValue));
|
||||
}
|
||||
#region 格式化
|
||||
|
||||
//StringFormat={}{0:C} $123.46
|
||||
//StringFormat={}{0:C1} $123.5
|
||||
//StringFormat=单价:{0:C} 单价:$123.46
|
||||
//StringFormat={}{0}元 123.45678元
|
||||
//StringFormat={}{0:D6} 086723
|
||||
//StringFormat={}{0:F4} 28768234.9329
|
||||
//StringFormat={}{0:N3} 28,768,234.933
|
||||
//StringFormat={}{0:P1} 78.9 %
|
||||
//StringFormat={}{0:0000.00} 0123.46
|
||||
//StringFormat={}{0:####.##} 123.46
|
||||
//StringFormat={}{0:d} 5/4/2015
|
||||
//StringFormat={}{0:D} Monday, May 04, 2015
|
||||
//StringFormat={}{0:f} Monday, May 04, 2015 5:46 PM
|
||||
//StringFormat={}{0:F} Monday, May 04, 2015 5:46:56 PM
|
||||
//StringFormat={}{0:g} 5/4/2015 5:46 PM
|
||||
//StringFormat={}{0:G} 5/4/2015 5:46:56 PM
|
||||
//StringFormat={}{0:m} May 04
|
||||
//StringFormat={}{0:Distinct} May 04
|
||||
//StringFormat={}{0:t} 5:46 PM
|
||||
//StringFormat={}{0:Command} 5:46:56 PM
|
||||
//StringFormat={}{0:yyyy年MM月dd日} 2015年05月04日
|
||||
//StringFormat={}{0:yyyy-MM-dd} 2015-05-04
|
||||
//StringFormat={}{0:yyyy-MM-dd HH:mm} 2015-05-04 17:46
|
||||
//StringFormat={}{0:yyyy-MM-dd HH:mm:ss},,ConverterCulture=zh-CN||StringFormat='yyyy:MM:dd HH:mm:ss',,ConverterCulture=zh-CN 2015-05-04 17:46:56
|
||||
//< TextBox.Text >
|
||||
// < MultiBinding StringFormat = "姓名:{0}	{1}" >
|
||||
// < Binding Path = "FristName" />
|
||||
// < Binding Path = "LastName" />
|
||||
// </ MultiBinding >
|
||||
//</ TextBox.Text >
|
||||
// < !--
|
||||
// \a  BEL
|
||||
// \b  BS - Backspace
|
||||
// \f  FF - Formfeed
|
||||
// \n 
 LF, NL - Linefeed, New Line
|
||||
// \r 
 CR - Carriage return
|
||||
// \t 	 HT - Tab, Horizontal Tabelator
|
||||
// \v  VT - Vertical Tabelator
|
||||
|
||||
#endregion
|
||||
}
|
||||
15
ShrlAlgoToolkit.RevitAddins/Assists/ThumbnailOptions.cs
Normal file
15
ShrlAlgoToolkit.RevitAddins/Assists/ThumbnailOptions.cs
Normal file
@@ -0,0 +1,15 @@
|
||||
using ShrlAlgoToolkit.Core.Assists;
|
||||
using ShrlAlgoToolkit;
|
||||
using ShrlAlgoToolkit.Core;
|
||||
|
||||
namespace ShrlAlgoToolkit.RevitAddins.Assists;
|
||||
|
||||
public enum ThumbnailOptions
|
||||
{
|
||||
None = 0x00,
|
||||
BiggerSizeOk = 0x01,
|
||||
InMemoryOnly = 0x02,
|
||||
IconOnly = 0x04,
|
||||
ThumbnailOnly = 0x08,
|
||||
InCacheOnly = 0x10
|
||||
}
|
||||
471
ShrlAlgoToolkit.RevitAddins/Assists/ValidatorAssist.cs
Normal file
471
ShrlAlgoToolkit.RevitAddins/Assists/ValidatorAssist.cs
Normal file
@@ -0,0 +1,471 @@
|
||||
using System.Globalization;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
using ShrlAlgoToolkit.Core.Assists;
|
||||
using ShrlAlgoToolkit;
|
||||
using ShrlAlgoToolkit.Core;
|
||||
|
||||
namespace ShrlAlgoToolkit.RevitAddins.Assists;
|
||||
|
||||
/// <summary>
|
||||
/// 各种验证帮助类
|
||||
/// </summary>
|
||||
public class ValidatorAssist
|
||||
{
|
||||
/// <summary>
|
||||
/// 截取指定长度字符串
|
||||
/// </summary>
|
||||
/// <param name="inputString">要处理的字符串</param>
|
||||
/// <param name="len">指定长度</param>
|
||||
/// <returns>返回处理后的字符串</returns>
|
||||
public static string ClipString(string inputString, int len)
|
||||
{
|
||||
var isShowFix = false;
|
||||
if (len % 2 == 1)
|
||||
{
|
||||
isShowFix = true;
|
||||
len--;
|
||||
}
|
||||
|
||||
var ascii = new ASCIIEncoding();
|
||||
var tempLen = 0;
|
||||
var tempString = string.Empty;
|
||||
var s = ascii.GetBytes(inputString);
|
||||
for (var i = 0; i < s.Length; i++)
|
||||
{
|
||||
if (s[i] == 63)
|
||||
{
|
||||
tempLen += 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
tempLen += 1;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
tempString += inputString.Substring(i, 1);
|
||||
}
|
||||
catch
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (tempLen > len)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
var mybyte = Encoding.Default.GetBytes(inputString);
|
||||
if (isShowFix && mybyte.Length > len)
|
||||
{
|
||||
tempString += "…";
|
||||
}
|
||||
|
||||
return tempString;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获得两个日期的间隔
|
||||
/// </summary>
|
||||
/// <param name="dateTime1">日期一。</param>
|
||||
/// <param name="dateTime2">日期二。</param>
|
||||
/// <returns>日期间隔TimeSpan。</returns>
|
||||
public static TimeSpan DateDiff(DateTime dateTime1, DateTime dateTime2)
|
||||
{
|
||||
var ts1 = new TimeSpan(dateTime1.Ticks);
|
||||
var ts2 = new TimeSpan(dateTime2.Ticks);
|
||||
var ts = ts1.Subtract(ts2).Duration();
|
||||
return ts;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 格式化日期时间
|
||||
/// </summary>
|
||||
/// <param name="dateTime1">日期时间</param>
|
||||
/// <param name="dateMode">显示模式</param>
|
||||
/// <returns>0-9种模式的日期</returns>
|
||||
public static string FormatDate(DateTime dateTime1, string dateMode)
|
||||
{
|
||||
return dateMode switch
|
||||
{
|
||||
"0" => dateTime1.ToString("yyyy-MM-dd"),
|
||||
"1" => dateTime1.ToString("yyyy-MM-dd HH:mm:ss"),
|
||||
"2" => dateTime1.ToString("yyyy/MM/dd"),
|
||||
"3" => dateTime1.ToString("yyyy年MM月dd日"),
|
||||
"4" => dateTime1.ToString("MM-dd"),
|
||||
"5" => dateTime1.ToString("MM/dd"),
|
||||
"6" => dateTime1.ToString("MM月dd日"),
|
||||
"7" => dateTime1.ToString("yyyy-MM"),
|
||||
"8" => dateTime1.ToString("yyyy/MM"),
|
||||
"9" => dateTime1.ToString("yyyy年MM月"),
|
||||
_ => dateTime1.ToString(CultureInfo.InvariantCulture),
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 得到随机日期
|
||||
/// </summary>
|
||||
/// <param name="time1">起始日期</param>
|
||||
/// <param name="time2">结束日期</param>
|
||||
/// <returns>间隔日期之间的 随机日期</returns>
|
||||
public static DateTime GetRandomTime(DateTime time1, DateTime time2)
|
||||
{
|
||||
var random = new Random();
|
||||
DateTime minTime;
|
||||
|
||||
var ts = new TimeSpan(time1.Ticks - time2.Ticks);
|
||||
|
||||
// 获取两个时间相隔的秒数
|
||||
var dTotalSecontds = ts.TotalSeconds;
|
||||
int iTotalSecontds;
|
||||
|
||||
if (dTotalSecontds > int.MaxValue)
|
||||
{
|
||||
iTotalSecontds = int.MaxValue;
|
||||
}
|
||||
else
|
||||
{
|
||||
iTotalSecontds = dTotalSecontds < int.MinValue ? int.MinValue : (int)dTotalSecontds;
|
||||
}
|
||||
|
||||
if (iTotalSecontds > 0)
|
||||
{
|
||||
minTime = time2;
|
||||
}
|
||||
else if (iTotalSecontds < 0)
|
||||
{
|
||||
minTime = time1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return time1;
|
||||
}
|
||||
|
||||
var maxValue = iTotalSecontds;
|
||||
|
||||
if (iTotalSecontds <= int.MinValue)
|
||||
{
|
||||
maxValue = int.MinValue + 1;
|
||||
}
|
||||
|
||||
var i = random.Next(Math.Abs(maxValue));
|
||||
|
||||
return minTime.AddSeconds(i);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 验证是否包含汉语
|
||||
/// </summary>
|
||||
/// <param name="source">The source<see cref="string" /></param>
|
||||
/// <returns>The <see cref="bool" /></returns>
|
||||
public static bool HasChinese(string source)
|
||||
{
|
||||
return Regex.IsMatch(source, @"[\u4e00-\u9fa5]+", RegexOptions.IgnoreCase);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 全部是中文
|
||||
/// </summary>
|
||||
/// <param name="source"></param>
|
||||
/// <returns></returns>
|
||||
public static bool IsChinese(string source)
|
||||
{
|
||||
return Regex.IsMatch(source, @"^[\u4e00-\u9fa5]+$", RegexOptions.IgnoreCase);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The IsDate
|
||||
/// </summary>
|
||||
/// <param name="str">The str<see cref="string" /></param>
|
||||
/// <returns>The <see cref="bool" /></returns>
|
||||
public static bool IsDate(string str)
|
||||
{
|
||||
//考虑到了4年一度的366天,还有特殊的2月的日期
|
||||
var reg = new Regex(
|
||||
@"^((((1[6-9]|[2-9]\d)\d{2})-(0?[13578]|1[02])-(0?[1-9]|[12]\d|3[01]))|(((1[6-9]|[2-9]\d)\d{2})-(0?[13456789]|1[012])-(0?[1-9]|[12]\d|30))|(((1[6-9]|[2-9]\d)\d{2})-0?2-(0?[1-9]|1\d|2[0-8]))|(((1[6-9]|[2-9]\d)(0[48]|[2468][048]|[13579][26])|((16|[2468][048]|[3579][26])00))-0?2-29-)) (20|21|22|23|[0-1]?\d):[0-5]?\d:[0-5]?\d$"
|
||||
);
|
||||
return reg.IsMatch(str);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 是否为数字型
|
||||
/// </summary>
|
||||
/// <param name="strNumber"></param>
|
||||
/// <returns></returns>
|
||||
public static bool IsDecimal(string strNumber)
|
||||
{
|
||||
return new Regex(@"^([0-9])[0-9]*(\.\w*)?$").IsMatch(strNumber);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 验证是否为整数 如果为空,认为验证不合格 返回false
|
||||
/// </summary>
|
||||
/// <param name="number">要验证的整数</param>
|
||||
/// <returns>The <see cref="bool" /></returns>
|
||||
public static bool IsInt(string number)
|
||||
{
|
||||
//如果为空,认为验证不合格
|
||||
if (IsNullOrEmpty(number))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
//清除要验证字符串中的空格
|
||||
number = number.Trim();
|
||||
|
||||
//模式字符串
|
||||
var pattern = @"^[0-9]+[0-9]*$";
|
||||
|
||||
//验证
|
||||
return Regex.IsMatch(number, pattern);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 是不是Int型的
|
||||
/// </summary>
|
||||
/// <param name="source"></param>
|
||||
/// <returns></returns>
|
||||
public static bool IsIntInRegex(string source)
|
||||
{
|
||||
var regex = new Regex(@"^(-){0,1}\d+$");
|
||||
if (regex.Match(source).Success)
|
||||
{
|
||||
return long.Parse(source) is <= 0x7fffffffL and >= (-2147483648L);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 看字符串的长度是不是在限定数之间 一个中文为两个字符
|
||||
/// </summary>
|
||||
/// <param name="source">字符串</param>
|
||||
/// <param name="begin">大于等于</param>
|
||||
/// <param name="end">小于等于</param>
|
||||
/// <returns></returns>
|
||||
public static bool IsLengthStr(string source, int begin, int end)
|
||||
{
|
||||
var length = Regex.Replace(source, @"[^\x00-\xff]", "OK").Length;
|
||||
return length > begin || length < end;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 验证是不是正常字符 字母,数字,下划线的组合
|
||||
/// </summary>
|
||||
/// <param name="source"></param>
|
||||
/// <returns></returns>
|
||||
public static bool IsNormalChar(string source)
|
||||
{
|
||||
return Regex.IsMatch(source, @"[\w\d_]+", RegexOptions.IgnoreCase);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 判断对象是否为空,为空返回true
|
||||
/// </summary>
|
||||
/// <typeparam name="T">要验证的对象的类型</typeparam>
|
||||
/// <param name="data">要验证的对象</param>
|
||||
/// <returns>The <see cref="bool" /></returns>
|
||||
public static bool IsNullOrEmpty<T>(T data)
|
||||
{
|
||||
//如果为null
|
||||
if (data == null)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
//如果为""
|
||||
if (data is string)
|
||||
{
|
||||
if (string.IsNullOrEmpty(data.ToString().Trim()))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
//如果为DBNull
|
||||
if (data is DBNull)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
//不为空
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 判断对象是否为空,为空返回true
|
||||
/// </summary>
|
||||
/// <param name="data">要验证的对象</param>
|
||||
/// <returns>The <see cref="bool" /></returns>
|
||||
public static bool IsNullOrEmpty(object data)
|
||||
{
|
||||
//如果为null
|
||||
if (data == null)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
//如果为""
|
||||
if (data is string)
|
||||
{
|
||||
if (string.IsNullOrEmpty(data.ToString().Trim()))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
//如果为DBNull
|
||||
if (data is DBNull)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
//不为空
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 判断字符串是否为数字
|
||||
/// </summary>
|
||||
/// <param name="str">待验证的字符窜</param>
|
||||
/// <returns>bool</returns>
|
||||
public static bool IsNumber(string str)
|
||||
{
|
||||
return str.All(ar => char.IsNumber(ar));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 验证是否为数字
|
||||
/// </summary>
|
||||
/// <param name="number">要验证的数字</param>
|
||||
/// <returns>The <see cref="bool" /></returns>
|
||||
public static bool IsNumberInRegex(string number)
|
||||
{
|
||||
//如果为空,认为验证不合格
|
||||
if (IsNullOrEmpty(number))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
//清除要验证字符串中的空格
|
||||
number = number.Trim();
|
||||
|
||||
//模式字符串
|
||||
var pattern = @"^[0-9]+[0-9]*[.]?[0-9]*$";
|
||||
|
||||
//验证
|
||||
return Regex.IsMatch(number, pattern);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 检测客户输入的字符串是否有效,并将原始字符串修改为有效字符串或空字符串。
|
||||
/// 当检测到客户的输入中有攻击性危险字符串,则返回false,有效返回true。
|
||||
/// </summary>
|
||||
/// <param name="input">要检测的字符串</param>
|
||||
/// <returns>The <see cref="bool" /></returns>
|
||||
public static bool IsValidInput(ref string input)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (IsNullOrEmpty(input))
|
||||
{
|
||||
//如果是空值,则跳出
|
||||
return true;
|
||||
}
|
||||
|
||||
//替换单引号
|
||||
input = input.Replace("'", "''").Trim();
|
||||
|
||||
//检测攻击性危险字符串
|
||||
var testString = "and |or |exec |insert |select |delete |update |count |chr |mid |master |truncate |char |declare ";
|
||||
var testArray = testString.Split('|');
|
||||
foreach (var testStr in testArray)
|
||||
{
|
||||
if (input.ToLower().IndexOf(testStr, StringComparison.Ordinal) != -1)
|
||||
{
|
||||
//检测到攻击字符串,清空传入的值
|
||||
input = string.Empty;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
//未检测到攻击字符串
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new Exception(ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 得到字符串长度,一个汉字长度为2
|
||||
/// </summary>
|
||||
/// <param name="inputString">参数字符串</param>
|
||||
/// <returns></returns>
|
||||
public static int StrLength(string inputString)
|
||||
{
|
||||
var ascii = new ASCIIEncoding();
|
||||
var tempLen = 0;
|
||||
var s = ascii.GetBytes(inputString);
|
||||
for (var i = 0; i < s.Length; i++)
|
||||
{
|
||||
if (s[i] == 63)
|
||||
{
|
||||
tempLen += 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
tempLen += 1;
|
||||
}
|
||||
}
|
||||
|
||||
return tempLen;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The IsValidByte
|
||||
/// </summary>
|
||||
/// <param name="strIn">The strIn<see cref="string" /></param>
|
||||
/// <returns>The <see cref="bool" /></returns>
|
||||
internal bool IsValidByte(string strIn)
|
||||
{
|
||||
return Regex.IsMatch(strIn, @"^[a-z]{4,12}$");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The IsValidDate
|
||||
/// </summary>
|
||||
/// <param name="strIn">The strIn<see cref="string" /></param>
|
||||
/// <returns>The <see cref="bool" /></returns>
|
||||
internal bool IsValidDate(string strIn)
|
||||
{
|
||||
return Regex.IsMatch(
|
||||
strIn,
|
||||
@"^2d{3}-(?:0?[1-9]|1[0-2])-(?:0?[1-9]|[1-2]d|3[0-1])(?:0?[1-9]|1d|2[0-3]):(?:0?[1-9]|[1-5]d):(?:0?[1-9]|[1-5]d)$"
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The IsValidDecimal
|
||||
/// </summary>
|
||||
/// <param name="strIn">The strIn<see cref="string" /></param>
|
||||
/// <returns>The <see cref="bool" /></returns>
|
||||
internal bool IsValidDecimal(string strIn)
|
||||
{
|
||||
return Regex.IsMatch(strIn, @"[0].d{1,2}|[1]");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The IsValidPostfix
|
||||
/// </summary>
|
||||
/// <param name="strIn">The strIn<see cref="string" /></param>
|
||||
/// <returns>The <see cref="bool" /></returns>
|
||||
internal bool IsValidPostfix(string strIn)
|
||||
{
|
||||
return Regex.IsMatch(strIn, @".(?i:gif|jpg)$");
|
||||
}
|
||||
}
|
||||
@@ -194,7 +194,7 @@ public static class WinDialogAssist
|
||||
where T : Window, new()
|
||||
{
|
||||
AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve;
|
||||
var view = SingletonViewAssist<T>.GetInstance(out var isNewCreate);
|
||||
var view = Assists.SingletonViewAssist<T>.GetInstance(out var isNewCreate);
|
||||
if (isNewCreate)
|
||||
{
|
||||
view.DataContext = viewModel;
|
||||
|
||||
188
ShrlAlgoToolkit.RevitAddins/Assists/WindowsThumbnailProvider.cs
Normal file
188
ShrlAlgoToolkit.RevitAddins/Assists/WindowsThumbnailProvider.cs
Normal file
@@ -0,0 +1,188 @@
|
||||
using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
using ShrlAlgoToolkit.Core.Assists;
|
||||
using ShrlAlgoToolkit;
|
||||
using ShrlAlgoToolkit.Core;
|
||||
|
||||
namespace ShrlAlgoToolkit.RevitAddins.Assists;
|
||||
|
||||
/// <summary>
|
||||
/// 获取Windows缩略图
|
||||
/// </summary>
|
||||
public class WindowsThumbnailProvider
|
||||
{
|
||||
private const string ShellItem2Guid = "7E9FB0D3-919F-4307-AB2E-9B1860310C93";
|
||||
|
||||
public static Bitmap CreateAlphaBitmap(Bitmap srcBitmap, PixelFormat targetPixelFormat)
|
||||
{
|
||||
var result = new Bitmap(srcBitmap.Width, srcBitmap.Height, targetPixelFormat);
|
||||
|
||||
var bmpBounds = new System.Drawing.Rectangle(0, 0, srcBitmap.Width, srcBitmap.Height);
|
||||
|
||||
var srcData = srcBitmap.LockBits(bmpBounds, ImageLockMode.ReadOnly, srcBitmap.PixelFormat);
|
||||
|
||||
var isAlplaBitmap = false;
|
||||
|
||||
try
|
||||
{
|
||||
for (var y = 0; y <= srcData.Height - 1; y++)
|
||||
{
|
||||
for (var x = 0; x <= srcData.Width - 1; x++)
|
||||
{
|
||||
var pixelColor = System.Drawing.Color.FromArgb(Marshal.ReadInt32(srcData.Scan0, (srcData.Stride * y) + (4 * x)));
|
||||
|
||||
if ((pixelColor.A > 0) & (pixelColor.A < 255))
|
||||
{
|
||||
isAlplaBitmap = true;
|
||||
}
|
||||
|
||||
result.SetPixel(x, y, pixelColor);
|
||||
}
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
srcBitmap.UnlockBits(srcData);
|
||||
}
|
||||
|
||||
return isAlplaBitmap ? result : srcBitmap;
|
||||
}
|
||||
|
||||
public static Bitmap GetBitmapFromHBitmap(IntPtr nativeHBitmap)
|
||||
{
|
||||
var bmp = Image.FromHbitmap(nativeHBitmap);
|
||||
|
||||
return Image.GetPixelFormatSize(bmp.PixelFormat) < 32 ? bmp : CreateAlphaBitmap(bmp, PixelFormat.Format32bppArgb);
|
||||
}
|
||||
|
||||
public static Bitmap GetThumbnail(string fileName, int width, int height, ThumbnailOptions options)
|
||||
{
|
||||
var hBitmap = GetHBitmap(Path.GetFullPath(fileName), width, height, options);
|
||||
|
||||
try
|
||||
{
|
||||
// return a System.Drawing.Bitmap from the hBitmap
|
||||
return GetBitmapFromHBitmap(hBitmap);
|
||||
}
|
||||
finally
|
||||
{
|
||||
// delete HBitmap to avoid memory leaks
|
||||
DeleteObject(hBitmap);
|
||||
}
|
||||
}
|
||||
|
||||
[DllImport("gdi32.dll")]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
internal static extern bool DeleteObject(IntPtr hObject);
|
||||
|
||||
[DllImport("shell32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
|
||||
internal static extern int SHCreateItemFromParsingName(
|
||||
[MarshalAs(UnmanagedType.LPWStr)] string path,
|
||||
// The following parameter is not used - binding context.
|
||||
IntPtr pbc,
|
||||
ref Guid riid,
|
||||
[MarshalAs(UnmanagedType.Interface)] out Assists.WindowsThumbnailProvider.IShellItem shellItem
|
||||
);
|
||||
|
||||
private static IntPtr GetHBitmap(string fileName, int width, int height, ThumbnailOptions options)
|
||||
{
|
||||
var shellItem2Guid = new Guid(ShellItem2Guid);
|
||||
var retCode = SHCreateItemFromParsingName(fileName, IntPtr.Zero, ref shellItem2Guid, out var nativeShellItem);
|
||||
|
||||
if (retCode != 0)
|
||||
{
|
||||
throw Marshal.GetExceptionForHR(retCode);
|
||||
}
|
||||
|
||||
var nativeSize = new Assists.WindowsThumbnailProvider.NativeSize { Width = width, Height = height };
|
||||
|
||||
var hr = ((Assists.WindowsThumbnailProvider.IShellItemImageFactory)nativeShellItem).GetImage(nativeSize, options, out var hBitmap);
|
||||
|
||||
Marshal.ReleaseComObject(nativeShellItem);
|
||||
|
||||
return hr == Assists.WindowsThumbnailProvider.HResult.Ok ? hBitmap : throw Marshal.GetExceptionForHR((int)hr);
|
||||
}
|
||||
|
||||
internal enum HResult
|
||||
{
|
||||
Ok = 0x0000,
|
||||
False = 0x0001,
|
||||
InvalidArguments = unchecked((int)0x80070057),
|
||||
OutOfMemory = unchecked((int)0x8007000E),
|
||||
NoInterface = unchecked((int)0x80004002),
|
||||
Fail = unchecked((int)0x80004005),
|
||||
ElementNotFound = unchecked((int)0x80070490),
|
||||
TypeElementNotFound = unchecked((int)0x8002802B),
|
||||
NoObject = unchecked((int)0x800401E5),
|
||||
Win32ErrorCanceled = 1223,
|
||||
Canceled = unchecked((int)0x800704C7),
|
||||
ResourceInUse = unchecked((int)0x800700AA),
|
||||
AccessDenied = unchecked((int)0x80030005)
|
||||
}
|
||||
|
||||
[ComImport]
|
||||
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
|
||||
[Guid("43826d1e-e718-42ee-bc55-a1e261c37bfe")]
|
||||
internal interface IShellItem
|
||||
{
|
||||
void BindToHandler(IntPtr pbc, [MarshalAs(UnmanagedType.LPStruct)] Guid bhid, [MarshalAs(UnmanagedType.LPStruct)] Guid riid, out IntPtr ppv);
|
||||
|
||||
void Compare(Assists.WindowsThumbnailProvider.IShellItem psi, uint hint, out int piOrder);
|
||||
|
||||
void GetAttributes(uint sfgaoMask, out uint psfgaoAttribs);
|
||||
|
||||
void GetDisplayName(Assists.WindowsThumbnailProvider.SIGDN sigdnName, out IntPtr ppszName);
|
||||
|
||||
void GetParent(out Assists.WindowsThumbnailProvider.IShellItem ppsi);
|
||||
}
|
||||
|
||||
[ComImport]
|
||||
[Guid("bcc18b79-ba16-442f-80c4-8a59c30c463b")]
|
||||
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
|
||||
internal interface IShellItemImageFactory
|
||||
{
|
||||
[PreserveSig]
|
||||
Assists.WindowsThumbnailProvider.HResult GetImage([In] [MarshalAs(UnmanagedType.Struct)] Assists.WindowsThumbnailProvider.NativeSize size, [In] ThumbnailOptions flags, [Out] out IntPtr phbm);
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal struct NativeSize
|
||||
{
|
||||
private int width;
|
||||
private int height;
|
||||
|
||||
public int Width
|
||||
{
|
||||
set => width = value;
|
||||
}
|
||||
|
||||
public int Height
|
||||
{
|
||||
set => height = value;
|
||||
}
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct RGBQUAD
|
||||
{
|
||||
public byte rgbBlue;
|
||||
public byte rgbGreen;
|
||||
public byte rgbRed;
|
||||
public byte rgbReserved;
|
||||
}
|
||||
|
||||
internal enum SIGDN : uint
|
||||
{
|
||||
NORMALDISPLAY = 0,
|
||||
PARENTRELATIVEPARSING = 0x80018001,
|
||||
PARENTRELATIVEFORADDRESSBAR = 0x8001c001,
|
||||
DESKTOPABSOLUTEPARSING = 0x80028000,
|
||||
PARENTRELATIVEEDITING = 0x80031001,
|
||||
DESKTOPABSOLUTEEDITING = 0x8004c000,
|
||||
FILESYSPATH = 0x80058000,
|
||||
URL = 0x80068000
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user