winforms – 如何在高DPI上扩展Windows窗体按钮的图像?

前端之家收集整理的这篇文章主要介绍了winforms – 如何在高DPI上扩展Windows窗体按钮的图像?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我找不到在 Windows窗体按钮中缩放图像的方法.请参阅下面DPI 200%上显示的Windows窗体设计器的样子(我知道Windows窗体设计器应仅用于DPI 100%/ 96,此屏幕截图只是说明了我的观点).

当按钮大小正确缩放(34×33)时,按钮大小中的图像不会缩放/拉伸/缩放(它仍然是16×16).我做了很多尝试来解决这个问题:

>父控件AutoScaleMode设置为Font,将其设置为Dpi不会使其工作.
>将AutoSize设置按钮设置为true或false不会使其正常工作.
>将按钮或父controlAutoSizeMode设置为任何值都不起作用.
>没有可以设置为拉伸或缩放的Button.ImageLayout.
>使用新的App.Config设置< add key =“EnableWindowsFormsHighDpiAutoResizing”value =“true”/>不起作用.
>更改按钮FlatStyle或ImageAlign不起作用.

你是如何在你的应用中解决这个问题的?

因此,尽管MS哲学是 to go toward out-of-the-box stretched images for Windows Form Controls when high DPI,但看起来Button上的图像需要手动拉伸.当然,更好的解决方案是,对于向用户显示的每个位图(在按钮上和其他地方),定义适合250%200%150%和125%DPI的几个位图.

这是代码

  1. public static IEnumerable<IDisposable> AdjustControlsThroughDPI(this Control.ControlCollection controls) {
  2. Debug.Assert(controls != null);
  3. if (DPIRatioIsOne) {
  4. return new IDisposable[0]; // No need to adjust on DPI One
  5. }
  6.  
  7. var list = new List<IDisposable>();
  8. foreach (Control control in controls) {
  9. if (control == null) { continue; }
  10.  
  11. var button = control as ButtonBase;
  12. if (button != null) {
  13. button.AdjustControlsThroughDPI(list);
  14. continue;
  15. }
  16.  
  17. // Here more controls tahn button can be adjusted if needed...
  18.  
  19. // Recursive
  20. var nestedControls = control.Controls;
  21. Debug.Assert(nestedControls != null);
  22. if (nestedControls.Count == 0) { continue; }
  23. var disposables = nestedControls.AdjustControlsThroughDPI();
  24. list.AddRange(disposables);
  25. }
  26. return list;
  27. }
  28.  
  29. private static void AdjustControlsThroughDPI(this ButtonBase button,IList<IDisposable> list) {
  30. Debug.Assert(button != null);
  31. Debug.Assert(list != null);
  32. var image = button.Image;
  33. if (image == null) { return; }
  34.  
  35. var imageStretched = image.GetImageStretchedDPI();
  36. button.Image = imageStretched;
  37. list.Add(imageStretched);
  38. }
  39.  
  40.  
  41. private static Image GetImageStretchedDPI(this Image imageIn) {
  42. Debug.Assert(imageIn != null);
  43.  
  44. var newWidth = imageIn.Width.MultipliedByDPIRatio();
  45. var newHeight = imageIn.Height.MultipliedByDPIRatio();
  46. var newBitmap = new Bitmap(newWidth,newHeight);
  47.  
  48. using (var g = Graphics.FromImage(newBitmap)) {
  49. // According to this blog post http://blogs.msdn.com/b/visualstudio/archive/2014/03/19/improving-high-dpi-support-for-visual-studio-2013.aspx
  50. // NearestNeighbor is more adapted for 200% and 200%+ DPI
  51. var interpolationMode = InterpolationMode.HighQualityBicubic;
  52. if (s_DPIRatio >= 2.0f) {
  53. interpolationMode = InterpolationMode.NearestNeighbor;
  54. }
  55. g.InterpolationMode = interpolationMode;
  56. g.DrawImage(imageIn,new Rectangle(0,newWidth,newHeight));
  57. }
  58.  
  59. imageIn.Dispose();
  60. return newBitmap;
  61. }

请注意,返回了创建的可枚举的一次性位图.如果您不关心在按钮上处理位图,则不必关心处理拉伸位图.

请注意我们处理原始按钮位图.

注意我们自己的成员来处理DPI:MultipliedByDPIRatio(this int),DPIRatioIsOne:bool,s_DPIRatio.你可以写自己的,棘手的一点是获得实际的DPI比率.为了收集DPI比率,我找到的最好的方法this one.

请注意对博客文章Improving High-DPI support for Visual Studio 2013的引用,其中VS团队解释说,对于他们的图标样式,他们确定图像延伸到200%,100%[最好用Bicubic算法实现,并且高于或等于200%,最好实现与朴素最近邻算法.提供的代码反映了这些选择.

编辑:在200%DPI下的各种插值模式的屏幕截图下,IMHO InterpolationMode.HighQualityBicubic优于InterpolationMode.NearestNeighbor.

猜你在找的Windows相关文章