我有一个 Windows 窗体应用程序和一个多显示器配置:
主显示器(笔记本): 分辨率:1980x1080(推荐) 缩放比例:125%(推荐)
外部显示: 分辨率:1980x1080(推荐) 缩放:100%(推荐)
Windows 版本:Windows 10 版本 1909(操作系统内部版本 18363.1198)
应用:
场景 1:
在主显示器上启动应用程序: 应用:模糊(可能按系统缩放到 125%)。 工具提示:模糊、预期大小、预期位置。 => 好的。
将正在运行的应用程序移动到外部显示器: 应用程序:清除(可能不再缩放)=> 好的 工具提示:模糊、比预期大、位置错误甚至屏幕外 - 鼠标光标向左越远,向左的位置越偏离。 => 不行。
场景 2:
在外部显示器上启动应用程序: 应用:透明(可能没有缩放)。 工具提示:清晰、预期大小、预期位置。 => 好的。
将正在运行的应用程序移至主显示屏: 应用程序:模糊(可能缩放到 125%)=> 好的 工具提示:清晰、比预期小、位置错误甚至离开屏幕 - 鼠标光标向右移动得越远,向左移动的位置越远。 => 不行。
我知道缩放出现在主显示器上以及为什么不在外部显示器上的原因。参见示例:https://support.microsoft.com/en-us/help/3025083/windows-scaling-issues-for-high-dpi-devices 但我不明白为什么工具提示会在外部显示器上缩放,即使应用程序的其余部分不是,并且外部显示器的缩放设置为 100%。 我的目标是修复外部显示器上的工具提示大小和位置。
我曾尝试用一个简单的测试应用程序来重现该问题,该应用程序使用相同的 .NET Framework 目标版本和 DevExpress 版本,但尚未成功。
[编辑]:如果您在应用程序已经运行时休眠 Windows,从休眠状态唤醒后,问题似乎消失了:工具提示的大小和位置符合预期。
[EDIT2]:我已经与 DevExpress 支持人员讨论过这个问题,我们已经创建了一个测试项目来重现该问题,该项目不包含任何 DevExpress 组件,而只包含标准的 Winforms 控件。
DevExpress 似乎使用具有 WS_POPUP 窗口样式的窗口来显示工具提示。
重现问题的第二个必需部分是另一种显示在不同显示器上的表单(即不是主表单显示工具提示的那个),具有不同的缩放比例。
这是一个几乎完整的示例来重现这一点。我想知道这是否应该被视为 Windows 或 WinForms 错误?
Form1.cs:
using System;
using System.Drawing;
using System.Windows.Forms;
namespace WrongTooltipLocation
{
public partial class Form1 : Form
{
/* Windows Display Settings:
* - Main Screen
* Scaling: 125%
*
* - Second Screen
* Scaling: 100%
*
* To show the tooltip, move the mouse cursor over Button2.
*/
public Form1()
{
InitializeComponent();
button2.MouseEnter += Button2_MouseEnter;
}
private void Button2_MouseEnter(object sender, EventArgs e) {
_messageForm.Activate();
// Show tooltip
TooltipForm tooltipForm = new TooltipForm();
tooltipForm.Location = Cursor.Position;
tooltipForm.Size = new Size(100, 100);
tooltipForm.Visible = true;
}
protected override void OnShown(EventArgs e) {
base.OnShown(e);
ShowMessage();
// After the ShowMessage method is called, move the main form to the second screen and keep the message form on the main screen
// => tooltips are displayed at the wrong location
}
Form _messageForm;
private void ShowMessage()
{
_messageForm = new Form()
{
TopLevel = true,
ControlBox = false,
StartPosition = FormStartPosition.Manual,
FormBorderStyle = FormBorderStyle.None,
ShowInTaskbar = false,
Visible = false
};
Label label = new Label()
{
Location = new Point(20, 20),
Text = "Message Form",
ForeColor = Color.Green
};
_messageForm.Controls.Add(label);
_messageForm.Show();
_messageForm.Activate();
}
}
public class TooltipForm : Form {
public TooltipForm() {
this.StartPosition = FormStartPosition.Manual;
BackColor = Color.Red;
// This label is blurry on the second screen and clear on the main screen.
// Shouldn't that be the other way around?
Label label = new Label()
{
Location = new Point(20, 20),
Text = "My Tooltip",
ForeColor = Color.Yellow
};
Controls.Add(label);
}
protected override CreateParams CreateParams {
get {
CreateParams cp = base.CreateParams;
cp.Style = unchecked((int)0x80000000); //WS_POPUP
return cp;
}
}
}
}
Form1.designer.cs
using System;
namespace WrongTooltipLocation
{
partial class Form1
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
this.toolTip1 = new System.Windows.Forms.ToolTip(this.components);
this.button2 = new System.Windows.Forms.Button();
this.SuspendLayout();
//
// button2
//
this.button2.Location = new System.Drawing.Point(65, 84);
this.button2.Name = "button2";
this.button2.Size = new System.Drawing.Size(75, 23);
this.button2.TabIndex = 1;
this.button2.Text = "button2";
this.toolTip1.SetToolTip(this.button2, "Button 2");
this.button2.UseVisualStyleBackColor = true;
//
// Form1
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(632, 278);
this.Controls.Add(this.button2);
this.Name = "Form1";
this.Text = "Form1";
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.ToolTip toolTip1;
private System.Windows.Forms.Button button2;
}
}
程序.cs
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Threading;
using System.Windows.Forms;
namespace WrongTooltipLocation
{
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
}
}
App.config
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<appSettings>
</appSettings>
<startup useLegacyV2RuntimeActivationPolicy="true">
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2" />
</startup>
<runtime>
<generatePublisherEvidence enabled="false" />
<loadFromRemoteSources enabled="true" />
</runtime>
</configuration>
应用程序清单
<?xml version="1.0" encoding="utf-8"?>
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
<assemblyIdentity version="1.0.0.0" name="MyApplication.app"/>
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
<security>
<requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
<requestedExecutionLevel level="asInvoker" uiAccess="false" />
</requestedPrivileges>
</security>
</trustInfo>
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
<application>
</application>
</compatibility>
<application xmlns="urn:schemas-microsoft-com:asm.v3">
<windowsSettings>
<dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">false</dpiAware>
</windowsSettings>
</application>
</assembly>