在Windows窗体应用程序中跟踪屏幕变化和屏幕分辨率变化以更改表单大小。

7

我希望根据屏幕和分辨率的大小来改变表单的大小。

我需要正确的事件来跟踪这些屏幕更改以及运行时的屏幕分辨率更改。

换句话说,

  1. 如果用户正在使用两个屏幕并将应用程序移动到另一个屏幕,则应跟踪该操作并相应地更改大小,即如果新屏幕的分辨率较低,则减小大小,如果分辨率较大,则增加大小。

  2. 还要跟踪同一屏幕上的屏幕分辨率更改,并相应地更改大小。

我知道如何更改表单大小,获取当前屏幕及其分辨率,只需要这些事件来跟踪这些更改。


1
作为起点,请查看SystemEvents类。 - Steve
@Steve:谢谢,这解决了一半的问题,那么如何跟踪屏幕变化呢? - Indigo
@DonBoitnott:基本上,我有一个主要的GroupBox和一个内部的Panel。因此,我也在更改GroupBox和Panel的大小。所有内容都包含在Panel中,并可以使用滚动条访问。 - Indigo
1
很好。那么我假设你想让表单本身在所有方面都可见? 有更大的目标吗? 我想知道当奇怪的情况发生时会怎样,比如:如果我正在将表单拖到另一个监视器上,并且我在TitleBar的极右点(紧挨着ControlBox)握住,你调整大小足够小以使该空间消失,我剩下什么? - DonBoitnott
@DonBoitnott:是的,正确。然而,我在这里尝试采取一种相当简单的方法。这个应用程序比分辨率只有768个垂直分辨率的小型笔记本电脑要稍微大一些(仅在高度上)。在这种情况下,我只想减少我的应用程序的高度,使其在那台笔记本电脑屏幕上能够很好地显示,并且仍然能够将所有控件包装在一个面板内并通过滚动可用。我知道这个应用程序将要使用的系统的确切分辨率。因此,没有必要创建复杂的用户界面。 - Indigo
显示剩余2条评论
1个回答

9

在审阅此答案后,我决定完善并添加更多信息以形成更完整的解决方案。

挑战

追踪一个表单当前所呈现的屏幕。如果用户将表单拖到另一台监视器上或拔出监视器,则会发生变化。如果用户手动将窗口拖到不同的显示器上或直接更改分辨率,则分辨率可能会更改。

首先,需要跟踪表单的位置。我们需要钩入表单上下文中的移动事件,幸运的是,.Net框架提供了这样的事件,它被命名为Control.Move事件

其次,我们需要钩入屏幕分辨率更改事件,可以使用SystemEvents.DisplaySettingsChanged事件来完成。

最后,将以上两部分结合起来,得到如下:

struct Resolution
{
    public int Width;
    public int Height;
}

int previous = -1;
int current = -1;

private bool CheckScreenChanged()
{
    bool changed = false;
    current = GetScreenIndex();

    if (current != -1 && previous != -1 && current != previous) // form changed screen.
    {
        changed = true;
    }

    previous = current;

    return changed;
}

private int GetScreenIndex()
{
    return Array.IndexOf(Screen.AllScreens, Screen.FromControl(this));
}

private Resolution GetCurrentResolution()
{
    Screen screen = Screen.FromControl(this);
    Resolution res = new Resolution();
    res.Width = screen.Bounds.Width;
    res.Height = screen.Bounds.Height;

    return res;
}

private void SetResolutionLabel()
{
    Resolution res = GetCurrentResolution();
    label2.Text = String.Format("Width: {0}, Height: {1}", res.Width, res.Height);
}

private void ScreenChanged()
{
    label1.Text = "Screen " + current.ToString();
}

private void Form_Moved(object sender, System.EventArgs e)
{
    bool changed = CheckScreenChanged();
    if (changed == true)
    {
        ScreenChanged();
        SetResolutionLabel();
    }
}

public void SystemEvents_DisplaySettingsChanged(object sender, EventArgs e)
{
    SetResolutionLabel();
}

public void Initialize()
{
    this.Move += Form_Moved;
    SystemEvents.DisplaySettingsChanged += new
    EventHandler(SystemEvents_DisplaySettingsChanged);

    previous = GetScreenIndex();
    current = GetScreenIndex();
    ScreenChanged();
    SetResolutionLabel();
}

上面的代码在一个简单的表单上进行了测试,表单中有两个标签,分别叫做label1和label2,在屏幕大小或分辨率发生变化时更新这些标签。

以下是代码在我的主屏幕/显示器上运行的截图:

Screen0

当表单被拖到我的次要屏幕/显示器上时,如下所示:

enter image description here


谢谢,我已经完成了并且运行良好。不过,问题仍然存在,如何跟踪屏幕变化(问题中的第1点)。 - Indigo
我认为您没有进行正确的关键字搜索,OP想知道在多屏系统中屏幕何时更改,他想知道可以通知屏幕切换的事件,而不是通过监视器检测分辨率。 - King King
1
由于这是一个静态事件,当您的应用程序被处理时,您必须分离您的事件处理程序,否则会导致内存泄漏。 [SystemEvents.DisplaySettingsChanged Event] (https://learn.microsoft.com/en-us/dotnet/api/microsoft.win32.systemevents.displaysettingschanged?view=dotnet-plat-ext-3.1) - TechAurelian

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接