使现有的.NET Windows应用程序是DPI感知应用程序、NET、Windows、DPI

2023-09-03 07:24:17 作者:ㄞ帥氣小正太£

我们在它使用的所有自定义控件在现有的Windows .NET应用程序。

事情被罚款了这么些日子,因为我们只是支持默认的96 dpi的分辨率。

现在,我们需要我们的应用程序进行DPI的感知。事情会失控,当我们去到下一个

更高分辨​​率的120或144等。

最常见的问题。

位图的缩放问题以及

文本截止

微软,你这个老炮儿到底还有没有用

在经历these MSDN文档和现有 SO问题我试图

将白费这么解决我的应用程序中(因为所使用的所有控件都

自定义,不DPI的感知)。

东西我想改变我的application.manifest启用DPI意识标志和设置AutoScaleMode到AutoScaleMode.Dpi的主要形式和其他形式后使用AutoScaleMode作为继承

改变控制字体在onload事件中

图形G = this.CreateGraphics();         INT DPI = int.Parse(g.DpiX.ToString());

 开关(DPI)
    {
        案例125:
            this.Font =新的字体(this.Font.FontFamily,this.Font.Size * 125.0f /(浮动)(g.DpiX));
            的Debug.WriteLine(<< ----选择DPI分辨率:+125 DPI ---->中);
            打破;
    ... 不久
 

在试图重写ScaleControl方法,利用基于DPI不同的比例因子

但是,所有这些似乎从来没有在我的情况下工作。

有谁知道/建议我一个更好的办法来解决这个问题。

感谢

VATSAG

解决方案

所以,我只是有同样的问题,在我的应用程序之一。我设法去解决它在2个步骤,不幸的是需要重构的拍,但干完活后,我设法让我的应用程序来自动调整不同的DPI的。这是怎么一回事呢:

所有的表格必须设置使用扩展 AutoScaleMode = AutoScaleMode.Font 。当我做了一些挖机我发现 AutoScaleMode.Dpi 完全不是那么回事正如人们所期望它。你也应该选择什么样的标准DPI 单位将。说,这是96,因为这就是你的应用程序最初设计不管怎么说,则必须将所有的形式使用 AutoScaleDimensions =新System.Drawing.SizeF(6F,13F)。您可以从设计视图中设置这些配置。此外,如果您已经创建任何自定义的控件,他们都应该被设置成使用 AutoScaleMode = AsutoScaleMode.Inherit 。有了这两样东西,你可以放心,.NET将尽一切的尺度上的所有您的静态组件。

现在是当它变得棘手。问题是,该框架将保持所有控件有关的权利的大小,只要他们没有动态创建的,并放置在窗体中。

所以,如果你是这样的:

  VAR myTextBox =新文本框();
myTextBox.Location =新System.Drawing.Point(20,20);
myForm.Controls.Add(myTextBox);
 

那么该文本框将被放置在位置(20,20),无论你的DPI是什么,从而导致它看的地方在高DPI显示器。所以,解决的办法是为绝不会使用硬codeD的像素值,而不是使用动态扩展值,根据您当前的DPI配置。所以,相反,你可能会想要写的东西,如:

  VAR显卡= Graphics.FromHwnd(IntPtr.Zero); //这个获取当前屏幕的图形配置
VAR的scaleX = graphics.DpiX / 96; // 96是我们的标准设计的DPI,还记得吗?
VAR的scaleY = graphics.DpiY / 96;
VAR myTextBox =新文本框();

myTextBox.Location =新System.Drawing.Point(Math.Round(20 *的scaleX),Math.Round(20 *的scaleY));

myForm.Controls.Add(myTextBox);
 

这样,在其中你可以绘制控制屏幕上的位置将取决于实际的DPI。而且,如果我可以建议,我真的解压缩放功能集成到某种辅助类,其中定义的方法来在X和Y比例值的,所以你有一个标准的缩放机制。要注意的是同样重要的是你独立地扩展于x和y的,因为某些屏幕对各轴的不同像素密度

不管怎么说,如果你按照这两个条件,你的应用程序应该看看它的显示在屏幕就好了独立的。

We have an existing windows .net application in which it uses all custom controls.

Things were fine these many days as we were just supporting the default 96 dpi resolution.

Now that we need our application to be dpi-aware. Things are going haywire when we go to next

higher resolution 120 or 144 etc.

Most common issues

Bitmap scaling issues and

Text cut-off

After going through these MSDN docs and existing SO questions I tried to

incorporate such a fix in vain inside my application (since all the controls used are

customized and are not dpi-aware).

Things I tried after modifying my application.manifest to enable the dpi-awareness flag and setting the AutoScaleMode to AutoScaleMode.Dpi on the main form and other forms use the AutoScaleMode as Inherit

Changed the control Font inside the OnLoad event

Graphics g = this.CreateGraphics(); int dpi = int.Parse(g.DpiX.ToString());

    switch (dpi)
    {
        case 125:
            this.Font = new Font(this.Font.FontFamily, this.Font.Size * 125.0f / (float)(g.DpiX));
            Debug.WriteLine("<<---- Selected DPI Resolution :" + " 125 DPI ---->"); 
            break;
    ... so on

Tried overriding the ScaleControl method to make use of different scaling factor based on DPI

But all these never seem to work in my case.

Does anyone know / suggest me a better approach to tackle this issue.

Thanks

VATSAG

解决方案

So, I just had the same problem in one of my applications. I managed to go around it in a 2 step process, which unfortunately requires a LOT of refactoring, but after the work was done, I managed to get my application to scale on different DPI's automatically. Here's how it goes:

All your forms must be set to scale using AutoScaleMode = AutoScaleMode.Font. When I did some dig-up I found out that AutoScaleMode.Dpi doesn't quite work as one would expect it to. You should also choose what your standard DPI unit will be. Say that it's 96, since that's what your application was originally designed in anyways, then you must set all your forms to use AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F). You can set these configurations from the designer view. Also, if you've created any custom controls, they should all be set to use AutoScaleMode = AsutoScaleMode.Inherit. With these two things in place, you can rest assured that .NET will do all the scaling on all your static components.

Now's when it gets tricky. The thing is that the framework will maintain all your controls about the right size as long as they aren't dynamically created and placed inside the form.

So if you do something like:

var myTextBox = new TextBox();
myTextBox.Location = new System.Drawing.Point(20, 20);
myForm.Controls.Add(myTextBox);

then that text box will be placed at location (20, 20) no matter what your DPI is, hence causing it to look out of place on high DPI monitors. So the solution is to NEVER use hard coded pixel values, instead use values that scale dynamically, depending on your current DPI configuration. So, instead you may want to write something like:

var graphics = Graphics.FromHwnd(IntPtr.Zero); // This gets the graphics configuration of the current screen
var scaleX = graphics.DpiX / 96; // 96 was our standard design DPI, remember?
var scaleY = graphics.DpiY / 96;
var myTextBox = new TextBox();

myTextBox.Location = new System.Drawing.Point(Math.Round(20 * scaleX), Math.Round(20 * scaleY));

myForm.Controls.Add(myTextBox);

That way the location at which you'll draw the control on the screen will depend on the actual DPI. And, if I may suggest, I would actually extract the scaling functionality into some sort of helper class, where you define methods to scale a value on x and on y, so you'll have a standard scaling mechanism. Note that it is also important that you scale independently on x and y, since some screens have different pixel densities on each axis.

Anyways, if you follow these two conditions, your application should look just fine independent of the screen it's displayed on.