Helper.cs 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459
  1. using System.Drawing;
  2. using System.IO;
  3. using System.Runtime.InteropServices;
  4. using System.Threading.Tasks;
  5. using System.Windows.Interop;
  6. using System.Windows.Media.Animation;
  7. using System.Windows.Media.Imaging;
  8. using wpfScrollEventType = System.Windows.Controls.Primitives.ScrollEventType;
  9. namespace System.Windows.Forms
  10. {
  11. public static class Helper
  12. {
  13. private static int screenDpi;
  14. private static int GetDpi()
  15. {
  16. using (Bitmap bmp = new Bitmap(1, 1))
  17. using (Graphics g = Graphics.FromImage(bmp))
  18. {
  19. return (int)g.DpiX;
  20. }
  21. }
  22. public static int ScreenDpi
  23. {
  24. get
  25. {
  26. if (screenDpi == 0)
  27. screenDpi = GetDpi();
  28. return screenDpi;
  29. }
  30. }
  31. public static double GetDpiScale(System.Windows.Media.Visual control) =>
  32. System.Windows.Media.VisualTreeHelper.GetDpi(control).DpiScaleX;
  33. public static System.Windows.Thickness PaddingToThickness(Padding p) =>
  34. new System.Windows.Thickness(p.Left, p.Top, p.Right, p.Bottom);
  35. public static Padding ThicknessToPadding(System.Windows.Thickness t) =>
  36. new Padding((int)t.Left, (int)t.Top, (int)t.Right, (int)t.Bottom);
  37. public static Color GetColor(System.Windows.Media.Color color) =>
  38. Color.FromArgb(color.A, color.R, color.G, color.B);
  39. public static System.Windows.Media.Color GetColor(Color color) =>
  40. System.Windows.Media.Color.FromArgb(color.A, color.R, color.G, color.B);
  41. public static Color GetColor(System.Windows.Media.Brush brush)
  42. {
  43. if (brush is System.Windows.Media.SolidColorBrush br)
  44. return Helper.GetColor(br.Color);
  45. return System.Drawing.Color.Transparent;
  46. }
  47. public static System.Windows.Media.Brush GetBrush(Color color) =>
  48. new System.Windows.Media.SolidColorBrush(GetColor(color));
  49. public static Font GetFont(System.Windows.Controls.Control control) =>
  50. GetFont(GetDpiScale(control), control.FontFamily, control.FontSize, control.FontStyle, control.FontWeight);
  51. public static Font GetFont(
  52. double dpiScale,
  53. System.Windows.Media.FontFamily family,
  54. double size,
  55. System.Windows.FontStyle style,
  56. System.Windows.FontWeight weight,
  57. bool underline = false,
  58. bool strikeout = false)
  59. {
  60. System.Drawing.FontStyle s = System.Drawing.FontStyle.Regular;
  61. if (style == System.Windows.FontStyles.Italic)
  62. s |= System.Drawing.FontStyle.Italic;
  63. if (weight == System.Windows.FontWeights.Bold)
  64. s |= System.Drawing.FontStyle.Bold;
  65. if (underline)
  66. s |= System.Drawing.FontStyle.Underline;
  67. if (strikeout)
  68. s |= System.Drawing.FontStyle.Strikeout;
  69. return new Font(family.Source, (float)(size * dpiScale / ScreenDpi * 72f), s);
  70. }
  71. public static void SetFont(System.Windows.Controls.Control control, Font font) => SetFont(control, GetDpiScale(control), font);
  72. public static void SetFont(System.Windows.Controls.Control control, double dpiScale, Font font)
  73. {
  74. if (font != null)
  75. {
  76. SetFont(font, dpiScale, out var family, out var size, out var style, out var weight, out _);
  77. control.FontFamily = family;
  78. control.FontSize = size;
  79. control.FontStyle = style;
  80. control.FontWeight = weight;
  81. }
  82. }
  83. public static void SetFont(Font font,
  84. double dpiScale,
  85. out System.Windows.Media.FontFamily family,
  86. out double size,
  87. out System.Windows.FontStyle style,
  88. out System.Windows.FontWeight weight,
  89. out System.Windows.TextDecorationCollection deco) => SetFont(font.Name, font.Size, font.Style, dpiScale, out family, out size, out style, out weight, out deco);
  90. public static void SetFont(
  91. string fontName,
  92. float fontSize,
  93. Drawing.FontStyle fontStyle,
  94. double dpiScale,
  95. out System.Windows.Media.FontFamily family,
  96. out double size,
  97. out System.Windows.FontStyle style,
  98. out System.Windows.FontWeight weight,
  99. out System.Windows.TextDecorationCollection deco)
  100. {
  101. family = new System.Windows.Media.FontFamily(fontName);
  102. size = fontSize / (dpiScale / ScreenDpi * 72f); // / 72f * ScreenDpi / dpiScale;
  103. style = System.Windows.FontStyles.Normal;
  104. if ((fontStyle & System.Drawing.FontStyle.Italic) != 0)
  105. style = System.Windows.FontStyles.Italic;
  106. weight = System.Windows.FontWeights.Normal;
  107. if ((fontStyle & System.Drawing.FontStyle.Bold) != 0)
  108. weight = System.Windows.FontWeights.Bold;
  109. deco = new TextDecorationCollection();
  110. if ((fontStyle & System.Drawing.FontStyle.Underline) != 0)
  111. deco.Add(TextDecorations.Underline);
  112. if ((fontStyle & System.Drawing.FontStyle.Strikeout) != 0)
  113. deco.Add(TextDecorations.Strikethrough);
  114. }
  115. private static System.Windows.Media.PixelFormat GetPixelFormat(System.Drawing.Imaging.PixelFormat format)
  116. {
  117. switch (format)
  118. {
  119. case Drawing.Imaging.PixelFormat.Indexed:
  120. break;
  121. case Drawing.Imaging.PixelFormat.Gdi:
  122. break;
  123. case Drawing.Imaging.PixelFormat.Alpha:
  124. break;
  125. case Drawing.Imaging.PixelFormat.PAlpha:
  126. break;
  127. case Drawing.Imaging.PixelFormat.Extended:
  128. break;
  129. case Drawing.Imaging.PixelFormat.Canonical:
  130. break;
  131. case Drawing.Imaging.PixelFormat.Undefined:
  132. break;
  133. case Drawing.Imaging.PixelFormat.Format1bppIndexed:
  134. return System.Windows.Media.PixelFormats.Indexed1;
  135. case Drawing.Imaging.PixelFormat.Format4bppIndexed:
  136. return System.Windows.Media.PixelFormats.Indexed4;
  137. case Drawing.Imaging.PixelFormat.Format8bppIndexed:
  138. return System.Windows.Media.PixelFormats.Indexed8;
  139. case Drawing.Imaging.PixelFormat.Format16bppGrayScale:
  140. return System.Windows.Media.PixelFormats.Gray16;
  141. case Drawing.Imaging.PixelFormat.Format16bppRgb555:
  142. return System.Windows.Media.PixelFormats.Bgr555;
  143. case Drawing.Imaging.PixelFormat.Format16bppRgb565:
  144. return System.Windows.Media.PixelFormats.Bgr565;
  145. case Drawing.Imaging.PixelFormat.Format16bppArgb1555:
  146. break;
  147. case Drawing.Imaging.PixelFormat.Format24bppRgb:
  148. return System.Windows.Media.PixelFormats.Bgr24;
  149. case Drawing.Imaging.PixelFormat.Format32bppRgb:
  150. return System.Windows.Media.PixelFormats.Bgr32;
  151. case Drawing.Imaging.PixelFormat.Format32bppArgb:
  152. return System.Windows.Media.PixelFormats.Bgra32;
  153. case Drawing.Imaging.PixelFormat.Format32bppPArgb:
  154. return System.Windows.Media.PixelFormats.Pbgra32;
  155. case Drawing.Imaging.PixelFormat.Format48bppRgb:
  156. return System.Windows.Media.PixelFormats.Rgb48;
  157. case Drawing.Imaging.PixelFormat.Format64bppArgb:
  158. return System.Windows.Media.PixelFormats.Rgba64;
  159. case Drawing.Imaging.PixelFormat.Format64bppPArgb:
  160. return System.Windows.Media.PixelFormats.Prgba64;
  161. }
  162. throw new Exception("Pixel format is not supported");
  163. }
  164. public static BitmapSource GetImage(Image image, float dpiX = 0, float dpiY = 0)
  165. {
  166. var bitmap = image as Bitmap;
  167. if (bitmap == null)
  168. return null;
  169. var bitmapData = bitmap.LockBits(
  170. new Rectangle(0, 0, bitmap.Width, bitmap.Height),
  171. System.Drawing.Imaging.ImageLockMode.ReadOnly, bitmap.PixelFormat);
  172. if (dpiX == 0 || dpiY == 0)
  173. {
  174. dpiX = bitmap.HorizontalResolution;
  175. dpiY = bitmap.VerticalResolution;
  176. }
  177. var bitmapSource = BitmapSource.Create(
  178. bitmapData.Width, bitmapData.Height,
  179. dpiX, dpiY,
  180. GetPixelFormat(bitmap.PixelFormat), null,
  181. bitmapData.Scan0, bitmapData.Stride * bitmapData.Height, bitmapData.Stride);
  182. bitmap.UnlockBits(bitmapData);
  183. return bitmapSource;
  184. }
  185. public static Image GetImage(BitmapSource image)
  186. {
  187. if (image == null)
  188. return null;
  189. using (var outStream = new MemoryStream())
  190. {
  191. var enc = new PngBitmapEncoder();
  192. enc.Frames.Add(BitmapFrame.Create(image));
  193. enc.Save(outStream);
  194. using (var bitmap = new Bitmap(outStream))
  195. return CloneBitmap(bitmap);
  196. }
  197. }
  198. public static void DrawControl(System.Windows.Controls.Control control, Bitmap bitmap, int width, int height, double dpi)
  199. {
  200. if (control == null)
  201. return;
  202. // dv is created using the default dpi; control dpi may vary in multi-monitor setup
  203. var dv = new System.Windows.Media.DrawingVisual();
  204. double dvdpi = GetDpiScale(dv) * 96;
  205. RenderTargetBitmap rtb = new RenderTargetBitmap(width, height, dvdpi, dvdpi, System.Windows.Media.PixelFormats.Pbgra32);
  206. using (var ctx = dv.RenderOpen())
  207. {
  208. var vb = new System.Windows.Media.VisualBrush(control) { Stretch = Media.Stretch.None, AlignmentX = Media.AlignmentX.Left, AlignmentY = Media.AlignmentY.Top };
  209. double rescale = dpi / dvdpi;
  210. ctx.PushTransform(new Media.ScaleTransform(rescale, rescale));
  211. ctx.DrawRectangle(vb, null, new Rect(0, 0, width, height));
  212. }
  213. rtb.Render(dv);
  214. using (var outStream = new MemoryStream())
  215. {
  216. var enc = new PngBitmapEncoder();
  217. enc.Frames.Add(BitmapFrame.Create(rtb));
  218. enc.Save(outStream);
  219. using (var bmp = new Bitmap(outStream))
  220. using (Graphics g = Graphics.FromImage(bitmap))
  221. {
  222. g.Clear(System.Drawing.SystemColors.Control);
  223. g.DrawImageUnscaled(bmp, 0, 0);
  224. }
  225. }
  226. }
  227. private static Bitmap CloneBitmap(Image source)
  228. {
  229. if (source == null)
  230. return null;
  231. Bitmap image = new Bitmap(source.Width, source.Height);
  232. image.SetResolution(source.HorizontalResolution, source.VerticalResolution);
  233. using (Graphics g = Graphics.FromImage(image))
  234. {
  235. g.DrawImageUnscaled(source, 0, 0);
  236. }
  237. return image;
  238. }
  239. public static Media.ImageSource GetIcon(Icon icon)
  240. {
  241. if (icon == null)
  242. return null;
  243. return Imaging.CreateBitmapSourceFromHIcon(icon.Handle, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions());
  244. }
  245. public static MouseButtons GetMouseButton(System.Windows.Input.MouseButton button)
  246. {
  247. return button switch
  248. {
  249. Input.MouseButton.Left => MouseButtons.Left,
  250. Input.MouseButton.Right => MouseButtons.Right,
  251. Input.MouseButton.Middle => MouseButtons.Middle,
  252. Input.MouseButton.XButton1 => MouseButtons.XButton1,
  253. Input.MouseButton.XButton2 => MouseButtons.XButton2,
  254. _ => MouseButtons.None
  255. };
  256. }
  257. public static MouseEventArgs GetMouseEventArgs(System.Windows.Controls.Control control, System.Windows.Input.MouseEventArgs args)
  258. {
  259. var button = MouseButtons.None;
  260. if (args.LeftButton == Input.MouseButtonState.Pressed)
  261. button |= MouseButtons.Left;
  262. if (args.RightButton == Input.MouseButtonState.Pressed)
  263. button |= MouseButtons.Right;
  264. if (args.MiddleButton == Input.MouseButtonState.Pressed)
  265. button |= MouseButtons.Middle;
  266. if (args.XButton1 == Input.MouseButtonState.Pressed)
  267. button |= MouseButtons.XButton1;
  268. if (args.XButton2 == Input.MouseButtonState.Pressed)
  269. button |= MouseButtons.XButton2;
  270. var pos = args.GetPosition(control);
  271. var dpi = GetDpiScale(control);
  272. if (control.FlowDirection == FlowDirection.RightToLeft)
  273. pos.X = control.Width - pos.X;
  274. int delta = args is System.Windows.Input.MouseWheelEventArgs wArgs ? wArgs.Delta : 0;
  275. return new MouseEventArgs(button, 0, (int)(pos.X * dpi), (int)(pos.Y * dpi), delta);
  276. }
  277. public static MouseEventArgs GetMouseEventArgs(System.Windows.Controls.Control control, System.Windows.Input.MouseButtonEventArgs args)
  278. {
  279. var button = MouseButtons.None;
  280. if (args.ChangedButton == Input.MouseButton.Left)
  281. button |= MouseButtons.Left;
  282. if (args.ChangedButton == Input.MouseButton.Right)
  283. button |= MouseButtons.Right;
  284. if (args.ChangedButton == Input.MouseButton.Middle)
  285. button |= MouseButtons.Middle;
  286. if (args.ChangedButton == Input.MouseButton.XButton1)
  287. button |= MouseButtons.XButton1;
  288. if (args.ChangedButton == Input.MouseButton.XButton2)
  289. button |= MouseButtons.XButton2;
  290. var pos = args.GetPosition(control);
  291. var dpi = GetDpiScale(control);
  292. if (control.FlowDirection == FlowDirection.RightToLeft)
  293. pos.X = control.Width - pos.X;
  294. return new MouseEventArgs(button, 0, (int)(pos.X * dpi), (int)(pos.Y * dpi), 0);
  295. }
  296. public static KeyEventArgs GetKeyEventArgs(System.Windows.Input.KeyEventArgs args)
  297. {
  298. var wpfKey = args.Key == System.Windows.Input.Key.System ? args.SystemKey : args.Key;
  299. var winformModifiers = GetKeyModifiers(args.KeyboardDevice.Modifiers);
  300. var winformKeys = (Keys)System.Windows.Input.KeyInterop.VirtualKeyFromKey(wpfKey);
  301. return new KeyEventArgs(winformKeys | winformModifiers);
  302. }
  303. public static Keys GetKeyModifiers(System.Windows.Input.ModifierKeys modifier)
  304. {
  305. var retVal = Keys.None;
  306. if (modifier.HasFlag(System.Windows.Input.ModifierKeys.Alt))
  307. retVal |= Keys.Alt;
  308. if (modifier.HasFlag(System.Windows.Input.ModifierKeys.Control))
  309. retVal |= Keys.Control;
  310. if (modifier.HasFlag(System.Windows.Input.ModifierKeys.Shift))
  311. retVal |= Keys.Shift;
  312. return retVal;
  313. }
  314. public static DragEventArgs GetDragEventArgs(System.Windows.Controls.Control control, System.Windows.DragEventArgs args)
  315. {
  316. var pos = args.GetPosition(control);
  317. var dpi = GetDpiScale(control);
  318. return new DragEventArgs(new DataObjectImpl(args.Data), (int)args.KeyStates, (int)(pos.X * dpi), (int)(pos.Y * dpi), (DragDropEffects)args.AllowedEffects, (DragDropEffects)args.Effects);
  319. }
  320. public static ScrollEventArgs GetScrollEventArgs(System.Windows.Controls.Primitives.ScrollEventArgs args, bool horizontal)
  321. {
  322. ScrollEventType t = args.ScrollEventType switch
  323. {
  324. wpfScrollEventType.SmallDecrement => ScrollEventType.SmallDecrement,
  325. wpfScrollEventType.SmallIncrement => ScrollEventType.SmallIncrement,
  326. wpfScrollEventType.LargeDecrement => ScrollEventType.LargeDecrement,
  327. wpfScrollEventType.LargeIncrement => ScrollEventType.LargeIncrement,
  328. wpfScrollEventType.ThumbPosition => ScrollEventType.ThumbPosition,
  329. wpfScrollEventType.ThumbTrack => ScrollEventType.ThumbTrack,
  330. wpfScrollEventType.First => ScrollEventType.First,
  331. wpfScrollEventType.Last => ScrollEventType.Last,
  332. _ => ScrollEventType.EndScroll
  333. };
  334. return new ScrollEventArgs(t, (int)args.NewValue, horizontal ? ScrollOrientation.HorizontalScroll : ScrollOrientation.VerticalScroll);
  335. }
  336. public static void GetContentAlignment(ContentAlignment value, out System.Windows.HorizontalAlignment h, out System.Windows.VerticalAlignment v)
  337. {
  338. h = System.Windows.HorizontalAlignment.Left;
  339. v = System.Windows.VerticalAlignment.Top;
  340. switch (value)
  341. {
  342. case ContentAlignment.TopLeft:
  343. break;
  344. case ContentAlignment.TopCenter:
  345. h = System.Windows.HorizontalAlignment.Center;
  346. break;
  347. case ContentAlignment.TopRight:
  348. h = System.Windows.HorizontalAlignment.Right;
  349. break;
  350. case ContentAlignment.MiddleLeft:
  351. v = System.Windows.VerticalAlignment.Center;
  352. break;
  353. case ContentAlignment.MiddleCenter:
  354. h = System.Windows.HorizontalAlignment.Center;
  355. v = System.Windows.VerticalAlignment.Center;
  356. break;
  357. case ContentAlignment.MiddleRight:
  358. h = System.Windows.HorizontalAlignment.Right;
  359. v = System.Windows.VerticalAlignment.Center;
  360. break;
  361. case ContentAlignment.BottomLeft:
  362. v = System.Windows.VerticalAlignment.Bottom;
  363. break;
  364. case ContentAlignment.BottomCenter:
  365. h = System.Windows.HorizontalAlignment.Center;
  366. v = System.Windows.VerticalAlignment.Bottom;
  367. break;
  368. case ContentAlignment.BottomRight:
  369. h = System.Windows.HorizontalAlignment.Right;
  370. v = System.Windows.VerticalAlignment.Bottom;
  371. break;
  372. }
  373. }
  374. public static Day GetDay(DayOfWeek day)
  375. {
  376. return day switch
  377. {
  378. DayOfWeek.Monday => Day.Monday,
  379. DayOfWeek.Tuesday => Day.Tuesday,
  380. DayOfWeek.Wednesday => Day.Wednesday,
  381. DayOfWeek.Thursday => Day.Thursday,
  382. DayOfWeek.Friday => Day.Friday,
  383. DayOfWeek.Saturday => Day.Saturday,
  384. DayOfWeek.Sunday => Day.Sunday,
  385. _ => Day.Default
  386. };
  387. }
  388. public static DayOfWeek GetDayOfWeek(Day day)
  389. {
  390. return day switch
  391. {
  392. Day.Monday => DayOfWeek.Monday,
  393. Day.Tuesday => DayOfWeek.Tuesday,
  394. Day.Wednesday => DayOfWeek.Wednesday,
  395. Day.Thursday => DayOfWeek.Thursday,
  396. Day.Friday => DayOfWeek.Friday,
  397. Day.Saturday => DayOfWeek.Saturday,
  398. Day.Sunday => DayOfWeek.Sunday,
  399. _ => DayOfWeek.Monday
  400. };
  401. }
  402. public static void AnimateOpacity(this UIElement element, double from, double to, int duration)
  403. {
  404. DoubleAnimation animation = new DoubleAnimation(from, to, TimeSpan.FromMilliseconds(duration));
  405. element.BeginAnimation(UIElement.OpacityProperty, animation);
  406. }
  407. }
  408. }