如果标记为 DPI 感知并与多个监视器一起使用,Winforms 应用程序将抛出 Win32Exception

如何解决如果标记为 DPI 感知并与多个监视器一起使用,Winforms 应用程序将抛出 Win32Exception

我有一个 Windows 窗体应用程序 (.NET Framework 4.8),它有一个 TabControl tabControl 作为主要对象。我用它来切换到不同的屏幕,我有一个 nextprevIoUs 按钮,用于选择带有以下代码的下一个或上一个选项卡:

private void ButtonNextTab(object sender,EventArgs e)
{
    int index = tabControl.Selectedindex;
    tabControl.SelectTab(index + 1); // index - 1 for ButtonPrevIoUsTab
}

我通过在 app.config 中包含以下内容将我的应用程序设置为 DPI 感知:

<System.Windows.Forms.ApplicationConfigurationSection>
   <add key="DpiAwareness" value="PerMonitorV2" />
</System.Windows.Forms.ApplicationConfigurationSection>

在最后一个选项卡上,我有一个 DataGridView。如果我使用按钮进入最后一个选项卡两次,无论我单击按钮的速度有多快,我都会收到以下异常:System.ComponentModel.Win32Exception: 'Error creating window handle.',并且它似乎被抛出到 { {1}} 方法。如果我用 SelectTab 替换 SelectTab,也会发生这种情况。

但是,如果我删除 tabControl.Selectedindex = index + 1 中的标记或使用 TabControl 的选项卡多次导航到选项卡,则不会发生这种情况。我在第二台显示器上以 100% 的比例创建并运行应用程序,但如果我在我的笔记本电脑主屏幕上以 125% 的比例运行它,则不会出现问题(尽管有趣的是,应用程序总是以 100% 启动,直到 DPI 更改事件出现通过将应用程序从一个屏幕移动到另一个屏幕来触发)。我只能在 100% 的屏幕上重现此问题,而从未在 125% 的屏幕上重现此问题。如果我将主屏幕上的缩放比例设置为 100%,问题就会消失,如果两个屏幕都设置为 125%,我也无法重现它。

我找不到有关此问题的任何信息。有什么办法可以预防吗?

Image of the exception information,barely contains any useful information


更新:我尝试将 DataGridView.DisableHighDpiImprovements 设置为 app.config,但没有解决


更新 2:完整的堆栈跟踪(图像仅显示第一位):

"false"

作为参考,这是 datagridview 的样子(删除标题中的文本),右侧的按钮不是 datagridview 的一部分,而是用于控制当前选定的行。

enter image description here


更新 3:我在创建新项目时无法自己重现它。以不同的 DPI 值(100% 和 125%)重新启动没有帮助。我发现第一次点击时下拉背景是黑色的。如果将鼠标悬停在某个选项上,它会显示为正常突出显示的选项(蓝色背景和白色文本),直到我再次离开它。这发生在两个屏幕上。

black dropdown menu

我还发现,如果我将光标放在占位符 at System.Windows.Forms.NativeWindow.CreateHandle(CreateParams cp) at System.Windows.Forms.Control.CreateHandle() at System.Windows.Forms.ComboBox.CreateHandle() at System.Windows.Forms.Control.RecreateHandleCore() at System.Windows.Forms.ComboBox.RecreateHandleCore() at System.Windows.Forms.ComboBox.OnFontChanged(EventArgs e) at System.Windows.Forms.Control.set_Font(Font value) at System.Windows.Forms.Control.WmDpiChangedBeforeParent(Message& m) at System.Windows.Forms.Control.WndProc(Message& m) at System.Windows.Forms.ComboBox.WndProc(Message& m) at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m) at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m) at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd,Int32 msg,IntPtr wparam,IntPtr lparam) 中的两个文本字段中,都不会发生异常。将光标放在这些文本字段之一后,文本字段本身像下拉列表一样显示为黑色,但只有一次(与下拉列表不同),之后下拉列表和其他文本框不再是黑色的。这会向我表明占位符行有问题,但我无法找出是什么,我不知道它与不同的 DPI 问题有何关系。其中一栏还有一个很长的工具提示,我认为可能会导致问题,但删除它没有任何作用。


更新 4:如果在表单设计器中将 DataGridView 的 Visible 属性设置为 false,则不会发生错误。这似乎将问题限制在与 DataGridView 和多个屏幕上的不同缩放相关的问题上。我还尝试在占位符行的两个文本字段中以编程方式设置文本,但没有奏效。

解决方法

我找到了一种解决方法,如果没有选择单元格,则手动选择 datagridview 中的第一个文本字段,问题不再发生:

private void ButtonNextTab(object sender,EventArgs e)
{
    int index = tabControl.SelectedIndex;
    if (index == 1 && dataGridView.CurrentCell is null)
    {
        dataGridView.Rows[0].Cells[1].Selected = true;
    }
    tabControl.SelectTab(index + 1);
}

我仍然不知道实际问题是什么,或者这个解决方法如何防止这种情况发生,但至少它是有效的。如果我有时间重写所有内容,我可能会切换到 WPF。如果有人遇到此问题并找出导致问题的原因,请将其添加为答案。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?
Java在半透明框架/面板/组件上重新绘画。
Java“ Class.forName()”和“ Class.forName()。newInstance()”之间有什么区别?
在此环境中不提供编译器。也许是在JRE而不是JDK上运行?
Java用相同的方法在一个类中实现两个接口。哪种接口方法被覆盖?
Java 什么是Runtime.getRuntime()。totalMemory()和freeMemory()?
java.library.path中的java.lang.UnsatisfiedLinkError否*****。dll
JavaFX“位置是必需的。” 即使在同一包装中
Java 导入两个具有相同名称的类。怎么处理?
Java 是否应该在HttpServletResponse.getOutputStream()/。getWriter()上调用.close()?
Java RegEx元字符(。)和普通点?