【问题标题】:PictureBox not showing on second identical formPictureBox 未显示在第二个相同的表单上
【发布时间】:2017-05-04 14:47:13
【问题描述】:

我有一个 winforms 应用程序,它必须在特定条件下在两个屏幕上显示紧急消息。

这两条消息作为两个相同的表单传递,每个表单都在每个屏幕上实例化。每个表单都包含一个带有图像的可配置 PictureBox。

满足条件时,两个窗体在两个屏幕上都正确启动,但图片只显示在两个屏幕(主屏幕)之一,另一个不显示。

表单在 foreach 上实例化,因此它们仅在不同的屏幕上使用相同的构造函数。

表单类:

public partial class FormClearingMessage : Form
{
    public FormClearingMessage(Screen s)
    {
        InitializeComponent();
        SetParameters(s);
    }

    private void SetParameters(Screen s)
    {
        this.Top = s.Bounds.Top;
        this.Left = s.Bounds.Left;
        this.Width = s.Bounds.Width;
        this.Height = s.Bounds.Height;
        this.pictureBox1.Top = this.Top + 20;
        this.pictureBox1.Left = this.Left + 20;
        this.pictureBox1.Width = this.Width - 40;
        this.pictureBox1.Height = this.Height - 40;
        this.pictureBox1.MaximumSize = new Size(this.pictureBox1.Width, this.pictureBox1.Height);
        this.LoadImage();  
    }

    private void LoadImage()
    {
                string imagePath = Utils.ResolveSymbolicPath(c.ReadCfgEntry("clearingMessage/imagePath", null));
                if (File.Exists(imagePath))
                    this.pictureBox1.Load(imagePath);
                else
                    throw new Exception();

    }
} 

初始化:

        // Initialize Clearing Message forms
        Screen[] screens = Screen.AllScreens;
        _clearingMessageForms = new List<FormClearingMessage>();

        foreach (Screen s in screens)
        {
            _clearingMessageForms.Add(new FormClearingMessage(s));
        }

条件满足时的说明:

                if (singleMessage.InformationType == _infoTypeForEmergency)
                {
                    if (_clearingMessageForms != null)
                   {
                        foreach (FormClearingMessage fcm in _clearingMessageForms)
                        {
                            if (!fcm.Visible)
                                this.Invoke(new Action(() =>     {
                                    fcm.Show();
                                }));           
                        }
                    }
                }

结果:

我似乎找不到设置有什么问题,但显然我遗漏了一些东西,我希望有人能帮助我。

提前致谢!

【问题讨论】:

  • 很可能,问题在于Screen.Bounds 返回的内容。如果Top 和/或Left 是负值,则说明您将PictureBox 错误地放置在表单上。您可以为TopLeft 硬编码0;表单的客户区总是的原点位于 (0, 0)。
  • 所以你的意思是图片框的位置总是相对于表单?
  • link宾果游戏。那成功了。非常感谢你的帮助。随时发布答案,以便我可以标记它:)
  • 我认为 SO 的目的是分享问题,以便其他人在遇到相同问题时可以找到答案。我知道我的答案是微不足道的,但鉴于我没有找到预先存在的答案这一事实足以让我继续提出这个问题,也许可以搁置无用的讽刺。
  • 这个词是UpvoteFlag 恰恰相反! - 另外:讽刺永远不会无用,相信我..

标签: c# winforms picturebox multiple-monitors


【解决方案1】:

在 Windows 中,有一个概念叫做“虚拟屏幕”。当您只有一个显示器时,虚拟屏幕与物理屏幕相同,您可以很高兴地忽略它。但是,当您有多个显示器时,它就开始变得重要了。

简而言之,虚拟屏幕是构成 Windows 桌面的所有显示器的边界矩形。下图是一个例子——虚拟屏幕显示为灰色:

让事情变得棘手的是,出于兼容性原因,点 (0, 0) 始终位于 primary 监视器的左上角。因此,如果您的辅助显示器位于主显示器的右侧和/或底部,则它的坐标大于主显示器,并且一切正常。但是,如果您的辅助显示器位于主显示器的左侧和/或顶部,则其坐标为

您的情况就是这种情况。右侧的显示器明确设置为主显示器,因此其左上角有坐标 (0, 0)。这意味着左侧监视器具有坐标。因此,当您从其对应的Screen 对象的Bounds 属性中检索TopLeft 属性时,您会得到负值。

如果您使用这些坐标来定位表单,这将是正确的,因为表单(和任何其他顶级窗口)使用虚拟屏幕坐标进行定位。

但是,您将 child 表单(即控件)定位在表单上。子窗口使用相对于父窗口的客户端 坐标。在客户端坐标中,父级的左上角始终位于 (0, 0),因此如果您希望 PictureBox 位于窗体的左上角,则应将其 TopLeft 属性硬编码为为 0。

另见this other answer

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-06-05
    • 1970-01-01
    • 2012-03-03
    • 1970-01-01
    相关资源
    最近更新 更多