I am developing a WinForms application in C#. It uses a panel to draw an image of the Mandelbrot fractal. In the manual for the program and whenever I post about it somewhere, I recommend people to set their scaling setting to 100%, as otherwise the images won't look nice. This is because on other settings, the image is scaled up after drawing it, and it becomes blurry. All other controls are blurry too.
For example: my panel is 500x500. The scaling in my Windows is set to 125%. When I run the program, the panel is internally still 500x500, but it appears as 625x625, blurry. Instead, when the program is run, I want the panel to internally resize to 625x625, and appear as 625x625 too.
I have found the following solution: I found out about SetProcessDPIAware() (from here). Setting that makes the window not scale (it appears as if it was at the 100% scale setting), but the text does (and without becoming blurry). I can then, at the start of the program, calculate the appropriate multiplier (dpi = DpiX / 96) and give that to a huge method that includes commands like
xentrylabel.Location = new Point((int)(xentrylabel.Location.X * dpi),(int)(xentrylabel.Location.Y * dpi));
xentry.Location = new Point((int)(xentry.Location.X * dpi), (int)(xentry.Location.Y * dpi));
xentry.Size = new Size((int)(xentry.Width * dpi), (int)(xentry.Height * dpi));
One for every control property that might need to be updated. While writing this question, I got this idea and got started with it. However, I realised that this will need very many lines of code, so I wonder if there isn't a built-in way to do this. It seems like an option that many would like to go for, rather than their applications becoming blurry or hard to read on screens with high dpi.
Is this way of manually correcting positions and sizes the way to go, or is there a built-in way to scale the form for other DPI settings by actually scaling everything in the form, instead of scaling the end result?
Edit: From some comments it seems as if SetProcessDPIAware() alone should scale up everything. But in my experience, it doesn't. Here are some screenshots:
Application on 100% scale setting:
https://i.stack.imgur.com/pws9B.png
Application on 125% scale setting without SetProcessDPIAware():
https://i.stack.imgur.com/cE4Wx.png
Application on 125% scale setting with SetProcessDPIAware():
https://i.stack.imgur.com/oVA8W.png
We solved the issue of rendering controls for high DPI screens with scaling greater than 100% in Chem4Word by creating a WPF user control which is hosted in an ElementHost control, which is set to fill the form.
WinForm
+- ElementHost
+- WPFUserControl
Looking at your uploaded images, that's exactly the problem which is solved by using a WPF user control.
I've been working on a UWP application that will initially be deployed only to Surface Pro 4 (Maybe some SP3s) devices but I'm having a real difficult time getting my UI to fit on the screen.
Right now my Designer window is set to '12" Tablet (2160 x 1440) 150% Scale' with it locked in landscape mode (the only way this app will be used) so that the 'Effective: 1440 x 960' resolution is set.
I've got my MainPage page set to 960 x 1440 with a Frame for display content essentially filling the entire 960 x 1440 but when I run the app (either in full screen or windowed) it cuts off the content of my MainPage (not just the frame content but part of my app sidebar menu).
That all being said my question(s): How do I get my UWP to scale my content to fit inside what ever size window the app is displayed in when running (full screen or user adjusted window size), OR what settings do I need/How do I configure it to display my entire MainPage contents on my SP4 screen (2736 x 1824) in fullscreen without just trial/error adjusting elements manually until they fit.
I'm more concerned with the second question because I don't just want this app to do what I want (because I know I can figure it out myself by manually sizing elements) but I want to understand why it's doing what it's doing and the right way to go about doing what I want to do.
I did a lot of searching but could not find the answer to my question, if this is a duplicate please feel free to link the answer.
Thanks in advance.
The Designer just gives you a general guide on how things would look. The demensions are not for SP4 specifically.
At 150% DPI, try setting your MainPage to 1824, 1216.
You can call
ApplicationView.GetForCurrentView().VisibleBounds
at runtime to find how many pixels(epx) that your screen is currently set to.
Note that these are effective pixels. They are different from the physical pixels of the device. All UWP UI measurements are epx based. So when you see this -
<Button Width="24" />
You should know that the value 24 is measured in epx.
To find out what epx really is, give this a read.
So I have a few custom cells using ViewCell in my app. Inside my ViewCell are Labels. I want the font size of those labels to be dependent on the text size of the device just like how the TextCell's text changes when you adjust the text size of your device.
Below image is using a built-in TextCell.
Below image is using a custom cell ViewCell
Im testing this in an iOS device and the text size is set to the smallest available. Whenever I change the device text size the cells using TextCells will just automatically changed. The labels inside the ViewCell doesn't change at all. Any suggestion pointing me to the right direction is very much appreciated.
Short answer
The TextCell uses the native UITableViewCell on iOS. This native view takes the device accessibility settings into account. When you use the Xamarin Forms Label, it does not. Xamarin Forms does not support iOS Dynamic Type (yet).
Explanation
The Forms Label uses the FontSizeConverter to set the actual font size. This font size defaults to the value -1 if you don't set any value yourself. The value -1 results in the use of NamedSize.Default (see the Font class).
When you take a look at the FontSizeConverter, if it can't parse the value as an absolute value, it will try to convert to a NamedSize value. In that case, it will use Device.GetNamedSize to get the actual size. This is done through the IPlatformServices interface, which converts these to absolute values (see the IOSPlatformServices).
There is also a FontExtensions class, that implements the same conversion from Named Size to an absolute value. Not very DRY at first sight, but there could be a good reason for this, that I'm not aware of.
Unfortunately, both the FontExtensions and the IOSPlatformServices don't take the accessibility options of iOS into account, but just return absolute values.
Possible solution
On iOS, you could use UIKit.UIApplication.SharedApplication.PreferredContentSizeCategory to get the current accessibility category. Based on this value, you could determine a scale for your fonts (use DynamicResource for the font sizes if you use them in XAML, so they can change at runtime).
Or take a look at SushiHangover's answer on a similar question.
See the preferredContentSizeCategory on the Apple Developer API reference.
Like I said in the title when i built to mobile the letter became too small. I think it is because phone has more pixel for his little screen.
Well I tried to fix text by simply making text to images in photoshop. But how can I make InputFields text (not the placeholder).
At a guess, your Canvas' CanvasScaler's UI Scale Mode is probably set to Constant Pixel Size, and if your mobile device's resolution is too high, text will appear small.
Try changing the UI Scale Mode to Scale With Screen Size and change the properties it provides as needed.
(if your Canvas doesn't have a CanvasScaler component, click the Add Component button and add it)
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?
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":
Set AutoScaleMode to None.
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).
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);
}
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.
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.
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.
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.
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!