问题
Windows Forms (including Windows Forms for Compact Framwork, which is what I am using) has an AutoScale feature. By setting the AutoScaleMode property to AutoScaleMode.Dpi
, your application designed for, say, 320x200 automatically scales to the larger display of, for example, a VGA device.
This works great, but I have a few self-made custom controls that do their own OnPaint
stuff, and I'd like them to scale as well. Unfortunately, I've not found good documentation or an example on how to do that.
Currently, I'm doing this:
protected SizeF zoom = new SizeF(1.0, 1.0);
protected override void ScaleControl(SizeF factor, BoundsSpecified specified)
{
base.ScaleControl(factor, specified);
zoom = factor; // remember the zoom factor
}
protected override void OnPaint(PaintEventArgs e)
{
// scale everything by zoom.Width and zoom.Height
...
e.Graphics.DrawImage(...);
...
}
It works, but I'm wondering if this is "the right way" to do it. Since (according to ILSpy) none of the other CF controls have an internal field to store the scale factor, I'm wondering if there's an easier or better way to do this.
回答1:
We generally handle all of the scaling in OnResize
in our controls and forms. We also have to support a lot of different devices with crazy dimensions and DPI (some paltforms don't even report the correct DPI!). We found with AutoScaleMode
off you can proportionaly use a helper like this to scale a form's children in OnResize
. You simply add a Size _initalSize
member set to the form size in the constructor. However I've generally found on most forms I have to write custom layout code to appropriate deal with portrait and landscape displays.
protected override void OnResize(EventArgs e)
{
base.OnResize(e);
// Scale the control
ScaleChildren(this, ref _initialFormSize);
}
public static void ScaleChildren(Control control, ref Size initialSize, float fontFactor)
{
if (control == null || control.Size == initialSize)
return;
SizeF scaleFactor = new SizeF((float)control.Width / (float)initialSize.Width, (float)control.Height / (float)initialSize.Height);
initialSize = control.Size;
if (!float.IsInfinity(scaleFactor.Width) || !float.IsInfinity(scaleFactor.Height))
{
foreach (Control child in control.Controls)
{
child.Scale(scaleFactor);
if (child is Panel)
continue;
try
{
// scale the font
float scaledFontSize = (float)(int)(child.Font.Size * scaleFactor.Height * fontFactor + 0.5f);
System.Diagnostics.Debug.WriteLine(
string.Format("ScaleChildren(): scaleFactor = ({0}, {1}); fontFactor = {2}; scaledFontSize = {3}; \"{4}\"",
scaleFactor.Width, scaleFactor.Height, fontFactor, scaledFontSize, child.Text));
child.Font = new Font(child.Font.Name, scaledFontSize, child.Font.Style);
}
catch { }
}
}
}
来源:https://stackoverflow.com/questions/8153853/how-to-make-compact-framework-custom-controls-autoscale-aware