using System.Drawing; using System.IO; using System.Runtime.InteropServices; using System.Threading.Tasks; using System.Windows.Interop; using System.Windows.Media.Animation; using System.Windows.Media.Imaging; using wpfScrollEventType = System.Windows.Controls.Primitives.ScrollEventType; namespace System.Windows.Forms { public static class Helper { private static int screenDpi; private static int GetDpi() { using (Bitmap bmp = new Bitmap(1, 1)) using (Graphics g = Graphics.FromImage(bmp)) { return (int)g.DpiX; } } public static int ScreenDpi { get { if (screenDpi == 0) screenDpi = GetDpi(); return screenDpi; } } public static double GetDpiScale(System.Windows.Media.Visual control) => System.Windows.Media.VisualTreeHelper.GetDpi(control).DpiScaleX; public static System.Windows.Thickness PaddingToThickness(Padding p) => new System.Windows.Thickness(p.Left, p.Top, p.Right, p.Bottom); public static Padding ThicknessToPadding(System.Windows.Thickness t) => new Padding((int)t.Left, (int)t.Top, (int)t.Right, (int)t.Bottom); public static Color GetColor(System.Windows.Media.Color color) => Color.FromArgb(color.A, color.R, color.G, color.B); public static System.Windows.Media.Color GetColor(Color color) => System.Windows.Media.Color.FromArgb(color.A, color.R, color.G, color.B); public static Color GetColor(System.Windows.Media.Brush brush) { if (brush is System.Windows.Media.SolidColorBrush br) return Helper.GetColor(br.Color); return System.Drawing.Color.Transparent; } public static System.Windows.Media.Brush GetBrush(Color color) => new System.Windows.Media.SolidColorBrush(GetColor(color)); public static Font GetFont(System.Windows.Controls.Control control) => GetFont(GetDpiScale(control), control.FontFamily, control.FontSize, control.FontStyle, control.FontWeight); public static Font GetFont( double dpiScale, System.Windows.Media.FontFamily family, double size, System.Windows.FontStyle style, System.Windows.FontWeight weight, bool underline = false, bool strikeout = false) { System.Drawing.FontStyle s = System.Drawing.FontStyle.Regular; if (style == System.Windows.FontStyles.Italic) s |= System.Drawing.FontStyle.Italic; if (weight == System.Windows.FontWeights.Bold) s |= System.Drawing.FontStyle.Bold; if (underline) s |= System.Drawing.FontStyle.Underline; if (strikeout) s |= System.Drawing.FontStyle.Strikeout; return new Font(family.Source, (float)(size * dpiScale / ScreenDpi * 72f), s); } public static void SetFont(System.Windows.Controls.Control control, Font font) => SetFont(control, GetDpiScale(control), font); public static void SetFont(System.Windows.Controls.Control control, double dpiScale, Font font) { if (font != null) { SetFont(font, dpiScale, out var family, out var size, out var style, out var weight, out _); control.FontFamily = family; control.FontSize = size; control.FontStyle = style; control.FontWeight = weight; } } public static void SetFont(Font font, double dpiScale, out System.Windows.Media.FontFamily family, out double size, out System.Windows.FontStyle style, out System.Windows.FontWeight weight, out System.Windows.TextDecorationCollection deco) => SetFont(font.Name, font.Size, font.Style, dpiScale, out family, out size, out style, out weight, out deco); public static void SetFont( string fontName, float fontSize, Drawing.FontStyle fontStyle, double dpiScale, out System.Windows.Media.FontFamily family, out double size, out System.Windows.FontStyle style, out System.Windows.FontWeight weight, out System.Windows.TextDecorationCollection deco) { family = new System.Windows.Media.FontFamily(fontName); size = fontSize / (dpiScale / ScreenDpi * 72f); // / 72f * ScreenDpi / dpiScale; style = System.Windows.FontStyles.Normal; if ((fontStyle & System.Drawing.FontStyle.Italic) != 0) style = System.Windows.FontStyles.Italic; weight = System.Windows.FontWeights.Normal; if ((fontStyle & System.Drawing.FontStyle.Bold) != 0) weight = System.Windows.FontWeights.Bold; deco = new TextDecorationCollection(); if ((fontStyle & System.Drawing.FontStyle.Underline) != 0) deco.Add(TextDecorations.Underline); if ((fontStyle & System.Drawing.FontStyle.Strikeout) != 0) deco.Add(TextDecorations.Strikethrough); } private static System.Windows.Media.PixelFormat GetPixelFormat(System.Drawing.Imaging.PixelFormat format) { switch (format) { case Drawing.Imaging.PixelFormat.Indexed: break; case Drawing.Imaging.PixelFormat.Gdi: break; case Drawing.Imaging.PixelFormat.Alpha: break; case Drawing.Imaging.PixelFormat.PAlpha: break; case Drawing.Imaging.PixelFormat.Extended: break; case Drawing.Imaging.PixelFormat.Canonical: break; case Drawing.Imaging.PixelFormat.Undefined: break; case Drawing.Imaging.PixelFormat.Format1bppIndexed: return System.Windows.Media.PixelFormats.Indexed1; case Drawing.Imaging.PixelFormat.Format4bppIndexed: return System.Windows.Media.PixelFormats.Indexed4; case Drawing.Imaging.PixelFormat.Format8bppIndexed: return System.Windows.Media.PixelFormats.Indexed8; case Drawing.Imaging.PixelFormat.Format16bppGrayScale: return System.Windows.Media.PixelFormats.Gray16; case Drawing.Imaging.PixelFormat.Format16bppRgb555: return System.Windows.Media.PixelFormats.Bgr555; case Drawing.Imaging.PixelFormat.Format16bppRgb565: return System.Windows.Media.PixelFormats.Bgr565; case Drawing.Imaging.PixelFormat.Format16bppArgb1555: break; case Drawing.Imaging.PixelFormat.Format24bppRgb: return System.Windows.Media.PixelFormats.Bgr24; case Drawing.Imaging.PixelFormat.Format32bppRgb: return System.Windows.Media.PixelFormats.Bgr32; case Drawing.Imaging.PixelFormat.Format32bppArgb: return System.Windows.Media.PixelFormats.Bgra32; case Drawing.Imaging.PixelFormat.Format32bppPArgb: return System.Windows.Media.PixelFormats.Pbgra32; case Drawing.Imaging.PixelFormat.Format48bppRgb: return System.Windows.Media.PixelFormats.Rgb48; case Drawing.Imaging.PixelFormat.Format64bppArgb: return System.Windows.Media.PixelFormats.Rgba64; case Drawing.Imaging.PixelFormat.Format64bppPArgb: return System.Windows.Media.PixelFormats.Prgba64; } throw new Exception("Pixel format is not supported"); } public static BitmapSource GetImage(Image image, float dpiX = 0, float dpiY = 0) { var bitmap = image as Bitmap; if (bitmap == null) return null; var bitmapData = bitmap.LockBits( new Rectangle(0, 0, bitmap.Width, bitmap.Height), System.Drawing.Imaging.ImageLockMode.ReadOnly, bitmap.PixelFormat); if (dpiX == 0 || dpiY == 0) { dpiX = bitmap.HorizontalResolution; dpiY = bitmap.VerticalResolution; } var bitmapSource = BitmapSource.Create( bitmapData.Width, bitmapData.Height, dpiX, dpiY, GetPixelFormat(bitmap.PixelFormat), null, bitmapData.Scan0, bitmapData.Stride * bitmapData.Height, bitmapData.Stride); bitmap.UnlockBits(bitmapData); return bitmapSource; } public static Image GetImage(BitmapSource image) { if (image == null) return null; using (var outStream = new MemoryStream()) { var enc = new PngBitmapEncoder(); enc.Frames.Add(BitmapFrame.Create(image)); enc.Save(outStream); using (var bitmap = new Bitmap(outStream)) return CloneBitmap(bitmap); } } public static void DrawControl(System.Windows.Controls.Control control, Bitmap bitmap, int width, int height, double dpi) { if (control == null) return; // dv is created using the default dpi; control dpi may vary in multi-monitor setup var dv = new System.Windows.Media.DrawingVisual(); double dvdpi = GetDpiScale(dv) * 96; RenderTargetBitmap rtb = new RenderTargetBitmap(width, height, dvdpi, dvdpi, System.Windows.Media.PixelFormats.Pbgra32); using (var ctx = dv.RenderOpen()) { var vb = new System.Windows.Media.VisualBrush(control) { Stretch = Media.Stretch.None, AlignmentX = Media.AlignmentX.Left, AlignmentY = Media.AlignmentY.Top }; double rescale = dpi / dvdpi; ctx.PushTransform(new Media.ScaleTransform(rescale, rescale)); ctx.DrawRectangle(vb, null, new Rect(0, 0, width, height)); } rtb.Render(dv); using (var outStream = new MemoryStream()) { var enc = new PngBitmapEncoder(); enc.Frames.Add(BitmapFrame.Create(rtb)); enc.Save(outStream); using (var bmp = new Bitmap(outStream)) using (Graphics g = Graphics.FromImage(bitmap)) { g.Clear(System.Drawing.SystemColors.Control); g.DrawImageUnscaled(bmp, 0, 0); } } } private static Bitmap CloneBitmap(Image source) { if (source == null) return null; Bitmap image = new Bitmap(source.Width, source.Height); image.SetResolution(source.HorizontalResolution, source.VerticalResolution); using (Graphics g = Graphics.FromImage(image)) { g.DrawImageUnscaled(source, 0, 0); } return image; } public static Media.ImageSource GetIcon(Icon icon) { if (icon == null) return null; return Imaging.CreateBitmapSourceFromHIcon(icon.Handle, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions()); } public static MouseButtons GetMouseButton(System.Windows.Input.MouseButton button) { return button switch { Input.MouseButton.Left => MouseButtons.Left, Input.MouseButton.Right => MouseButtons.Right, Input.MouseButton.Middle => MouseButtons.Middle, Input.MouseButton.XButton1 => MouseButtons.XButton1, Input.MouseButton.XButton2 => MouseButtons.XButton2, _ => MouseButtons.None }; } public static MouseEventArgs GetMouseEventArgs(System.Windows.Controls.Control control, System.Windows.Input.MouseEventArgs args) { var button = MouseButtons.None; if (args.LeftButton == Input.MouseButtonState.Pressed) button |= MouseButtons.Left; if (args.RightButton == Input.MouseButtonState.Pressed) button |= MouseButtons.Right; if (args.MiddleButton == Input.MouseButtonState.Pressed) button |= MouseButtons.Middle; if (args.XButton1 == Input.MouseButtonState.Pressed) button |= MouseButtons.XButton1; if (args.XButton2 == Input.MouseButtonState.Pressed) button |= MouseButtons.XButton2; var pos = args.GetPosition(control); var dpi = GetDpiScale(control); if (control.FlowDirection == FlowDirection.RightToLeft) pos.X = control.Width - pos.X; int delta = args is System.Windows.Input.MouseWheelEventArgs wArgs ? wArgs.Delta : 0; return new MouseEventArgs(button, 0, (int)(pos.X * dpi), (int)(pos.Y * dpi), delta); } public static MouseEventArgs GetMouseEventArgs(System.Windows.Controls.Control control, System.Windows.Input.MouseButtonEventArgs args) { var button = MouseButtons.None; if (args.ChangedButton == Input.MouseButton.Left) button |= MouseButtons.Left; if (args.ChangedButton == Input.MouseButton.Right) button |= MouseButtons.Right; if (args.ChangedButton == Input.MouseButton.Middle) button |= MouseButtons.Middle; if (args.ChangedButton == Input.MouseButton.XButton1) button |= MouseButtons.XButton1; if (args.ChangedButton == Input.MouseButton.XButton2) button |= MouseButtons.XButton2; var pos = args.GetPosition(control); var dpi = GetDpiScale(control); if (control.FlowDirection == FlowDirection.RightToLeft) pos.X = control.Width - pos.X; return new MouseEventArgs(button, 0, (int)(pos.X * dpi), (int)(pos.Y * dpi), 0); } public static KeyEventArgs GetKeyEventArgs(System.Windows.Input.KeyEventArgs args) { var wpfKey = args.Key == System.Windows.Input.Key.System ? args.SystemKey : args.Key; var winformModifiers = GetKeyModifiers(args.KeyboardDevice.Modifiers); var winformKeys = (Keys)System.Windows.Input.KeyInterop.VirtualKeyFromKey(wpfKey); return new KeyEventArgs(winformKeys | winformModifiers); } public static Keys GetKeyModifiers(System.Windows.Input.ModifierKeys modifier) { var retVal = Keys.None; if (modifier.HasFlag(System.Windows.Input.ModifierKeys.Alt)) retVal |= Keys.Alt; if (modifier.HasFlag(System.Windows.Input.ModifierKeys.Control)) retVal |= Keys.Control; if (modifier.HasFlag(System.Windows.Input.ModifierKeys.Shift)) retVal |= Keys.Shift; return retVal; } public static DragEventArgs GetDragEventArgs(System.Windows.Controls.Control control, System.Windows.DragEventArgs args) { var pos = args.GetPosition(control); var dpi = GetDpiScale(control); return new DragEventArgs(new DataObjectImpl(args.Data), (int)args.KeyStates, (int)(pos.X * dpi), (int)(pos.Y * dpi), (DragDropEffects)args.AllowedEffects, (DragDropEffects)args.Effects); } public static ScrollEventArgs GetScrollEventArgs(System.Windows.Controls.Primitives.ScrollEventArgs args, bool horizontal) { ScrollEventType t = args.ScrollEventType switch { wpfScrollEventType.SmallDecrement => ScrollEventType.SmallDecrement, wpfScrollEventType.SmallIncrement => ScrollEventType.SmallIncrement, wpfScrollEventType.LargeDecrement => ScrollEventType.LargeDecrement, wpfScrollEventType.LargeIncrement => ScrollEventType.LargeIncrement, wpfScrollEventType.ThumbPosition => ScrollEventType.ThumbPosition, wpfScrollEventType.ThumbTrack => ScrollEventType.ThumbTrack, wpfScrollEventType.First => ScrollEventType.First, wpfScrollEventType.Last => ScrollEventType.Last, _ => ScrollEventType.EndScroll }; return new ScrollEventArgs(t, (int)args.NewValue, horizontal ? ScrollOrientation.HorizontalScroll : ScrollOrientation.VerticalScroll); } public static void GetContentAlignment(ContentAlignment value, out System.Windows.HorizontalAlignment h, out System.Windows.VerticalAlignment v) { h = System.Windows.HorizontalAlignment.Left; v = System.Windows.VerticalAlignment.Top; switch (value) { case ContentAlignment.TopLeft: break; case ContentAlignment.TopCenter: h = System.Windows.HorizontalAlignment.Center; break; case ContentAlignment.TopRight: h = System.Windows.HorizontalAlignment.Right; break; case ContentAlignment.MiddleLeft: v = System.Windows.VerticalAlignment.Center; break; case ContentAlignment.MiddleCenter: h = System.Windows.HorizontalAlignment.Center; v = System.Windows.VerticalAlignment.Center; break; case ContentAlignment.MiddleRight: h = System.Windows.HorizontalAlignment.Right; v = System.Windows.VerticalAlignment.Center; break; case ContentAlignment.BottomLeft: v = System.Windows.VerticalAlignment.Bottom; break; case ContentAlignment.BottomCenter: h = System.Windows.HorizontalAlignment.Center; v = System.Windows.VerticalAlignment.Bottom; break; case ContentAlignment.BottomRight: h = System.Windows.HorizontalAlignment.Right; v = System.Windows.VerticalAlignment.Bottom; break; } } public static Day GetDay(DayOfWeek day) { return day switch { DayOfWeek.Monday => Day.Monday, DayOfWeek.Tuesday => Day.Tuesday, DayOfWeek.Wednesday => Day.Wednesday, DayOfWeek.Thursday => Day.Thursday, DayOfWeek.Friday => Day.Friday, DayOfWeek.Saturday => Day.Saturday, DayOfWeek.Sunday => Day.Sunday, _ => Day.Default }; } public static DayOfWeek GetDayOfWeek(Day day) { return day switch { Day.Monday => DayOfWeek.Monday, Day.Tuesday => DayOfWeek.Tuesday, Day.Wednesday => DayOfWeek.Wednesday, Day.Thursday => DayOfWeek.Thursday, Day.Friday => DayOfWeek.Friday, Day.Saturday => DayOfWeek.Saturday, Day.Sunday => DayOfWeek.Sunday, _ => DayOfWeek.Monday }; } public static void AnimateOpacity(this UIElement element, double from, double to, int duration) { DoubleAnimation animation = new DoubleAnimation(from, to, TimeSpan.FromMilliseconds(duration)); element.BeginAnimation(UIElement.OpacityProperty, animation); } } }