当 DPI 高于 96 并调用特定方法时,表单搞砸了

问题描述

我有一个重载方法,它获取上传图像中的字节,这似乎导致我的整个应用程序调整大小。这似乎只有在显示缩放比例不是 100% 时才会发生。

奇怪的是,当应用程序进入重载方法但在方法中的任何实际代码运行之前,它会调整大小。更奇怪的是,如果我将 DPI 比例设置为 100%,执行通常会调整表单大小的操作,然后将显示比例切换回 125%,则不会发生调整大小。

这是方法

public static byte[] GetMultiPageImageBytes(byte[] imageBytes,double? rotationAngle,string subject)
{
    using (MemoryStream inStream = new MemoryStream(imageBytes))
    {
        return GetMultiPageImageBytes(inStream,rotationAngle,subject);
    }
}

和重载方法(发生调整大小的地方):

public static byte[] GetMultiPageImageBytes(Stream inStream,string subject)
{ /************************ APP RESIZES ON THIS LINE ************************/
    BitmapDecoder decoder = new TiffBitmapDecoder(inStream,BitmapCreateOptions.PreservePixelFormat,BitmapCacheOption.Default);
    TiffBitmapEncoder encoder = new TiffBitmapEncoder();

    foreach (BitmapFrame frame in decoder.Frames)
    {
        BitmapMetadata Metadata = null;
        if (subject != null)
        {
            Metadata = new BitmapMetadata("tiff");
            Metadata.Subject = subject;
        }

        TransformedBitmap rotatedImage = null;
        if (rotationAngle != null)
        {
            System.Windows.Media.RotateTransform transform = new System.Windows.Media.RotateTransform(rotationAngle.Value);
            rotatedImage = new TransformedBitmap(frame,transform);
        }

        BitmapSource sourceImage = rotatedImage != null ? (BitmapSource)rotatedImage : (BitmapSource)frame;
        BitmapFrame newFrame = BitmapFrame.Create(sourceImage,frame.Thumbnail,Metadata,frame.ColorContexts);

        encoder.Frames.Add(newFrame);
    }

    using (MemoryStream outStream = new MemoryStream())
    {
        encoder.Save(outStream);
        return outStream.ToArray();
    }
}

我试过 SetProcessDPIAware() 解决了这个问题,但它弄乱了许多其他表单和组件的布局。该应用程序太大,此时无法优化 DPI 感知,因为我需要重新格式化数十个组件。

我还尝试删除调用重载方法的原始方法中的 using 语句,并仅手动处理流,但这也不起作用:

// 无效

public static byte[] GetMultiPageImageBytes(byte[] imageBytes,string subject)
{
    MemoryStream inStream = new MemoryStream(imageBytes);
    byte[] bytes;
    bytes = GetMultiPageImageBytes(inStream,subject);
    inStream.dispose();
    inStream.Close();
    return bytes;
}

关于可能导致这种情况的任何想法?对此的任何帮助将不胜感激!

解决方法

部分答案 - 这可能发生在该方法中首次使用的某个类的静态构造函数中。静态构造函数保证在类的第一次实例化或调用其静态方法之一之前的某个时间被调用。在这样的方法开始时看到这种情况发生是很典型的。所以这就解释了奇怪的时间。恐怕我对 WinForm 或 WPF 的了解还不够多,无法解释其余的内容,所以我不会推测。


具体来说,我建议以下任何类的静态构造函数都应该在您的第二个 GetMultiPageImageBytes 方法开始时被调用,如果它们还没有的话:

  • TiffBitmapDecoder
  • TiffBitmapEncoder
  • 位图元数据
  • 旋转变换
  • 变形位图
  • 位图框架
  • 任何他们的基类

.NET 规范不会确切地说明何时调用静态构造函数,只会在类的第一次实例化之前的某个时间调用它,或者调用其静态方法之一。通常,您将看到的行为是,它将在将要 执行其中一项操作的方法开始时调用。这就是为什么我说它是在你的方法的第一行发生奇怪事情的一种看似合理的机制,即使它还没有做任何事情。很可能是这样的静态构造函数或它导致运行的其他代码导致了您的奇怪行为。

确实,这个答案表明 loading any WPF classses causes the process to be set to DPI-aware。基于此,您的问题可能是 WPF 类根本没有设计为在非 WPF 应用程序中独立使用。从您的问题标题中的“WinForm”,我假设您的应用程序的其余部分都不是 WPF。

,

根据@Jimi 的建议禁用 DPI 感知对我有用。我最终使用了这个答案中的代码:WPF ClickOnce DPI awareness Per-Monitor v2 from @Marko

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...