如何解决如果标记为 DPI 感知并与多个监视器一起使用,Winforms 应用程序将抛出 Win32Exception
我有一个 Windows 窗体应用程序 (.NET Framework 4.8),它有一个 TabControl tabControl
作为主要对象。我用它来切换到不同的屏幕,我有一个 next 和 prevIoUs 按钮,用于选择带有以下代码的下一个或上一个选项卡:
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 的一部分,而是用于控制当前选定的行。
更新 3:我在创建新项目时无法自己重现它。以不同的 DPI 值(100% 和 125%)重新启动没有帮助。我发现第一次点击时下拉背景是黑色的。如果将鼠标悬停在某个选项上,它会显示为正常突出显示的选项(蓝色背景和白色文本),直到我再次离开它。这发生在两个屏幕上。
我还发现,如果我将光标放在占位符 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 举报,一经查实,本站将立刻删除。