С помощью следующего фрагмента кода я динамически создаю и отображаю окна изображений в зависимости от количества экранов, которые я выбираю в поле со списком, как показано на изображении ниже:
Кажется, это отлично работает, но проблема возникает, когда я увеличиваю размер приложения, тогда поля с изображениями не расширяются правильно, как на изображении ниже:
Увеличение приложения:
Уменьшение размера приложения:
private void CreatePictureBoxes(int num)
{
panelCameras.Controls.Clear();
int spacing = 2;
int numRows = (int)Math.Ceiling((double)num / 2);
int pbWidth = (panelCameras.ClientSize.Width - (3 * spacing)) / 2;
int pbHeight = (panelCameras.ClientSize.Height - ((numRows + 1) * spacing)) / numRows;
if (num == 1)
{
pbWidth = panelCameras.ClientSize.Width - (2 * spacing);
pbHeight = panelCameras.ClientSize.Height - (2 * spacing);
}
else if (num == 2)
{
pbWidth = (panelCameras.ClientSize.Width - (2 * spacing)) / 2;
pbHeight = panelCameras.ClientSize.Height - (2 * spacing);
}
for (int i = 0; i < num; i++)
{
PictureBox pb = new PictureBox();
pb.BackColor = Color.Black;
pb.SizeMode = PictureBoxSizeMode.StretchImage;
pb.Dock = DockStyle.None;
pb.Anchor = AnchorStyles.None;
pb.Location = new Point((i % 2) * (pbWidth + spacing) + spacing, (i / 2) * (pbHeight + spacing) + spacing);
Label lbl = new Label();
lbl.Text = (i + 1).ToString();
lbl.ForeColor = Color.White;
lbl.AutoSize = false;
lbl.Dock = DockStyle.Fill;
lbl.TextAlign = ContentAlignment.MiddleCenter;
pb.Controls.Add(lbl);
panelCameras.Controls.Add(pb);
pb.Size = new Size(pbWidth, pbHeight);
pb.Dock = DockStyle.None;
pb.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right | AnchorStyles.Bottom;
}
}
Моя лучшая попытка исправить это состояла в том, чтобы создать дополнительный метод для обработки расширения приложения и вызывать его в конце конца метода CreatePictureBoxes
:
private void pb_Resize(object sender, EventArgs e)
{
PictureBox? pb = sender as PictureBox ?? null;
if (pb != null)
{
int spacing = 10;
int numRows = (int)Math.Ceiling((double)panelCameras.Controls.Count / 2);
int pbWidth = (panelCameras.ClientSize.Width - (3 * spacing)) / 2;
int pbHeight = (panelCameras.ClientSize.Height - ((numRows + 1) * spacing)) / numRows;
if (panelCameras.Controls.Count == 1)
{
pbWidth = panelCameras.ClientSize.Width - (2 * spacing);
pbHeight = panelCameras.ClientSize.Height - (2 * spacing);
}
else if (panelCameras.Controls.Count == 2)
{
pbWidth = (panelCameras.ClientSize.Width - (2 * spacing)) / 2;
pbHeight = panelCameras.ClientSize.Height - (2 * spacing);
}
pb.Size = new Size(pbWidth, pbHeight);
pb.Location = new Point((pb.TabIndex % 2) * (pbWidth + spacing) + spacing, (pb.TabIndex / 2) * (pbHeight + spacing) + spacing);
}
}
Это каким-то образом сработало, но я считаю, что это вызовет больше проблем в будущем, и я не считаю, что это хороший подход.
Кто-нибудь знает, как я могу обрабатывать размеры изображений, чтобы они соответствовали размеру приложения?
Заранее спасибо!
Спасибо @dr.null Будет ли то, что сказал Иржи в их ответе, подходящим ответом, или вы знаете лучшее решение?
Принятый ответ является прямым решением проблемы, которую вы привели. Итак, это принято для меня. Однако вам не нужно делать это в первую очередь, элементы управления макетом WinForms существуют по какой-то причине, в основном для того, чтобы избежать того, что вы делаете здесь. Лучшим решением или правильным подходом является использование панели макета, в частности предложенной в моем первом комментарии.
Я бы разделил создание и раскладку панелей, вот так:
public Form1()
{
InitializeComponent();
// ...
panelCameras.Layout += panelCameras_Layout;
}
private void CreatePictureBoxes(int num)
{
panelCameras.Controls.Clear();
for (int i = 0; i < num; i++)
{
PictureBox pb = new PictureBox();
pb.BackColor = Color.Black;
pb.SizeMode = PictureBoxSizeMode.StretchImage;
pb.Dock = DockStyle.None;
pb.Anchor = AnchorStyles.None;
Label lbl = new Label();
lbl.Text = (i + 1).ToString();
lbl.ForeColor = Color.White;
lbl.AutoSize = false;
lbl.Dock = DockStyle.Fill;
lbl.TextAlign = ContentAlignment.MiddleCenter;
pb.Controls.Add(lbl);
panelCameras.Controls.Add(pb);
}
}
protected void panelCameras_Layout(object? sender, LayoutEventArgs levent)
{
var num = panelCameras.Controls.Count;
for (var i = 0; i < num; ++i)
{
int spacing = 2;
int numRows = (int)Math.Ceiling((double)num / 2);
int pbWidth = (panelCameras.ClientSize.Width - (3 * spacing)) / 2;
int pbHeight = (panelCameras.ClientSize.Height - ((numRows + 1) * spacing)) / numRows;
if (num == 1)
{
pbWidth = panelCameras.ClientSize.Width - (2 * spacing);
pbHeight = panelCameras.ClientSize.Height - (2 * spacing);
}
else if (num == 2)
{
pbWidth = (panelCameras.ClientSize.Width - (2 * spacing)) / 2;
pbHeight = panelCameras.ClientSize.Height - (2 * spacing);
}
var pb = panelCameras.Controls[i];
pb.Location = new Point((i % 2) * (pbWidth + spacing) + spacing, (i / 2) * (pbHeight + spacing) + spacing);
pb.Size = new Size(pbWidth, pbHeight);
}
}
Обратите внимание, что я удалил настройку размера и местоположения из CreatePictureBoxes, а также удалил изменение стиля привязки!
Спасибо! Я очень ценю помощь! Кажется, это работает отлично. У меня только один вопрос. Будет ли это правильным подходом к решению этой проблемы или вы поверите, что есть лучшая альтернатива?
Это зависит. Обычно способов много, и выбрать один всегда сложно :), так что не волнуйтесь. Если вам нужно повторно использовать поведение, вы можете получить свой собственный элемент управления (скажем, из панели) и переопределить OnLayout. Часто вы понимаете, что решение уже существует — возможно, вы могли бы использовать TableLayoutPanel. Но если это работает хорошо для вас, используйте его. Вы всегда можете изменить его, если вам нужно.
Нет, используйте TableLayoutPanel, установите во время разработки
SizeType
столбцов и строк, чтобы они делили пространство поровну, состыкуйте поля в ячейках сетки 2x2, и все.