28

I need a quick way of forcing my C# Windows Forms application to not scale fonts when a user choose a larger or smaller percentage in the OS settings.

Is this even possible?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Andrew
  • 281
  • 1
  • 3
  • 3
  • Why do you want to act contrary to the user's wishes? – CodesInChaos Jun 04 '14 at 08:55
  • 15
    Possibly because it will throw out the views, and have overflows that will be hard to fix for every single case. It would be a quicker fix to just "blanket-force-size." It is a band-aid fix, as you said, because it's not in the user's best interest, but that's my 2c. – eggy Jan 16 '15 at 02:48
  • FWIW, I have a situation that is the OPPOSITE: On a tablet, when it goes into tablet (touch) mode, I'd like to automatically increase the font size *as if* the user increased font size to 125%. REASON: Usability. Fingers need larger area to touch; outdoors in sunlight, need larger text to be readable. I mention this, to point out that there are legitimate reasons for an app to *modify* what the user sets. User shouldn't have to set their OS font size different, just to have this legacy app be useable in touch mode. – ToolmakerSteve Apr 07 '18 at 11:26

7 Answers7

28

Here is what worked for me...

        this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.None;
        this.Font = new System.Drawing.Font("Arial", 14F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Pixel, ((byte)(0)));

The above two lines are copied from my BaseForm.Designer.cs file, but basically I found two easy steps to get "no font scaling":

  1. Set AutoScaleMode to None.

  2. Use "Pixel" as the Unit Type for all Fonts, instead of the default Point value.

As far as if you should let Windows scale your fonts or not, that's up to you. I for one don't like the design, so if I feel my application needs to be scaled, I'll do it myself, with my own options and design.

Over the years of speaking with actual end-users, I've also found that most of them have no idea about DPI settings, and if they have anything other than the default set, it wasn't because they wanted it that way... and they just never noticed because all they use is the web browser and maybe Excel and Microsoft Word (which use whatever font they set it to).

If my application had respected the system font settings, they wouldn't have liked it as much == less sales, because it would have had this huge ugly font like the system dialogs do (and they don't know how to change it, but they don't care about system dialogs they never use).

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
eselk
  • 6,764
  • 7
  • 60
  • 93
  • following formula can be used to determine font size in pixels: pixel_size == point_size * 96 / 72 // for 96 dpi .. 100% – Bachor May 12 '15 at 07:54
18

The problem is that the Font property of a Form or a control specifies the font size in Points. That's a measurement that affect the height of the letters when the DPI setting changes. One point is 1/72 inches. The default DPI, 96 dots per inch and a font size of 9 points yields a letter that is 9 / 72 x 96 = 12 pixels high.

When the user bumps up the DPI setting to, say, 120 DPI (125%) then the letter becomes 9 / 72 x 120 = 15 pixels high. If you don't let the control get larger then the text won't fit in the control anymore. Very ugly to look at.

The Form.AutoScaleMode property solves this problem. It checks at which size the form was designed and compares it against the DPI on the machine on which it runs. And resizes and relocates the controls to ensure this kind of clipping won't happen. Very useful, it is completely automatic without you having to do anything about it.

The typical problem is the "relocates" bit in the previous paragraph. If you give controls their own font size instead of inheriting the size of the form or if the automatic layout of the form isn't kosher then controls may end up in the wrong spot, destroying the organized look of the form.

You need to fix that, it isn't clear from your question what the source of the problem might be. Trying to prevent this auto-scaling from doing its job is not sustainable. You'll have to iterate all of the controls in the form and change their Font, picking a smaller font size. This is however going to get you into trouble a couple of years from now, if not already. Your user is going to complain about having to work with a postage stamp.

The easiest way to debug the layout problem, avoiding the pain of constantly changing the DPI size, is to temporarily paste this code into your form class:

    protected override void OnLoad(EventArgs e) {
        this.Font = new Font(this.Font.FontFamily, this.Font.SizeInPoints * 125 / 96);
        base.OnLoad(e);
    }
Hans Passant
  • 922,412
  • 146
  • 1,693
  • 2,536
  • +1. But I would like to add that inheriting a changed font by the contained controls makes AutoScaleMode not working as intended, see the link at the end of my answer. As a workaround, one has to change the fonts of all controls explicitly. – Doc Brown Nov 03 '10 at 17:40
6

I found a pretty easy workaround.

this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F);

this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;

This will make the text the same size regardless of the autoscale size.

protoculture
  • 141
  • 2
  • 2
  • 4
    At what step in the lifecycle of the control/form is this set? In the Constructor? The InitializeComponent Routine? – DarrenMB Sep 11 '15 at 01:04
2

Going against the user wishes like this is not something MS eagerly accommodates.

Rather than fixing the symptom (your app not scaling correctly), would it not be probably just as quick to fix the problem? When a user selects larger fonts, it's usually because they need the larger letters to be able to read them; so scaling correctly is more important than not scaling and remaining illegible to the user.

Gabriel Magana
  • 4,338
  • 24
  • 23
  • isn't the question "how to force not to autoscale", while you are suggesting not to do so? – sudarsanyes Jun 04 '14 at 08:55
  • I was suggesting making the the app scale correctly, rather than finding a way to disobey the user's Windows settings. – Gabriel Magana Jun 11 '14 at 17:50
  • 10
    I don't believe this answers the question. While it's useful to say that "XYZ shouldn't be done" it's not useful to say "you cannot do XYZ" unless you cannot do XYZ. This answer could work as a comment to the original question, but not as an answer. – mrmillsy May 19 '15 at 23:11
2

No. GDI and Windows Forms are resolution dependent. The best option is to design your layouts in a way that they scale appropriately when a window is resized. This tends to allow font size scaling to work correctly, as well, as the layouts will adjust as needed.

This, by the way, is one of the big improvements in WPF - it's designed to be resolution independent.

Reed Copsey
  • 554,122
  • 78
  • 1,158
  • 1,373
2

I suspect you already tried

yourform.AutoScaleMode = System.Windows.Forms.AutoScaleMode.None;

in your forms, which prevents your forms from scaling, but not your fonts. So what you have to do (even if it is not recommended, see the other posts) is setting the font size for all controls in your form to a fixed size:

Here is a code snippet to grab all controls of a Form:

    public List<Control> FindAllControls(Control container)
    {
        List<Control> controlList = new List<Control>();
        FindAllControls(container, controlList);
        return controlList;
    }

    private void FindAllControls(Control container, IList<Control> ctrlList)
    {
        foreach (Control ctrl in container.Controls)
        {
            if (ctrl.Controls.Count == 0)
                ctrlList.Add(ctrl);
            else
                FindAllControls(ctrl, ctrlList);
        }
    }

Under http://www.csharp411.com/change-font-size/ you will find a link how to change the font size of a control, especially when you want to use fixed pixel sized. I think with these tools you can wire it together on your own.

EDIT: Don't forget to say: if you are finally going not to ignore the OS font size and to use AutoScaleMode as intended: this has some quirks, see my previous post here on SO.

Community
  • 1
  • 1
Doc Brown
  • 19,739
  • 7
  • 52
  • 88
1
  • In Windows 8.0, even if you set the Font Unit as Pixel, with the AutoScaling set to None, it is auto scaling.
  • In Windows 7, the same application is not auto scaling.

So therefore, the only way to not to let your text auto scale on Windows 7 is to set the Font Unit as Pixel and the Window's AutoScaling property as None.

And in Windows 8.0, I guess you have no other choice but to set the dpi to the dpi of the developer machine and ask the user to never change it!

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
sudarsanyes
  • 3,156
  • 8
  • 42
  • 52