So trotz der MS Philosophie ist to go toward out-of-the-box stretched images for Windows Form Controls when high DPI, scheint es Bilder auf Knopf manuell werden müssen gestreckt. Natürlich wäre eine noch bessere Lösung, dass für jede Bitmap, die dem Benutzer (auf der Schaltfläche und überall sonst) angezeigt wird, mehrere Bitmaps definiert werden, die an 250% 200% 150% und 125% DPI angepasst sind. Hier
ist der 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;
}
Beachten Sie, dass eine zählbare von Einweg-Bitmaps erstellt zurückgegeben wird. Wenn Sie Bitmap auf Schaltflächen nicht deponieren möchten, müssen Sie sich nicht darum kümmern, gestreckte Bitmap zu entfernen.
Beachten Sie, dass wir ursprüngliche Schaltflächen Bitmaps entsorgen.
Beachten Sie unsere eigenen Mitglieder mit DPI zu beschäftigen: MultipliedByDPIRatio(this int)
, DPIRatioIsOne:bool
, s_DPIRatio
. Sie können Ihre eigenen schreiben, der knifflige Punkt ist, das tatsächliche DPI-Verhältnis zu erhalten. Um DPI-Verhältnis zu sammeln, ist der beste Weg, den ich fand, this one. Beachten Sie den Verweis auf den Blogpost Improving High-DPI support for Visual Studio 2013, wo das VS-Team erklärt, dass für ihren Symbolstil, dass das Bild zwischen gestreckt 200%, 100% [wird am besten erreicht mit Bicubic-Algorithmus und über oder gleich 200% , wird am besten mit einem Naiven Nearest-Neighbor-Algorithmus erreicht. Der vorgestellte Code spiegelt diese Auswahl wider.
Edit: Screenshot unten verschiedenen Interpolationsmodus bei 200% DPI, IMHO InterpolationMode.HighQualityBicubic
ist besser als InterpolationMode.NearestNeighbor
.
Sie suchen ein Pony zu fragen . Sie können den Code einfach hinzufügen, um die Bitmaps zu skalieren, die einzige Garantie, die Sie erhalten, ist, dass Sie die Art, wie sie aussieht, absolut nicht mögen. –
Eine neue Bitmap erstellen und selbst skalieren ist die Hacky/Plan B Lösung. Dies ist die Kontrollverantwortung, um sein Image zu erweitern und hier möchte ich wirklich sicherstellen, dass ich keine saubere Lösung vermisse. –
Das ist der geheimnisvolle Teil dieser Frage. Wenn Sie wissen, dass die Bitmap-Skalierung ein hässlicher Hack ist, warum sollten Sie dann eine Standard-.NET-Klasse verwenden? Diese "Verantwortung", die Sie erwarten, ist einfach nicht da. Das Verwalten von Assets für ein dpiAware-Programm ist Aufgabe eines Programmierers. Die Implementierung ist ziemlich trivial, aber Sie werden niemals Hilfe bekommen, solange Sie die Frage auf diese Weise stellen. –