PictureBox 未显示在第二个相同的表单上
PictureBox not showing on second identical form
我有一个 winforms 应用程序,它必须在特定条件下在两个屏幕上显示紧急消息。
这两条消息作为两个相同的表单传递,每个表单都在每个屏幕上实例化。每个表单都包含一个带有图像的可配置 PictureBox。
当条件满足时,两个窗体在两个屏幕上都正确启动,但是图片只在其中一个(主屏幕)显示,而另一个不显示。
表单在 foreach 上实例化,因此它们仅在不同的屏幕上使用相同的构造函数。
表格class:
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();
}));
}
}
}
结果:
我似乎没有发现设置有任何问题,但显然我遗漏了一些东西,我希望有人能帮助我。
提前致谢!
在Windows中,有一个概念叫做"virtual screen"。当您只有一台显示器时,虚拟屏幕与物理屏幕完全相同,您可以忽略它。但是,当您有多个显示器时,它就开始变得重要了。
简而言之,虚拟屏幕是构成Windows桌面的所有显示器的边框。下图为示例——虚拟屏幕显示为灰色:
让事情变得棘手的是,出于兼容性原因,点 (0, 0) 始终位于 primary 监视器的左上角。因此,如果您的辅助显示器位于主显示器的右 and/or 底部,则它的坐标比主显示器大,一切正常。但是,如果您的辅助显示器位于主显示器的左侧 and/or 顶部,则其坐标为 负值。
你的情况就是这种情况。右侧显示器显然设置为您的主显示器,因此其左上角的坐标为 (0, 0)。这意味着左侧监视器的坐标为 negative。因此,当您从对应的 Screen
对象的 Bounds
属性 中检索 Top
和 Left
属性时,您会得到负值。
如果您使用这些坐标来定位表单,这将是正确的,因为表单(和任何其他顶级 windows)使用虚拟屏幕坐标进行定位。
但是,您正在将 child 表单(即控件)定位在表单上。子 windows 使用 client 坐标,这是相对于父的。在客户端坐标中,父级的左上角始终位于 (0, 0),因此如果您希望 PictureBox 位于窗体的左上角,则应对其 Top
和 [=11 进行硬编码=] 属性为 0.
另见 。
我有一个 winforms 应用程序,它必须在特定条件下在两个屏幕上显示紧急消息。
这两条消息作为两个相同的表单传递,每个表单都在每个屏幕上实例化。每个表单都包含一个带有图像的可配置 PictureBox。
当条件满足时,两个窗体在两个屏幕上都正确启动,但是图片只在其中一个(主屏幕)显示,而另一个不显示。
表单在 foreach 上实例化,因此它们仅在不同的屏幕上使用相同的构造函数。
表格class:
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();
}));
}
}
}
结果:
我似乎没有发现设置有任何问题,但显然我遗漏了一些东西,我希望有人能帮助我。
提前致谢!
在Windows中,有一个概念叫做"virtual screen"。当您只有一台显示器时,虚拟屏幕与物理屏幕完全相同,您可以忽略它。但是,当您有多个显示器时,它就开始变得重要了。
简而言之,虚拟屏幕是构成Windows桌面的所有显示器的边框。下图为示例——虚拟屏幕显示为灰色:
让事情变得棘手的是,出于兼容性原因,点 (0, 0) 始终位于 primary 监视器的左上角。因此,如果您的辅助显示器位于主显示器的右 and/or 底部,则它的坐标比主显示器大,一切正常。但是,如果您的辅助显示器位于主显示器的左侧 and/or 顶部,则其坐标为 负值。
你的情况就是这种情况。右侧显示器显然设置为您的主显示器,因此其左上角的坐标为 (0, 0)。这意味着左侧监视器的坐标为 negative。因此,当您从对应的 Screen
对象的 Bounds
属性 中检索 Top
和 Left
属性时,您会得到负值。
如果您使用这些坐标来定位表单,这将是正确的,因为表单(和任何其他顶级 windows)使用虚拟屏幕坐标进行定位。
但是,您正在将 child 表单(即控件)定位在表单上。子 windows 使用 client 坐标,这是相对于父的。在客户端坐标中,父级的左上角始终位于 (0, 0),因此如果您希望 PictureBox 位于窗体的左上角,则应对其 Top
和 [=11 进行硬编码=] 属性为 0.
另见