2014-11-12 6 views
5

मुझे विंडोज़ फॉर्म बटन में छवि को स्केल करने का कोई तरीका नहीं मिल रहा है। डीपीआई 200% पर दिखाए गए विंडोज फॉर्म डिजाइनर के साथ यह कैसा दिखता है (मुझे पता है कि विंडोज फॉर्म डिजाइनर का उपयोग केवल डीपीआई 100%/96 पर किया जाना चाहिए, यह स्क्रीनशॉट सिर्फ मेरे बिंदु को सही ढंग से दिखाता है)।विंडोज़ फॉर्म बटन की छवि को उच्च-डीपीआई पर कैसे स्केल करें?

जबकि बटन का आकार ठीक से स्केल किया गया है (34x33), बटन आकार में छवि स्केल/खिंचाव/ज़ूम नहीं होती है (यह 16x16 बनी हुई है)।

  • माता पिता नियंत्रण AutoScaleMode, Font पर सेट है यह Dpi के लिए सेटिंग इस काम नहीं है: मैं इस को हल करने के कई प्रयास किया था।
  • सेटिंग बटन AutoSize से true या false यह काम नहीं करता है।
  • किसी भी मूल्य पर बटन या पैरेंट नियंत्रण AutoSizeMode सेट करना यह काम नहीं करता है।
  • कोई Button.ImageLayout नहीं है जिसे Stretch या Zoom पर सेट किया जा सकता है।
  • App.Config सेटिंग <add key="EnableWindowsFormsHighDpiAutoResizing" value="true" /> सेटिंग का उपयोग करके यह काम नहीं करता है।
  • बदलते बटन FlatStyle या ImageAlign यह काम नहीं करता है।

आपने इसे अपने ऐप में कैसे हल किया?

Windows Form Button Image doesn't scale

+0

आप एक टट्टू के लिए पूछ रहे हैं । आप आसानी से बिटमैप्स को स्केल करने के लिए कोड जोड़ सकते हैं, आपको केवल एक ही गारंटी मिल जाएगी कि आप जिस तरह से दिखते हैं उससे बिल्कुल नफरत करेंगे। –

+0

एक नया बिटमैप बनाना और इसे स्केल करना पाठ्यक्रम की हैकी/योजना बी समाधान है। यह अपनी छवि को फैलाने की नियंत्रण ज़िम्मेदारी है और यहां, मैं वास्तव में यह सुनिश्चित करना चाहता हूं कि मुझे एक साफ समाधान याद नहीं आया। –

+2

यह इस प्रश्न का रहस्यमय हिस्सा है। यदि आप जानते हैं कि बिटमैप स्केलिंग एक बदसूरत हैक है तो पृथ्वी पर क्यों आप मानक .NET क्लास का उपयोग करने की उम्मीद करेंगे? वह "ज़िम्मेदारी" जो आप उम्मीद करते हैं वह बस वहां नहीं है। एक dpiAware प्रोग्राम के लिए संपत्ति प्रबंधन एक प्रोग्रामर का काम है। इसे कार्यान्वित करना बहुत छोटा है लेकिन जब तक आप इस सवाल से पूछते हैं तब तक आपको कोई मदद नहीं मिलेगी। –

उत्तर

4
एमएस दर्शन के बावजूद

तो to go toward out-of-the-box stretched images for Windows Form Controls when high DPI है, यह बटन पर छवियों को मैन्युअल रूप से फैला होने की जरूरत है लगता है। निस्संदेह एक बेहतर समाधान यह होगा कि प्रत्येक बिटमैप उपयोगकर्ता (बटन और हर जगह) पर दिखाया गया है ताकि 250% 200% 150% और 125% डीपीआई के अनुकूल कई बिटमैप्स को परिभाषित किया जा सके।

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; 
    } 

सूचना है कि बनाया डिस्पोजेबल बिटमैप्स का एक गणनीय दिया जाता है:

यहाँ कोड है। यदि आपको बटन पर बिटमैप का निपटान करने की परवाह नहीं है, तो आपको विस्तारित बिटमैप का निपटान करने की आवश्यकता नहीं होगी।

नोटिस हम मूल बटन बिटमैप्स का निपटान करते हैं।

डीपीआई से निपटने के लिए अपने सदस्यों को नोटिस करें: MultipliedByDPIRatio(this int), DPIRatioIsOne:bool, s_DPIRatio। आप अपना खुद का लिख ​​सकते हैं, वास्तविक बिंदु वास्तविक डीपीआई अनुपात प्राप्त करना है। डीपीआई अनुपात को इकट्ठा करने के लिए मुझे सबसे अच्छा तरीका this one मिला है।

सूचना ब्लॉग पोस्ट Improving High-DPI support for Visual Studio 2013 जहां वी.एस. टीम बताते हैं कि उनके आइकन शैली के लिए, वे उस छवि के बीच फैला] 200%, 100% [सबसे अच्छा Bicubic एल्गोरिथ्म साथ हासिल की है निर्धारित करते हैं, और इसके बाद के संस्करण या 200% के बराबर करने के लिए संदर्भ , बेवकूफ निकटतम पड़ोसी एल्गोरिदम के साथ सबसे अच्छा हासिल किया जाता है। प्रस्तुत कोड इन विकल्पों को दर्शाता है।


संपादित करें: 200% पर विभिन्न प्रक्षेप मोड के नीचे स्क्रीनशॉट डीपीआई, IMHO InterpolationMode.HighQualityBicubicInterpolationMode.NearestNeighbor से बेहतर है।

Interpolation mode

1

यहाँ स्वीकार किए जाते हैं जवाब है कि डीपीआई पैमाने की बहाली भी शामिल है के आधार पर सहायक वर्ग का उपयोग करने के लिए तैयार है, और PictureBox छवि स्केलिंग का समर्थन जोड़ता है:

public static class HighDpiHelper 
{ 
    public static void AdjustControlImagesDpiScale(Control container) 
    { 
     var dpiScale = GetDpiScale(container).Value; 
     if (CloseToOne(dpiScale)) 
      return; 

     AdjustControlImagesDpiScale(container.Controls, dpiScale); 
    } 

    private static void AdjustButtonImageDpiScale(ButtonBase button, float dpiScale) 
    { 
     var image = button.Image; 
     if (image == null) 
      return; 

     button.Image = ScaleImage(image, dpiScale); 
    } 

    private static void AdjustControlImagesDpiScale(Control.ControlCollection controls, float dpiScale) 
    { 
     foreach (Control control in controls) 
     { 
      var button = control as ButtonBase; 
      if (button != null) 
       AdjustButtonImageDpiScale(button, dpiScale); 
      else 
      { 
       var pictureBox = control as PictureBox; 
       if (pictureBox != null) 
        AdjustPictureBoxDpiScale(pictureBox, dpiScale); 
      } 

      AdjustControlImagesDpiScale(control.Controls, dpiScale); 
     } 
    } 

    private static void AdjustPictureBoxDpiScale(PictureBox pictureBox, float dpiScale) 
    { 
     var image = pictureBox.Image; 
     if (image == null) 
      return; 

     if (pictureBox.SizeMode == PictureBoxSizeMode.CenterImage) 
      pictureBox.Image = ScaleImage(pictureBox.Image, dpiScale); 
    } 

    private static bool CloseToOne(float dpiScale) 
    { 
     return Math.Abs(dpiScale - 1) < 0.001; 
    } 

    private static Lazy<float> GetDpiScale(Control control) 
    { 
     return new Lazy<float>(() => 
     { 
      using (var graphics = control.CreateGraphics()) 
       return graphics.DpiX/96.0f; 
     }); 
    } 

    private static Image ScaleImage(Image image, float dpiScale) 
    { 
     var newSize = ScaleSize(image.Size, dpiScale); 
     var newBitmap = new Bitmap(newSize.Width, newSize.Height); 

     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 (dpiScale >= 2.0f) 
       interpolationMode = InterpolationMode.NearestNeighbor; 

      g.InterpolationMode = interpolationMode; 
      g.DrawImage(image, new Rectangle(new Point(), newSize)); 
     } 

     return newBitmap; 
    } 

    private static Size ScaleSize(Size size, float scale) 
    { 
     return new Size((int)(size.Width * scale), (int)(size.Height * scale)); 
    } 
} 
संबंधित मुद्दे