The problem with solution 1 is the memory consumption. You are better of virtualizing and rendering only the part that the user will see. This will greatly improve overall performance and dramatically reduce memory usage. This way your panel can be over 1 million pixels wide!
Here is an example. It has one PictureBox and one horizontal Scrollbar.
Designer:
partial class Form1
{
private System.ComponentModel.IContainer components = null;
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
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();
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);
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);
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;
}
Code-Behind:
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)
{
if (offset == hScrollBar1.Value) return;
offset = hScrollBar1.Value;
var gr = e.Graphics;
gr.TextRenderingHint = TextRenderingHint.AntiAlias;
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;
}
}