Turning "Fix scaling for apps" Off breaks our app's behavior (breaks .NET Framework Image manipulation)... is there a work-around?

T

TCC Developer

Am I correct that when a user sets "Fix scaling for apps" to Off that Windows essentially treats all apps as DPI Unaware?

If so, is there a way for our app to say "treat us as DPI Aware anyway"? (That would be the easiest work-around.)


Background: our WinForms app targets .NET Framework 4.5.1 and calls SetProcessDPIAware() during startup, which makes it "system" aware, not "per monitor"... and we generally autoscale pretty well. Our app constructs Metafiles (EMF+) that it saves to a database and displays in WinForms PictureBox controls. That code has been working great for many years.


However, with Windows 10 1903 and .NET Framework 4.8, if a user sets "Fix scaling for apps" to Off with Scaling at 150% or higher, it not only makes our UI a little fuzzier by telling us 100% and then doing the scaling its own way, it ALSO breaks the Metafiles we construct... our Image processing. In particular, it seems to scale up what is drawn by Graphics.DrawImage by 150%... or scales back the resulting dimensions by 150%... not sure... but the result is the image we are drawing into the Metafile gets cropped. This is not just what is showing on the screen... the images we are computing in memory and then saving to our SQL Server database are getting wrongly cropped.


If we change the calls to "new Metafile" to pre-specify the frame size, then that avoids the bug. Unfortunately, we don't know the resultant size... we keep building up the Image as we go. So, we normally do not specify a Rectangle and it just auto sizes to the contents that we draw into the Metafile. (It just does it off by the Scaling factor now that "Fix scaling for apps" can be turned off.)


Work-around question #2: Is there some way we can construct the Metafile without specify a size that will still not result in cropping when "Fix scaling for apps" is turned Off?


Work-around question #3: Is there some way for us to detect that "Fix scaling for apps" is turned Off such that we can warn the user that we will malfunction... that they need to turn that back On?


We created a tiny sample program to illustrate the problem. It is a simple WinForm with two PictureBoxes and a button that takes the Image in the first, draws it into a new Metafile, then puts the new Metafile into the second PictureBox. That works as expected, UNLESS you set Scaling 150% or more and turn "Fix scaling for apps" Off, in which case the computed Metafile will only be the upper left portion of the original Image. Here's some code snippets...


The main program setting it DPI Aware:


static class Program


{
[
System.Runtime.InteropServices.DllImport("user32.dll")]
private static extern bool SetProcessDPIAware();

/// <summary>
/// The main entry point for the application.
/// </summary>
[
STAThread]
static void Main()
{
//if (Environment.OSVersion.Version.Major >= 6)
SetProcessDPIAware();

Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}

}




Our call to create a new Metafile with offscreen device context and no pre-computed bounds such that it grows to its contents:


public static Metafile NewMetafile()


{
using (Graphics g = Graphics.FromHwnd(IntPtr.Zero)) // offscreen device context
{
IntPtr hdc = g.GetHdc(); // gets released by g.Dispose() called by using g
return new Metafile(hdc, EmfType.EmfPlusOnly);
}

}




The implementation of the button click, copying the Image into a new Metafile:


private void DrawUsingMetafile()


{
try
{
Image img = this.pictureBox1.Image;

Metafile mf = NewMetafile();

using (Graphics gmf = Graphics.FromImage(mf))
{
gmf.
DrawImage(img, 0, 0, img.Width, img.Height);
}

this.pictureBox2.Image = mf;
}
catch (Exception ex)
{

MessageBox.Show(ex.Message, "Exception", MessageBoxButtons.OK, MessageBoxIcon.Error);

}

}




Any suggested work-arounds for this inconsistent Windows behavior would be greatly appreciated.

Continue reading...
 
Back
Top Bottom