Therefore, despite the fact that the MS philosophy approaches ready-made stretched images for Windows Form controls at a high DPI level , it seems that the images on the button need to be manually stretched. Of course, even the best solution would be for each bitmap shown to the user (on the button and everywhere) to define several bitmaps adapted to 250% 200% 150% and 125% DPI.
Here is the code:
public static IEnumerable<IDisposable> AdjustControlsThroughDPI(this Control.ControlCollection controls) { Debug.Assert(controls != null); if (DPIRatioIsOne) { return new IDisposable[0]; // No need to adjust on DPI One } var list = new List<IDisposable>(); foreach (Control control in controls) { if (control == null) { continue; } var button = control as ButtonBase; if (button != null) { button.AdjustControlsThroughDPI(list); continue; } // Here more controls tahn button can be adjusted if needed... // Recursive var nestedControls = control.Controls; Debug.Assert(nestedControls != null); if (nestedControls.Count == 0) { continue; } var disposables = nestedControls.AdjustControlsThroughDPI(); list.AddRange(disposables); } return list; } private static void AdjustControlsThroughDPI(this ButtonBase button, IList<IDisposable> list) { Debug.Assert(button != null); Debug.Assert(list != null); var image = button.Image; if (image == null) { return; } var imageStretched = image.GetImageStretchedDPI(); button.Image = imageStretched; list.Add(imageStretched); } private static Image GetImageStretchedDPI(this Image imageIn) { Debug.Assert(imageIn != null); var newWidth = imageIn.Width.MultipliedByDPIRatio(); var newHeight = imageIn.Height.MultipliedByDPIRatio(); var newBitmap = new Bitmap(newWidth, newHeight); using (var g = Graphics.FromImage(newBitmap)) { // According to this blog post http://blogs.msdn.com/b/visualstudio/archive/2014/03/19/improving-high-dpi-support-for-visual-studio-2013.aspx // NearestNeighbor is more adapted for 200% and 200%+ DPI var interpolationMode = InterpolationMode.HighQualityBicubic; if (s_DPIRatio >= 2.0f) { interpolationMode = InterpolationMode.NearestNeighbor; } g.InterpolationMode = interpolationMode; g.DrawImage(imageIn, new Rectangle(0, 0, newWidth, newHeight)); } imageIn.Dispose(); return newBitmap; }
Note that a list of one-time bitmaps is returned. If you donβt like placing bitmaps on buttons, you donβt have to worry about deleting the bitmap.
Please note that we have the original bitmap images of the buttons.
Pay attention to our own members for working with DPI: MultipliedByDPIRatio(this int) , DPIRatioIsOne:bool , s_DPIRatio . You can write your own, the difficult task is to get the actual DPI ratio. To compile DPI, the best way to find this one .
Check out the link to the blog post Improving High DPI Support for Visual Studio 2013 , where the VS team explains that for their icon style, they determine that the image is stretched between> 200%, 100% [best achieved using the algorithm Bikubitsa and above or equal to 200%, is best achieved with the naive nearest neighbor algorithm. The code presented reflects these options.
Edit: screenshot with different interpolation mode at 200% DPI, IMHO InterpolationMode.HighQualityBicubic better than InterpolationMode.NearestNeighbor .

source share