Sicppy Ответов: 2

Как расширить контроль за размером экрана в прокручиваемой панели


Я пытаюсь создать своего рода временную шкалу событий, чтобы синхронизировать события в моей игре с музыкой, я попытался сделать пользовательский элемент управления временной шкалой и поместить его внутрь панели, чтобы я мог прокручивать ее, однако я не могу расширить элемент управления за пределы предела.

Я провел небольшое исследование и обнаружил, что вы не можете изменить размер объекта формы за пределами ширины вашего монитора. Есть ли какой-нибудь обходной путь для этого? У меня уже есть он внутри панели с автопрокруткой.

Код не слишком релевантен но вот он:
public List<List<bool>> matrix = new List<List<bool>>();

public void ExpandWindow()
{
	Size mySize = new Size(matrix.Count * CellWidth, matrix[0].Count * RowHeight);
	MaximumSize = mySize;
	this.Size = mySize;
	Invalidate();
	MessageBox.Show("Timeline Width: " + matrix.Count + "\r\nLogical Width: " + (mySize.Width / CellWidth) + "\r\nPhysical Width: " + (Width / CellWidth));
}


Вывод окна debug messagebox выглядит следующим образом
Timeline Width: 4615
Logical Width: 4615
Physical Width: 1260


ширина временной шкалы - это ширина матрицы, логическая ширина-это то, что выводит вычисление, а физическая ширина-это то, как долго он на самом деле был установлен.

Матрица заполняется в другом месте кода

Что я уже пробовал:

Я попытался переопределить функцию SetBoundsCore, но это просто помешало элементу управления вообще изменить размер.

Graeme_Grant

вы пробовали использовать поиск Google? прокручиваемая панель winform-поиск Google[^]

Sicppy

У меня уже есть прокручиваемая панель, я просто не могу получить элемент внутри панели дольше 1260

Graeme_Grant

Я думаю, что вы не смотрели на ссылку, которую я предоставил... Вот ответ StackOverflow, который объясняет, как делать то, что вы хотите: https://stackoverflow.com/a/4306333 (из результатов поиска Google search, приведенных выше).

BillWoodruff

Это приложение Windows Form ? Если это так, то есть простой способ достичь того, чего вы хотите.

Sicppy

Да,это приложение windows forms.

BillWoodruff

Планируете ли вы самостоятельно нарисовать содержимое временной шкалы с помощью "Paint" или собираетесь отобразить элементы управления WinForm для создания временной шкалы ?

Sicppy

Я рисую содержимое с помощью события paint

BillWoodruff

в этом случае я бы рассмотрел возможность использования двойного буферизованного пользовательского элемента управления для рисования, а не Панели. если бы я делал игру, я бы использовал Unity или DirectX, которые очень хорошо настроены для сложного рендеринга. твое здоровье, Билл

Sicppy

Я вроде как отказался от этого вопроса, ха-ха, но на самом деле я делал игру не в winforms, а в unity, но это была ритмическая игра, я сделал отдельную программу в winforms, чтобы попытаться сделать своего рода планировщик, который приурочил события к музыке, в конце концов я просто использовал Vixen-программу, используемую для синхронизации рождественских огней с музыкой, и экспортировал проекты в необработанный текстовый формат и анализировал их в своей игре в unity.

2 Ответов

Рейтинг:
1

BillWoodruff

Я думаю, что здесь должно быть что-то простое, чего вам не хватает.

Хотя абсолютный номинальный размер выигрышной формы может быть ограничен, Вы можете иметь практически неограниченную виртуальную поверхность с помощью прокрутки. Пример:

private void Form1_Load(object sender, EventArgs e)
{
    Panel pnl = new Panel();

    pnl.AutoSize = false;
    pnl.Dock = DockStyle.None;
    pnl.Anchor = AnchorStyles.None;
    
    pnl.AutoScroll = true;
       
    pnl.Size = new Size(10000, this.Height);

    pnl.BackColor = Color.AliceBlue;

    this.Controls.Add(pnl);

    pnl.Left = 0;
    pnl.Top = 0;

    Console.Write($"Form Bounds: {this.Bounds}\r\nPanel Bounds: {pnl.Bounds}");
}
Вывод на консоль после запуска этого:

Границы Формы: {X=336, Y=336, Ширина=1274,Высота=1527}
Границы Панели: {X=0, Y=0, Ширина=10000,Высота=1527}

Дайте мне знать, если этот пример вам не поможет.


Рейтинг:
1

Graeme_Grant

Проблема с решением 1 заключается в потреблении памяти. Вы лучше виртуализируете и визуализируете только ту часть, которую увидит пользователь. Это значительно улучшит общую производительность и значительно сократит использование памяти. Таким образом, ваша панель может иметь ширину более 1 миллиона пикселей!

Вот вам пример. Он имеет один PictureBox и одну горизонтальную полосу прокрутки.

Дизайнер:

partial class Form1
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;

/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
    if (disposing && (components != null))
    {
        components.Dispose();
    }
    base.Dispose(disposing);
}

#region Windows Form Designer generated code

/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
    this.pictureBox1 = new System.Windows.Forms.PictureBox();
    this.hScrollBar1 = new System.Windows.Forms.HScrollBar();
    ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).BeginInit();
    this.SuspendLayout();
    // 
    // pictureBox1
    // 
    this.pictureBox1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 
    | System.Windows.Forms.AnchorStyles.Left) 
    | System.Windows.Forms.AnchorStyles.Right)));
    this.pictureBox1.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
    this.pictureBox1.Location = new System.Drawing.Point(13, 13);
    this.pictureBox1.Name = "pictureBox1";
    this.pictureBox1.Size = new System.Drawing.Size(259, 216);
    this.pictureBox1.TabIndex = 0;
    this.pictureBox1.TabStop = false;
    this.pictureBox1.Paint += new System.Windows.Forms.PaintEventHandler(this.PictureBox1_Paint);
    this.pictureBox1.Resize += new System.EventHandler(this.PictureBox1_Resize);
    // 
    // hScrollBar1
    // 
    this.hScrollBar1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left) 
    | System.Windows.Forms.AnchorStyles.Right)));
    this.hScrollBar1.Location = new System.Drawing.Point(13, 232);
    this.hScrollBar1.Maximum = 5000;
    this.hScrollBar1.Name = "hScrollBar1";
    this.hScrollBar1.Size = new System.Drawing.Size(259, 20);
    this.hScrollBar1.TabIndex = 1;
    this.hScrollBar1.ValueChanged += new System.EventHandler(this.HScrollBar1_ValueChanged);
    // 
    // Form1
    // 
    this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
    this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
    this.BackColor = System.Drawing.Color.White;
    this.ClientSize = new System.Drawing.Size(284, 261);
    this.Controls.Add(this.hScrollBar1);
    this.Controls.Add(this.pictureBox1);
    this.Name = "Form1";
    this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
    this.Text = "Form1";
    ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).EndInit();
    this.ResumeLayout(false);

}

#endregion

private System.Windows.Forms.PictureBox pictureBox1;
private System.Windows.Forms.HScrollBar hScrollBar1;
}

с фоновым кодом:
public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();

        canvasWidth = 1000000 * (elementWidth + elementGap);
        CalcSize();
    }

    private readonly int elementWidth = 60;
    private readonly int elementGap = 10;

    private readonly Font font = new Font("Arial", 14);

    private int displayWidth;

    private int canvasWidth;
    private int offset = -1;

    private void PictureBox1_Paint(object sender, PaintEventArgs e)
    {
        // nothing to do!
        if (offset == hScrollBar1.Value) return;
        offset = hScrollBar1.Value;

        var gr = e.Graphics;

        // Set text rendering mode
        gr.TextRenderingHint = TextRenderingHint.AntiAlias;

        // Calculate cell positioning
        var step = elementWidth + elementGap;
        var count = (hScrollBar1.Value / step) + 1;

        using (var br = new SolidBrush(Color.Red))
        {
            for (int i = 0; i < displayWidth; i += step)
            {
                gr.DrawString(count.ToString(), font, br, i, 50);
                count++;
            }
        }
    }

    private void HScrollBar1_ValueChanged(object sender, EventArgs e)
    {
        pictureBox1.Invalidate();
    }

    private void PictureBox1_Resize(object sender, EventArgs e)
    {
        CalcSize();
    }

    private void CalcSize()
    {
        displayWidth = pictureBox1.Width;

        var max = canvasWidth - pictureBox1.Width;
        hScrollBar1.Maximum = max;
        if (hScrollBar1.Value > max) hScrollBar1.Value = max;

        hScrollBar1.LargeChange = displayWidth;
        hScrollBar1.SmallChange = elementWidth + elementGap;
    }
}