使用自定义ImageListView控件后的窗体缩小问题 [英] Form Shrinking Issue After using a Custom ImageListView Control

查看:125
本文介绍了使用自定义ImageListView控件后的窗体缩小问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用以下控件在winforms中加载图像。





不使用DpiAware Option



解决方案

我能够重现该问题,这有点奇怪。由于我怀疑该应用程序未声明为可识别DPI,因此将其设置为可识别DPI可解决表单更改大小的问题。这可以通过将清单文件添加到项目中来完成(项目菜单->添加新项->常规选项卡->选择应用清单文件。然后将以下内容添加到文件中:

 <应用程序xmlns = urn:schemas-microsoft-com:asm.v3> 
< windowsSettings>
< dpiAware xmlns = http://schemas.microsoft.com/SMI/2005/WindowsSettings> true< / dpiAware>
< / windowsSettings>
< / application>

这可以解决问题,但我很好奇代码为何如此运行,该过程以DPI-并没有意识到,并且在关闭图像选择对话框之后,它会如何切换为DPI感知的过程。可以使用SysInternal的Process Explorer应用程序进行观察。我的第一个想法是搜索对 SetProcessDpiAwareness ,但是没有结果。深入研究代码发现,调用了 MetadataExtractor.cs 中的 InitViaWpf 方法。此方法和其他方法利用 System.Windows.Media.Imaging 命名空间中的类。看起来WPF库的这种用法使应用程序变为DPI感知,就像WPF应用程序默认为DPI感知一样。为名为 USEWIC ImageListView 项目声明了一个条件编译符号,该条件编译符号控制WPF类的用法。在项目的属性构建配置中删除该符号将阻止其使用,并且可以用作替代解决方案,它可能比声明Winform应用程序可识别DPI为佳,但我没有时间进一步研究该库。






编辑:通过创建 BitmapFrame

 使用System.Windows.Forms; 
使用System.IO;
使用System.Windows.Media.Imaging;

命名空间WindowsFormsApplication1
{
公共部分类Form1:表单
{
public Form1()
{
InitializeComponent() ;
}

private void button1_Click(对象发送者,EventArgs e)
{
使用(Stream strm = File.OpenRead( someimage.jpg))
{
BitmapFrame frame = BitmapFrame.Create(strm,BitmapCreateOptions.IgnoreColorProfile,BitmapCacheOption.None);
}

}
}
}






编辑2:DPI感知winform缩放的过程。



步骤1:在设计器中,设置AutoScaleMode属性继承。我知道没有任何意义,但继承是真正的默认设置。



步骤2:修改窗体的构造函数以使用Dpi或Font自动缩放。这样做是为了防止设计人员记录不正确的AutoScaleDimensions。

 公共Form1()
{
InitializeComponent();
//选择Dpi或字体缩放
this.AutoScaleDimensions = new SizeF(96,96);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;

//this.AutoScaleDimensions = new System.Drawing.SizeF(6.0F,13.0F);
//this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;



}



编辑3:维护在使用WPF库的不支持DPI的应用程序上进行DPI虚拟化(防止自动切换为支持DPI的软件),在app.manifest文件中包括 dpiAware 部分,但是

 < application xmlns = urn:schemas-microsoft-com:asm.v3> 
< windowsSettings>
< dpiAware xmlns = http://schemas.microsoft.com/SMI/2005/WindowsSettings> false< / dpiAware>
< / windowsSettings>
< / application>


I'm using the following control for loading images in winforms.

https://www.codeproject.com/Articles/43265/ImageListView

(OR)

https://github.com/oozcitak/imagelistview

It seems on a 1080P 15" Laptop there exists some scaling issue related to this control which is not reproducible on a 24" 1080P Monitor

I have recently noticed an odd thing happening with form scaling. It happens with the master solution downloaded directly from GitHub, and in my own application. My PC display setting is set to scale the display to 125% (right click desktop -> Display Settings -> Change the size of text, apps, and ...)

When I start debugging, the form loads - correctly scaled. However, as soon as I click on a folder in the treeview which has images, the images are loaded, and the form is scaled back to 100%. So the whole form appears to instantly shrink, while the rest of Windows is still at 125%.

I am not sure if this is a Windows or .Net Framework bug, or just the way the control is implemented. Or maybe there is a property I am not aware of that needs to be changed?

Any help / advise would be appreciated!

UPDATE:

After using the DpiAware Option

Without using DpiAware Option

解决方案

I have been able to reproduce the issue and it is a bit strange. As I suspected the application is not declared to be DPI-aware and setting it to be DPI-aware resolves the issue of the form changing size. This can be done by adding a manifest file to the project (Project Menu->Add New Item->General Tab->Select "Application Manifest File". Then add the follow to the file:

  <application xmlns="urn:schemas-microsoft-com:asm.v3">
    <windowsSettings>
      <dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true</dpiAware>
    </windowsSettings>
  </application>

That clears up the issue, but I was curious as to why the code was behaving this way. The process starts out as DPI-unaware and after closing the image selection dialog, it some how switched to being a DPI-aware process. The can be observed using the SysInternal's Process Explorer application. My first thought was to to search for a call to SetProcessDpiAwareness, but that yielded no results. Digging into the code revealed that the InitViaWpf method in MetadataExtractor.cs is called. This method and others utilize classes from the System.Windows.Media.Imaging namespace. It appears that this usage of the WPF libraries causes the application to become DPI-aware in the same way that WPF applications are DPI-aware by default. There is a conditional compilation symbol declared for the ImageListView project named USEWIC that controls this usage of the WPF classes. Removing this symbol in the project's properties build configuration will prevent their usage and can be used as an alternative solution and may be preferable to declaring the Winform application as being DPI-aware, but I don't have the time to investigate this library further.


Edit: This behavior can be easily replicated by creating an instance of BitmapFrame in a Winform application that has not been marked as being DPI-aware.

using System.Windows.Forms;
using System.IO;
using System.Windows.Media.Imaging;

namespace WindowsFormsApplication1
    {
    public partial class Form1 : Form
        {
        public Form1()
            {
            InitializeComponent();
            }

        private void button1_Click(object sender, EventArgs e)
            {
            using (Stream strm = File.OpenRead("someimage.jpg"))
                {
                BitmapFrame frame = BitmapFrame.Create(strm, BitmapCreateOptions.IgnoreColorProfile, BitmapCacheOption.None);
                }

            }
        }
    }


Edit 2: Procedure for DPI-aware winform scaling.

Step 1: In the designer, set the AutoScaleMode property to Inherit. I know None would make sense, but Inherit is the true default setting.

Step 2: Modify the Form's constructor to use either Dpi or Font automatic scaling. This is done to prevent the designer from recording improper AutoScaleDimensions.

public Form1()
    {
    InitializeComponent();
    // Select either Dpi or font scaling
    this.AutoScaleDimensions = new SizeF(96, 96);
    this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;

    //this.AutoScaleDimensions = new System.Drawing.SizeF(6.0F, 13.0F);
    //this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;

}

Edit 3: To maintain the DPI-virtualization (prevent the automatic switching to DPI-aware) on a DPI-unaware application that uses WPF libraries, include the dpiAware section in the app.manifest file, but explicity set it to false.

  <application xmlns="urn:schemas-microsoft-com:asm.v3">
    <windowsSettings>
      <dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">false</dpiAware>
    </windowsSettings>
  </application> 

这篇关于使用自定义ImageListView控件后的窗体缩小问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆