using System; using System.Drawing; using System.Drawing.Drawing2D; using System.IO; using System.Windows.Forms; namespace PaintDotNet { /// /// Defines miscellaneous constants and static functions. /// public sealed class Utility { private Utility() { } public static Keys LetterOrDigitCharToKeys(char c) { if (c >= 'a' && c <= 'z') { return (Keys)((int)(c - 'a') + (int)Keys.A); } else if (c >= 'A' && c <= 'Z') { return (Keys)((int)(c - 'A') + (int)Keys.A); } else if (c >= '0' && c <= '9') { return (Keys)((int)(c - '0') + (int)Keys.D0); } else { return Keys.None; } } public static Control FindFocus() { foreach (Form form in Application.OpenForms) { Control focused = FindFocus(form); if (focused != null) { return focused; } } return null; } private static Control FindFocus(Control c) { if (c.Focused) { return c; } foreach (Control child in c.Controls) { Control f = FindFocus(child); if (f != null) { return f; } } return null; } public static void DrawColorRectangle(Graphics g, Rectangle rect, Color color, bool drawBorder) { int inflateAmt = drawBorder ? -2 : 0; Rectangle colorRectangle = Rectangle.Inflate(rect, inflateAmt, inflateAmt); Brush colorBrush = new LinearGradientBrush(colorRectangle, Color.FromArgb(255, color), color, 90.0f, false); HatchBrush backgroundBrush = new HatchBrush(HatchStyle.LargeCheckerBoard, Color.FromArgb(191, 191, 191), Color.FromArgb(255, 255, 255)); if (drawBorder) { g.DrawRectangle(Pens.Black, rect.Left, rect.Top, rect.Width - 1, rect.Height - 1); g.DrawRectangle(Pens.White, rect.Left + 1, rect.Top + 1, rect.Width - 3, rect.Height - 3); } PixelOffsetMode oldPOM = g.PixelOffsetMode; g.PixelOffsetMode = PixelOffsetMode.Half; g.FillRectangle(backgroundBrush, colorRectangle); g.FillRectangle(colorBrush, colorRectangle); g.PixelOffsetMode = oldPOM; backgroundBrush.Dispose(); colorBrush.Dispose(); } public static Font CreateFont(string name, float size, FontStyle style) { Font returnFont; try { returnFont = new Font(name, size, style); } catch (Exception) { returnFont = new Font(FontFamily.GenericSansSerif, size); } return returnFont; } public static readonly Color TransparentKey = Color.FromArgb(192, 192, 192); private static bool allowGCFullCollect = true; public static bool AllowGCFullCollect { get { return allowGCFullCollect; } set { allowGCFullCollect = value; } } public static void GCFullCollect() { if (AllowGCFullCollect) { GC.Collect(); GC.WaitForPendingFinalizers(); GC.Collect(); GC.WaitForPendingFinalizers(); } } public static bool IsArrowKey(Keys keyData) { Keys key = keyData & Keys.KeyCode; if (key == Keys.Up || key == Keys.Down || key == Keys.Left || key == Keys.Right) { return true; } else { return false; } } public static bool DoesControlHaveMouseCaptured(Control control) { bool result = false; result |= control.Capture; foreach (Control c in control.Controls) { result |= DoesControlHaveMouseCaptured(c); } return result; } public static void SplitRectangle(Rectangle rect, Rectangle[] rects) { int height = rect.Height; for (int i = 0; i < rects.Length; ++i) { Rectangle newRect = Rectangle.FromLTRB(rect.Left, rect.Top + ((height * i) / rects.Length), rect.Right, rect.Top + ((height * (i + 1)) / rects.Length)); rects[i] = newRect; } } public static bool CheckNumericUpDown(NumericUpDown upDown) { int a; bool result = int.TryParse(upDown.Text, out a); if (result && (a <= (int)upDown.Maximum) && (a >= (int)upDown.Minimum)) { return true; } else { return false; } } public static void SetNumericUpDownValue(NumericUpDown upDown, decimal newValue) { if (upDown.Value != newValue) { upDown.Value = newValue; } } public static void SetNumericUpDownValue(NumericUpDown upDown, int newValue) { SetNumericUpDownValue(upDown, (decimal)newValue); } public static void ErrorBox(IWin32Window parent, string message) { MessageBox.Show(parent, message, PdnInfo.GetBareProductName(), MessageBoxButtons.OK, MessageBoxIcon.Error); } public static DialogResult AskYesNo(IWin32Window parent, string question) { return MessageBox.Show(parent, question, PdnInfo.GetBareProductName(), MessageBoxButtons.YesNo, MessageBoxIcon.Question); } public static Icon ImageToIcon(Image image) { return ImageToIcon(image, Utility.TransparentKey); } public static Icon ImageToIcon(Image image, bool disposeImage) { return ImageToIcon(image, Utility.TransparentKey, disposeImage); } public static Icon ImageToIcon(Image image, Color seeThru) { return ImageToIcon(image, seeThru, false); } /// /// Converts an Image to an Icon. /// /// The Image to convert to an icon. Must be an appropriate icon size (32x32, 16x16, etc). /// The color that will be treated as transparent in the icon. /// Whether or not to dispose the passed-in Image. /// An Icon representation of the Image. public static Icon ImageToIcon(Image image, Color seeThru, bool disposeImage) { Bitmap bitmap = new Bitmap(image); for (int y = 0; y < bitmap.Height; ++y) { for (int x = 0; x < bitmap.Width; ++x) { if (bitmap.GetPixel(x, y) == seeThru) { bitmap.SetPixel(x, y, Color.FromArgb(0)); } } } Icon icon = Icon.FromHandle(bitmap.GetHicon()); bitmap.Dispose(); if (disposeImage) { image.Dispose(); } return icon; } /// /// Converts a RectangleF to RectangleF by rounding down the Location and rounding /// up the Size. /// public static Rectangle RoundRectangle(RectangleF rectF) { float left = (float)Math.Floor(rectF.Left); float top = (float)Math.Floor(rectF.Top); float right = (float)Math.Ceiling(rectF.Right); float bottom = (float)Math.Ceiling(rectF.Bottom); return Rectangle.Truncate(RectangleF.FromLTRB(left, top, right, bottom)); } /// /// Allows you to find the bounding box for a "region" that is described as an /// array of bounding boxes. /// /// The "region" you want to find a bounding box for. /// A RectangleF structure that surrounds the Region. public static RectangleF GetRegionBounds(RectangleF[] rectsF, int startIndex, int length) { if (rectsF.Length == 0) { return RectangleF.Empty; } float left = rectsF[startIndex].Left; float top = rectsF[startIndex].Top; float right = rectsF[startIndex].Right; float bottom = rectsF[startIndex].Bottom; for (int i = startIndex + 1; i < startIndex + length; ++i) { RectangleF rectF = rectsF[i]; if (rectF.Left < left) { left = rectF.Left; } if (rectF.Top < top) { top = rectF.Top; } if (rectF.Right > right) { right = rectF.Right; } if (rectF.Bottom > bottom) { bottom = rectF.Bottom; } } return RectangleF.FromLTRB(left, top, right, bottom); } /// /// Allows you to find the bounding box for a "region" that is described as an /// array of bounding boxes. /// /// The "region" you want to find a bounding box for. /// A RectangleF structure that surrounds the Region. public static Rectangle GetRegionBounds(Rectangle[] rects, int startIndex, int length) { if (rects.Length == 0) { return Rectangle.Empty; } int left = rects[startIndex].Left; int top = rects[startIndex].Top; int right = rects[startIndex].Right; int bottom = rects[startIndex].Bottom; for (int i = startIndex + 1; i < startIndex + length; ++i) { Rectangle rect = rects[i]; if (rect.Left < left) { left = rect.Left; } if (rect.Top < top) { top = rect.Top; } if (rect.Right > right) { right = rect.Right; } if (rect.Bottom > bottom) { bottom = rect.Bottom; } } return Rectangle.FromLTRB(left, top, right, bottom); } public static double Clamp(double x, double min, double max) { if (x < min) { return min; } else if (x > max) { return max; } else { return x; } } public static int Clamp(int x, int min, int max) { if (x < min) { return min; } else if (x > max) { return max; } else { return x; } } public static byte ClampToByte(double x) { if (x > 255) { return 255; } else if (x < 0) { return 0; } else { return (byte)x; } } public static byte ClampToByte(float x) { if (x > 255) { return 255; } else if (x < 0) { return 0; } else { return (byte)x; } } public static byte ClampToByte(int x) { if (x > 255) { return 255; } else if (x < 0) { return 0; } else { return (byte)x; } } public static float Lerp(float from, float to, float frac) { return (from + frac * (to - from)); } public static double Lerp(double from, double to, double frac) { return (from + frac * (to - from)); } public static void ShowHelp(Control parent,int type) { //string helpFileUrlFormat = PdnResources.GetString("HelpFile.Url.Format"); //string baseSiteUrl = Application.StartupPath + @"\最新显微镜图像处理与分析系统 (修正版本)20210206.chm";//InvariantStrings.WebsiteUrl; //string helpFileUrl = baseSiteUrl;// string.Format(helpFileUrlFormat, baseSiteUrl); string filePath = Application.StartupPath + @"\最新显微镜图像处理与分析系统 (修正版本)20210206.chm"; if (!System.IO.File.Exists(filePath)) { return; } if (type == 1) { Help.ShowHelp(parent, filePath); } else { Help.ShowHelp(parent, filePath, HelpNavigator.Index); } //JScript\JScript //PdnInfo.OpenUrl(parent, helpFileUrl); } /// /// Reads a 16-bit unsigned integer from a Stream in little-endian format. /// /// /// -1 on failure, else the 16-bit unsigned integer that was read. public static int ReadUInt16(Stream stream) { int byte1 = stream.ReadByte(); if (byte1 == -1) { return -1; } int byte2 = stream.ReadByte(); if (byte2 == -1) { return -1; } return byte1 + (byte2 << 8); } public static void WriteUInt16(Stream stream, UInt16 word) { stream.WriteByte((byte)(word & 0xff)); stream.WriteByte((byte)(word >> 8)); } public static void WriteUInt24(Stream stream, int uint24) { stream.WriteByte((byte)(uint24 & 0xff)); stream.WriteByte((byte)((uint24 >> 8) & 0xff)); stream.WriteByte((byte)((uint24 >> 16) & 0xff)); } public static void WriteUInt32(Stream stream, UInt32 uint32) { stream.WriteByte((byte)(uint32 & 0xff)); stream.WriteByte((byte)((uint32 >> 8) & 0xff)); stream.WriteByte((byte)((uint32 >> 16) & 0xff)); stream.WriteByte((byte)((uint32 >> 24) & 0xff)); } /// /// Reads a 24-bit unsigned integer from a Stream in little-endian format. /// /// /// -1 on failure, else the 24-bit unsigned integer that was read. public static int ReadUInt24(Stream stream) { int byte1 = stream.ReadByte(); if (byte1 == -1) { return -1; } int byte2 = stream.ReadByte(); if (byte2 == -1) { return -1; } int byte3 = stream.ReadByte(); if (byte3 == -1) { return -1; } return byte1 + (byte2 << 8) + (byte3 << 16); } /// /// Reads a 32-bit unsigned integer from a Stream in little-endian format. /// /// /// -1 on failure, else the 32-bit unsigned integer that was read. public static long ReadUInt32(Stream stream) { int byte1 = stream.ReadByte(); if (byte1 == -1) { return -1; } int byte2 = stream.ReadByte(); if (byte2 == -1) { return -1; } int byte3 = stream.ReadByte(); if (byte3 == -1) { return -1; } int byte4 = stream.ReadByte(); if (byte4 == -1) { return -1; } return unchecked((long)((uint)(byte1 + (byte2 << 8) + (byte3 << 16) + (byte4 << 24)))); } public static int ReadFromStream(Stream input, byte[] buffer, int offset, int count) { int totalBytesRead = 0; while (totalBytesRead < count) { int bytesRead = input.Read(buffer, offset + totalBytesRead, count - totalBytesRead); if (bytesRead == 0) { throw new IOException("ran out of data"); } totalBytesRead += bytesRead; } return totalBytesRead; } public static void Swap(ref T a, ref T b) { T t; t = a; a = b; b = t; } public static byte FastScaleByteByByte(byte a, byte b) { int r1 = a * b + 0x80; int r2 = ((r1 >> 8) + r1) >> 8; return (byte)r2; } } }