5

My WinForms app has a toolbar. The toolbar buttons are type ToolStripButton. The icon images are 16x16 pngs, installed as resources.

this.BtnNew.Image = Resources.NewDocument;
this.BtnNew.ImageScaling = ToolStripItemImageScaling.None;

This looks fine on most computers, however on a computer with high dpi, the toolbar buttons appear small compared to the rest of the app (text is scaled up). I would like the toolbar icons to scale too.

I tried

this.BtnNew.ImageScaling = ToolStripItemImageScaling.SizeToFit;

This scaled the icon correctly, but it appeared blurry, of course because the original image is only 16x16 pixels.

How can I get the icons to scale correctly according to dpi without blurring? Would using 64x64 pngs be any better, or will I get a different kind of blur when they're scaled down? Can I use svg images?

Colonel Panic
  • 132,665
  • 89
  • 401
  • 465
  • If this is your only issue with DPI scaling then well done indeed! Such a pain trying to support winforms dpi on XP, Vista and 7+ – musefan Jul 01 '15 at 10:05
  • @musefan oh yes. Here's a short guide I wrote if it helps anyone http://stackoverflow.com/a/28369995/284795 – Colonel Panic Jul 01 '15 at 10:09

1 Answers1

2

Scaling down will look better than scaling up. Typically for an icon image, predefined sizes will be created. For simplicity, assume the width and height are equal. So the image sizes are { 16, 24, 32, 48, 64, 128, 256 }. Using a single 64x64 would require testing to see if the result is acceptable.

The height of the ToolStripButton is going to be determined by its Font if the button displays some Text. If there is no text, then the preferred height can still be calculated based on Font, or by the Graphics.Dpi properties. The displayed image can be scaled on the fly to fit the preferred height of the ToolStripItem. E.g.

public class MyToolStripButton : ToolStripButton {

    public IList<Image> Images { get; private set; }

    public MyToolStripButton(String text, IList<Image> images) : base(text) {
        Images = images.OrderBy(i => i.Height).ToList();
        ImageScaling = ToolStripItemImageScaling.None;
        RefreshImage();
    }

    protected override void OnFontChanged(EventArgs e) {
        base.OnFontChanged(e);
        RefreshImage();
    }

    public void RefreshImage() {
        int h = this.Height;
        Image bestImage = null;
        for (int i = 0; i < Images.Count; i++) {
            var img = Images[i];
            if (img.Height > h || i == Images.Count - 1) {
                bestImage = img;
                break;
            }
        }

        // scale down the image
        Image oldImage = this.Image;
        Bitmap newImage = new Bitmap(h, h);
        using (var g = Graphics.FromImage(newImage)) {
            g.DrawImage(bestImage, 0, 0, h, h);
        }

        this.Image = newImage;

        if (oldImage != null)
            oldImage.Dispose();
    }
}

        [STAThread]
        static void Main() {
            Form f = new Form();
            MenuStrip menu1 = new MenuStrip() { Dock = DockStyle.Top };
            f.Controls.Add(menu1);
            f.MainMenuStrip = menu1;

            int[] res = { 16, 32, 48, 64, 128 };
            Image[] images = new Image[res.Length];
            for (int i = 0; i < res.Length; i++) {
                Bitmap img = new Bitmap(res[i], res[i]);
                using (var g = Graphics.FromImage(img)) {
                    g.DrawEllipse(Pens.Red, 0, 0, res[i], res[i]);
                }
                images[i] = img;
            }

            MyToolStripButton btn1 = new MyToolStripButton("Button", images);
            btn1.Click += delegate {
                Font fnt = btn1.Owner.Font;
                btn1.Owner.Font = new Font(fnt.FontFamily, fnt.Size + 2f, fnt.Style);
            };
            menu1.Items.Add(btn1);
            Application.Run(f);
        }
Loathing
  • 5,109
  • 3
  • 24
  • 35