如何使用 C# 和 WinForm 创建 1 像素宽 window

How to create an 1 pixel wide window using C# and WinForm

我想创建一个在桌面底角显示一个小 window 的应用程序。在启动时,window 应该非常小,理想情况下,宽度只有几个像素。

这是我用来执行此操作的代码:

public partial class DurationT64 : Form
{
    private Size fullSize;
    private Point fullPos;
    private Point compactPos;

    public DurationT64()
    {
        InitializeComponent();

        var workingArea = Screen.PrimaryScreen.WorkingArea;

        this.MinimumSize = new Size(0, this.Height);
        this.MaximumSize = new Size(this.Width, this.Height);

        // fullPos: the window location when it is in full size form.
        fullPos = new Point(workingArea.Right - this.Width, workingArea.Bottom - this.Height);
        this.Location = fullPos;
        // fullSize: the size of the windown when it is in full size form.
        fullSize = new Size(this.Width, this.Height);
        this.Size = fullSize;

        // compactPos: the window location when it is in compact size form.
        compactPos = new Point(workingArea.Right - 30, fullPos.Y);
        this.Width = 1;
        this.Location = compactPos;
    }
}

如您所见,在此示例中,我打算创建一个宽度仅为 1 像素的 window,靠近主监视器的右边缘放置。

然而,我意识到 window 并没有我预期的那么小。它缩小到 20 像素宽,但不少于此。例如,请参考下面的屏幕截图: an image shows that the window is wider than it suppose to be

我对这个问题做了一些研究,注意到 Zach Johnson (@zach-johnson) 在 2009 年提出了一个解决方案。这是 link Overcome OS Imposed Windows Form Minimum Size Limit

但是,link 中提出的其他方法(Zach 提出的拦截 WM_ 消息和@Ace 提出的 SetBoundsCore 方法)对我有用。

任何人都可以给我一些解决这个问题的方法吗?如果可能,最好是完全基于 C#/Winform 且不依赖本机 Win32 window 消息循环的解决方案。

非常感谢!

这很简单,Winforms 确保 window 不能小于系统强加的最小尺寸 window,暴露为 中的 SystemInformation.MinWindowTrackSize property。网。这是一个 "safety" 设置,它确保用户在调整它时不会将 window 设置得太小,从而失去对它的控制。同样的考虑也适用于代码。

绕过这个限制不需要任何魔法,你需要做两件事:

  • 将 FormBorderStyle 属性 设置为 None 这样用户就无法调整 window.
  • 的大小
  • 在 创建 window 之后设置大小 。 Load事件最好。

关于您现有代码的一些评论:修改 Width/Height/Size 属性时要小心,您在构造函数中做的太多了,它无法正常工作。在构造函数中,它们还不匹配 window 的实际大小。并且在具有高分辨率显示器的现代机器上根本不会接近,自动缩放以匹配视频适配器的 DPI 在今天很重要。您必须推迟到创建 window 并完成缩放,Load 事件是此类代码的合适位置。实际使用 Load 的少数原因之一。

并注意你的 Location 属性 计算不充分,它没有考虑任务栏的位置。它在我的机器上不起作用,我喜欢右边的任务栏。

最小复制:

public partial class Form1 : Form {
    public Form1() {
        InitializeComponent();
        this.FormBorderStyle = FormBorderStyle.None;
    }
    protected override void OnLoad(EventArgs e) {
        this.Width = 1;
        base.OnLoad(e);
    }
}

请记住,您需要鹰眼才能在屏幕上找到它:)