如果 DPI 发生变化,如何正确地将标签与文本框对齐?

2023-11-30

我已在我的配置文件中启用了这些推荐设置:

<add key="DpiAware" value="true" />
<add key="DpiAwareness" value="PerMonitorV2" />
<add key="EnableWindowsFormsHighDpiAutoResizing" value="true" />

也在主函数中:

Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);

一切都位于顶部和左侧锚定位置,这就是它在 100% 缩放显示屏上的外观:

enter image description here

当我将窗口移动到 150% 或 175% 缩放显示时:

enter image description here

如您所见,标签向下偏移几个像素。

容器的AutoScaleMode被设定为DPI.

如何保持对齐?


我遇到了同样的问题,经过一番挖掘后,我得到了这个控件,它可以用来代替标签。已知问题:单击时,聚焦的控件会失去焦点。这可以在 TableLayoutPanel 中使用,也可以独立使用。

public class LabelTextBox : System.Windows.Forms.TextBox
{
    private const int WM_NCPAINT = 0x85;
    private const int WM_SETFOCUS = 0x07;
    private const int WM_ENABLE = 0x0A;
    private const int WM_SETCURSOR = 0x20;

    [StructLayout(LayoutKind.Sequential)]
    private struct RECT
    {
        // https://www.pinvoke.net/default.aspx/Structures/RECT.html
    }

    [StructLayout(LayoutKind.Sequential)]
    private struct POINT
    {
        // https://www.pinvoke.net/default.aspx/Structures/POINT.html
    }

    public LabelTextBox()
    {
        // Disable some TextBox interactions, so it is intact as the Label
        this.ReadOnly = true;
        this.TabStop = false;
    }

    [DllImport("user32")]
    private static extern IntPtr GetWindowDC(IntPtr hwnd);
    
    [DllImport("user32")]
    private static extern bool GetClientRect(IntPtr hwnd, out RECT rectangle);
    
    [DllImport("user32")]
    private static extern bool GetWindowRect(IntPtr hwnd, out RECT rectangle);

    [DllImport("user32.dll")]
    static extern bool ClientToScreen(IntPtr hWnd, ref POINT lpPoint);

    protected override void WndProc(ref Message m)
    {
        // Disable some TextBox interactions, so it is intact as the Label
        if (m.Msg == WM_SETFOCUS || m.Msg == WM_ENABLE || m.Msg == WM_SETCURSOR)
            return;

        // When the boreder should be painted
        if (m.Msg == WM_NCPAINT)
        {
            // Get the rect of the client area in the screen coordinates.
            var clientOrigin = new POINT(0, 0);
            ClientToScreen(Handle, ref clientOrigin);
            GetClientRect(Handle, out var clientRect);
            clientRect.X = clientOrigin.X;
            clientRect.Y = clientOrigin.Y;

            // Get the rect of the window area in the screen coordinates.
            GetWindowRect(Handle, out var windowRect);

            // Calculate the rect of the client area in the window coordinates.
            // This will be our clipping area, because we want to paint only the border.
            var clip = new Rectangle(
                clientRect.Left - windowRect.Left,
                clientRect.Top - windowRect.Top,
                clientRect.Width,
                clientRect.Height
                );

            // Get the Graphics, set the clip and fill with the BackColor.
            var dc = GetWindowDC(Handle);
            using (Graphics g = Graphics.FromHdc(dc))
            {
                g.SetClip(clip, CombineMode.Exclude);
                g.FillRectangle(new SolidBrush(BackColor), 0, 0, windowRect.Width, windowRect.Height);
            }
            
            return;
        }

        base.WndProc(ref m);
    }
}

结果:

100 %

100%

200 %

200%

我通过 TableLayoutPanel 中那些糟糕的解决方案得出了这个结论:

  1. 垂直居中——对齐相当稳定,但无法对齐基线。
  2. 通过填充进行微调 - 在较高 DPI 上仍然不够稳定。
  3. 使用无边框文本框代替标签 - 无边框文本框的对齐方式与标签相同。

该解决方案的灵感来自于:

  1. https://stackoverflow.com/a/27027829/2408668
  2. https://stackoverflow.com/a/74106039/2408668
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如果 DPI 发生变化,如何正确地将标签与文本框对齐? 的相关文章

  • GCC C++ (ARM) 和指向结构体字段的 const 指针

    假设有一个简单的测试代码 typedef struct int first int second int third type t define ADDRESS 0x12345678 define REGISTER type t ADDRE
  • Tensorflow 中的自定义资源

    由于某些原因 我需要为 Tensorflow 实现自定义资源 我试图从查找表实现中获得灵感 如果我理解得好的话 我需要实现3个TF操作 创建我的资源 资源的初始化 例如 在查找表的情况下填充哈希表 执行查找 查找 查询步骤 为了促进实施 我
  • MEX 文件中的断言导致 Matlab 崩溃

    我正在使用mxAssert 宏定义为matrix h在我的 C 代码中 mex 可以完美编译 当我调用的 mex 代码中违反断言时 该断言不会导致我的程序崩溃 而是导致 Matlab 本身崩溃 我错过了什么吗 这是有意的行为吗 当我查看 M
  • 添加对共享类的多个 WCF 服务的服务引用

    我正在尝试将我的 WCF Web 服务拆分为几个服务 而不是一个巨大的服务 但是 Visual Studio Silverlight 客户端 复制了两个服务共享的公共类 这是一个简单的例子来说明我的问题 在此示例中 有两个服务 两者都返回类
  • 获取两个字符串之间的公共部分c# [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我需要的是获取两个单词之间的共同部分并获取差异 例子 场景1 word1 感言 word2 Test 将返回 公共部分Test 不同之
  • 在 OpenCL 中将函数作为参数传递

    是否可以在 OpenCL 1 2 中将函数指针传递给内核 我知道可以用C实现 但不知道如何在OpenCL的C中实现 编辑 我想做这篇文章中描述的同样的事情 在 C 中如何将函数作为参数传递 https stackoverflow com q
  • 通信对象 System.ServiceModel.Channels.ServiceChannel 不能用于通信

    通信对象System ServiceModel Channels ServiceChannel 无法用于通信 因为它处于故障状态 这个错误到底是什么意思 我该如何解决它 您收到此错误是因为您让服务器端发生 NET 异常 并且您没有捕获并处理
  • 处理 fanart.tv Web 服务响应 JSON 和 C#

    我正在尝试使用 fanart tv Webservice API 但有几个问题 我正在使用 Json Net Newtonsoft Json 并通过其他 Web 服务将 JSON 响应直接反序列化为 C 对象 这里的问题是元素名称正在更改
  • 在 C++11 中省略返回类型

    我最近发现自己在 C 11 模式下的 gcc 4 5 中使用了以下宏 define RETURN x gt decltype x return x 并编写这样的函数 template
  • 获取从属性构造函数内部应用到哪个属性的成员?

    我有一个自定义属性 在自定义属性的构造函数内 我想将属性的属性值设置为属性所应用到的属性的类型 是否有某种方式可以访问该属性所应用到的成员从我的属性类内部 可以从 NET 4 5 using CallerMemberName Somethi
  • 如何在 VS 中键入时显示方法的完整文档?

    标题非常具有描述性 是否有任何扩展可以让我看到我正在输入的方法的完整文档 我想查看文档 因为我可以在对象浏览器中看到它 其中包含参数的描述和所有内容 而不仅仅是一些 摘要 当然可以选择查看所有覆盖 它可能是智能感知的一部分 或者我不知道它并
  • VS30063:您无权访问 https://dev.azure.com

    我正在尝试在 asp net core 2 1 mvc 应用程序中使用以下代码连接 Azure DevOps Uri orgUrl new Uri https dev azure com xxxxx String personalAcces
  • 如何用 kevent() 替换 select() 以获得更高的性能?

    来自Kqueue 维基百科页面 http en wikipedia org wiki Kqueue Kqueue 在内核和用户空间之间提供高效的输入和输出事件管道 因此 可以修改事件过滤器以及接收待处理事件 同时每次主事件循环迭代仅使用对
  • std::bind 重载解析

    下面的代码工作正常 include
  • 从匿名类型获取值

    我有一个方法如下 public void MyMethod object obj implement 我这样称呼它 MyMethod new myparam waoww 那么我该如何实施MyMethod 获取 myparam 值 Edit
  • 同时从多个流中捕获、最佳方法以及如何减少 CPU 使用率

    我目前正在编写一个应用程序 该应用程序将捕获大量 RTSP 流 在我的例子中为 12 个 并将其显示在 QT 小部件上 当我超过大约 6 7 个流时 问题就会出现 CPU 使用率激增并且出现明显的卡顿 我认为它不是 QT 绘制函数的原因是因
  • 我应该在应用程序退出之前运行 Dispose 吗?

    我应该在应用程序退出之前运行 Dispose 吗 例如 我创建了许多对象 其中一些对象具有事件订阅 var myObject new MyClass myObject OnEvent OnEventHandle 例如 在我的工作中 我应该使
  • 以编程方式使用自定义元素创建网格

    我正在尝试以编程方式创建一个网格 并将自定义控件作为子项附加到网格中 作为 2x2 矩阵中的第 0 行第 0 列 为了让事情变得更棘手 我使用了 MVVM 设计模式 下面是一些代码可以帮助大家理解这个想法 应用程序 xaml cs base
  • 在基类集合上调用派生方法

    我有一个名为 A 的抽象类 以及实现 A 的其他类 B C D E 我的派生类持有不同类型的值 我还有一个 A 对象的列表 abstract class A class B class A public int val get privat
  • WPF/数据集:如何通过 XAML 将相关表中的数据绑定到数据网格列中?

    我正在使用 WPF DataSet 连接到 SQL Server Express XAML 和 C Visual Studio 2013 Express 我从名为 BankNoteBook 的现有 SQL Server Express 数据

随机推荐