Adding dynamic controls to form with auto scroll - c#

When I add my controls to the form, it goes fine until I try to specify a location larger than int16.MaxValue. The controls just pile up on top of each other. Here is code which is simplified but demonstrates the behavior:
private void Form1_Load(object sender, EventArgs e)
{
this.AutoScroll = true;
int nexttop = 0;
for (int i = 0; i < 500; i++)
{
TextBox t = new TextBox();
t.Text = i.ToString();
t.Multiline = true;
if (nexttop > Int16.MaxValue)
{
bool debug = true;
}
t.Location = new Point(0, nexttop);
t.Size = new Size(100, 77);
nexttop += t.Height;
this.Controls.Add(t);
}
}
I want to avoid moving the scroll bar programaticaly, since this causes timing issues.
Do you have any ideas on how to fix this? TIA.

This limit (32767) is due to GDI+. I believe different behaviours may be observed according to the Windows version.

Related

Creating an array of pictureboxes in windows form (C#)

I'm trying to create an array/list of picturebox objects that are declared and added to the form on button click (Meaning that I'm not creating multiple objects with my array, but plan to if I can get this to run). Not getting errors, but the pictureboxes themselves do not appear on the form.
private void spawn_Click(object sender, EventArgs e)
{
var pictureTest[0] = new PictureBox();
pictureTest[0].Image = Properties.Resources.testimage;
pictureTest[0].Location = new Point(500, 250);
pictureTest[0].Name = "spawn1";
pictureTest[0].Size = new Size(50, 50);
pictureTest[0].TabIndex = 98;
pictureTest[0].TabStop = false;
this.Controls.Add(pictureTest[0]);
}
Through the course of my research, I've mainly just gotten the advice to use this.Controls.Add, but that doesn't seem to be my issue here. My array is declared earlier with:
PictureBox[] pictureTest = new pictureTest[100];
As #HansPassant says in the comments, this code doesn't compile. The following should broadly do what you want:
int _position = 10;
private void spawn_Click(object sender, EventArgs e)
{
var pictureTest = new PictureBox();
pictureTest.Image = Properties.Resources.testimage;
pictureTest.Location = new Point(_position, 250);
pictureTest.Name = "spawn1";
pictureTest.Size = new Size(50, 50);
pictureTest.TabIndex = 98;
pictureTest.TabStop = false;
this.Controls.Add(pictureTest);
_position += 100;
}
Firstly, there's no need to maintain a separate array of PictureBox, as they are part of your form. Secondly, as #HansPassant said - you were overlaying the images directly on top of each other, so you couldn't tell if you had 1 or 1000.

Auto arrange unlimited number of buttons on form

I'm trying generate dynamically a bunch of buttons. The number of buttons is determined by how many pits are alive, and this is retrieved from a database.
Here is how it looks like :
Here is what I used to generate them :
private void Form1_Load(object sender, EventArgs e)
{
int numOf = pits.numOfPits();
Button[] genButtons = new Button[numOf];
int l = 1;
for (int i = 0; i < numOf; i++)
{
genButtons[i] = new Button();
genButtons[i].Width = 160;
genButtons[i].Height = 80;
Point location = new Point((i + 1) *200,75);
if (location.X > this.ClientSize.Width - 200)
{
location.X = l * 200;
location.Y += 100;
l++;
}
genButtons[i].Location = location;
this.Controls.Add(genButtons[i]);
}
}
The problem is that it will only work for 2 rows and it is kind of hard coded. How can I improve it to support an unlimited number of buttons.
You can ignore the limited "height" of form for the purpose of this question. I'll probably add some pagination later.
Add button controls to the FlowLayoutPanel. Extend the FlowLayoutPanel to include items per page, current page, and data to implement paging.
private void Form1_Load(object sender, EventArgs e)
{
FlowLayoutPanel flp = new FlowLayoutPanel();
for (int i = 0; i < pits.numOfPits(); ++i)
{
Button btn = new Button();
btn.Width = 160;
btn..Height = 80; //set padding or margin to appropriate values
flp.Controls.Add(btn);
}
this.Controls.Add(flp);
}

Make Panel scrollable

I am working on a simple Windows Forms application which consists of a Panel where I draw graphics with Graphic. Let's say, my panel is now of size 300x300 but the content inside is 500x500. Obviously, I need to add scrollbars to the Panel.
My code so far:
public CircuitControl()
{
// Initialize empty list of circuit objects
CircuitObjects = new List<CircuitObject>();
drawingAreaPanel.AutoScroll = true;
drawingAreaPanel.VerticalScroll.Enabled = true;
drawingAreaPanel.VerticalScroll.Visible = true;
drawingAreaPanel.HorizontalScroll.Enabled = true;
drawingAreaPanel.MaximumSize = new Size(300, 300);
drawingAreaPanel.Size = new Size(600, 600);
}
But none of these codes create actually a scroll bar. My question is: Where and how do I set the size of the Panel where I actually drew? I think this is the part which is missing. Thanks.
The scrollbars won't show up until there's actually something in the Panel that you can't see all of.
Try placing a larger control, such as a PictureBox, inside the Panel, and setting the PictureBox's initial size as larger than the Panel.
Just add:
drawingAreaPanel.AutoScroll = true;
And it will be done automatically.
€dit: Don't forget to set the anchors in order to get the scrollbars.
A clean and simple approach is to set AutoScrollMinSize. This shows the scrollbars (or just one if you leave the other value at 0).
Now drawing through the graphics object will not be scrolled automatically.
This can be easily achieved with a transformation matrix, which is set before painting and translates the drawing by the scroll offset.
A pretty example: (this flickers of course without further optimizations)
private void button1_Click(object sender, EventArgs e)
{
using(Form frm = new Form())
{
Panel pnl = new Panel();
pnl.Paint += delegate (Object snd, PaintEventArgs e2) {
Matrix mtx = new Matrix();
mtx.Translate(pnl.AutoScrollPosition.X, pnl.AutoScrollPosition.Y);
e2.Graphics.Transform = mtx;
e2.Graphics.Clear(Color.Black);
for(int i=0; i <= 125; i++)
for(int j=0; j <= 125; j++)
using(Brush b = new SolidBrush(Color.FromArgb(255, 255-i*2, j*2, (i*j) % 255)))
e2.Graphics.FillRectangle(b, new Rectangle(5+j*20, 5+i*20, 20, 20));
};
pnl.AutoScrollMinSize = new Size(126*20+10, 126*20+10);
pnl.Dock = DockStyle.Fill;
frm.Controls.Add(pnl);
frm.Padding = new Padding(25);
frm.ShowDialog(this);
}
}

Creating dynamic comboboxes on a dynamic panel

I am trying to create 4 comboboxes on a dynamically created panel but nothing is showing. What am I missing here, this is my code:
public partial class Form1 : Form
{
ComboBox[] cmb;
public Form1()
{
InitializeComponent();
}
Panel pnl;
private void Form1_Load(object sender, EventArgs e)
{
panel();
createCombo();
}
private void panel()
{
pnl= new Panel();
pnl.Location = new Point(10, 10);
pnl.BorderStyle = BorderStyle.FixedSingle;
pnl.Size = new Size(200, 150);
this.Controls.Add(pnl);
createCombo();
}
private void createCombo()
{
for (int i = 0; i <= 3; ++i)
{
cmb[i] = new ComboBox();
cmb[i].Text = "CodeCall!";
cmb[i].Size = new Size(90, 00);
cmb[i].Location = new Point(i+5, 0);
pnl.Controls.Add(cmb[i]);
}
}
}
Interface shows only the panel:
I initially thought the problem was the height:
cmb[i].Size = new Size(90, 00);
However, it turns out you actually cannot set the height for a ComboBox.
The real problem is a NullReferenceException that is getting swallowed (you must be on a 64-bit system). You never initialize cmb and thus it is null when cmb[i] = new ComboBox() is called.
See http://blog.adamjcooper.com/2011/05/why-is-my-exception-being-swallowed-in.html for an explanation as to why this happens but the conditions that must be met are (quoting):
You are running on a 64-bit version of Windows (whether your application is built for 32-bit or 64-bit doesn’t matter; only the bit depth of the OS)
You are building a WinForms app
You are debugging the application with Visual Studio (using default options for Exception catching)
Your main form has a Load event handler
During the execution of your Load handler, an exception occurs
Tested and the code works fine, provided you're not getting a null reference exception. You need to instantiate your array:
private void createCombo()
{
cmb = new ComboBox[5];
for (int i = 0; i <= 3; ++i)
{
cmb[i] = new ComboBox();
cmb[i].Text = "CodeCall!";
cmb[i].Size = new Size(90, 00);
cmb[i].Location = new Point(i+5, 0);
pnl.Controls.Add(cmb[i]);
}
}
For me, the combobox appeared without issue. However they all appear almost on top of eachother, you'll need to set cmb[i].Location differently. Also, I personally would recommend this instead of what you are doing:
private void createCombo()
{
cmb = new ComboBox[5];
int width = 90;
int height = 25;
int spacing = 5;
for (int i = 0; i <= 3; ++i)
{
ComboBox newBox = new ComboBox();
newBox.Text = "CodeCall!";
newBox.Size = new Size(width, height);
newBox.Location = new Point((i*width)+spacing, 0);
cmb[i] = newBox;
pnl.Controls.Add(newBox);
}
}
The problem is the height:
cmb[i].Size = new Size(90, 00);
Answer doesn't include exact answer.
The problem is that you have a 0 for height. Try for example:
cmb[i].Size = new Size(90, 90);

How to enable auto scroll?

I have a feeling that Im am missing something obvious but:
I have a single row of pictures in a form, in theory the pictures could go on forever. I need a scroll bar so that the user can look at all of the pictures in the row. I know I need to enable auto scroll but I have no idea how to enable it. Can someone tell me how to enable it or something that I am missing?
If it helps this is the code i am using to generate the pictures:
private void imagePalletToolStripMenuItem_Click(object sender, EventArgs e)
{
MyPalletGui.Show();
Dictionary<string,Bitmap> MyPallet = MyImageCollection.ToDictionary();
int xcor = -50;
int ycor = 0;
foreach (Bitmap curtImage in MyPallet.Values){
PictureBox myPicBox = new PictureBox();
xcor += 50;
myPicBox.Location = new Point(xcor, ycor);
myPicBox.Width = 50;
myPicBox.Height = 50;
myPicBox.Visible = true;
myPicBox.Image = new Bitmap(curtImage);
this.MyPalletGui.Controls.Add(myPicBox);
This code will do exactly what you want, it uses the Form as the ViewPort with AutoScroll:
public Form1()
{
InitializeComponent();
PopulatePictures();
}
private void PopulatePictures()
{
this.AutoScroll = true;
string[] list = Directory.GetFiles(#"C:\\Users\\Public\\Pictures\\Sample Pictures", "*.jpg");
PictureBox[] picturebox= new PictureBox[list.Length];
int y = 100;
for (int index = 0; index < picturebox.Length; index++)
{
picturebox[index] = new PictureBox();
this.Controls.Add(picturebox[index]);
picturebox[index].Location=new Point(index * 120, y);
if(x%12 == 0)
y = y + 150;
picturebox[index].Size = new Size(100,120);
picturebox[index].Image = Image.FromFile(list[index]);
}
}

Categories

Resources