creating a tablelayoutpanel of pictureboxes takes a long time - c#

I'm creating this tablelayoutpanel of picture boxes (66x66 pixels) and while on one PC it is taking less then a second to finish, it takes about 8 seconds on another pc (with the same capabilities...).
I have to create the graphics on run time as I know only on run time which images I need to place.
This is the function:
private void InitializeDrawerCells(int cabinetPartID, int drawerID)
{
PictureBox pb;
try
{
tblDrawerCells.RowStyles.Clear();
tblDrawerCells.ColumnStyles.Clear();
tblDrawerCells.Controls.Clear();
tblDrawerCells.RowCount = 12;
tblDrawerCells.ColumnCount = 16;
for (int i = 0; i < tblDrawerCells.RowCount; i++)
{
RowStyle style = new RowStyle
{
SizeType = SizeType.Absolute,
Height = tblDrawerCells.Height / tblDrawerCells.RowCount
};
tblDrawerCells.RowStyles.Add(style);
}
for (int i = 0; i < tblDrawerCells.ColumnCount; i++)
{
ColumnStyle style = new ColumnStyle
{
SizeType = SizeType.Absolute,
Width = tblDrawerCells.Width / tblDrawerCells.ColumnCount
};
tblDrawerCells.ColumnStyles.Add(style);
}
for (int i = 0; i < tblDrawerCells.ColumnCount; i++)
{
for (int j = 0; j < tblDrawerCells.RowCount; j++)
{
pb = new PictureBox();
if (_DrawerType == eDrawerType.Regular)
{
if (Scenraio == OpenCabinetScenario.Maintenance)
{
if (NarcoticsCabinetManager.CabinetParts[_CurrentCabPartID].Drawers[_DrawerNumber - 1].DrawerType == eDrawerType.Regular)
pb.BackgroundImage = ImageOn[tblDrawerCells.RowCount - j - 1][i];
else
pb.BackgroundImage = ImageReturnOff;
}
else
pb.BackgroundImage = ImageOff;
}
else
pb.BackgroundImage = global::NarcoticsStorageSystem2.Properties.Resources._11x6_Cells;
pb.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Center;
// pb.Dock = System.Windows.Forms.DockStyle.Fill;
pb.Location = new System.Drawing.Point(0, 0);
pb.Margin = new System.Windows.Forms.Padding(0, 0, 0, 0);
if (_DrawerType == eDrawerType.Regular)
pb.Size = new System.Drawing.Size(66, 66);
else if (_DrawerType == eDrawerType.Return)
pb.Size = new System.Drawing.Size(198, 66);
// if (_Scenraio == OpenCabinetScenario.FillItems)
// {
pb.Click += new System.EventHandler(this.pbCell_Click);
// }
pb.TabStop = false;
pb.Tag = new Tuple<int, int, int, int>(_DrawerNumber, tblDrawerCells.RowCount - j, i + 1, (int)ImageType.Off);
tblDrawerCells.Controls.Add(pb, i, j);
}
}
}
catch (Exception ex)
{
//add ex to log...
}
finally
{
}
}
Any ideas?

Related

Dynamically update button

I am attempting to dynamically add a list of buttons:
private void updateClientListUI()
{
if (this.InvokeRequired)
{
this.Invoke(new MethodInvoker(this.updateClientListUI));
}
else
{
int count = 1;
int x = 0;
int y = 0;
for (int i = 0; i < 5; i++)
{
Button btn = new Button();
btn.Text = count.ToString();
btn.Name = count.ToString();
btn.Size = new Size(35, 35);
btn.Location = new Point(150, 150 * y);
//btn.Dock = DockStyle.Fill;
y++;
count++;
Controls.Add(btn);
}
}
}
Unfortunately this does not apply any buttons to the form.
In addition I was wondering how could I append these buttons in a panel called subPanelClient
This worked for me, the issue was the position of the button, as you have to indicate it within a panel or form.
In this case i just docked them to the panel
private void updateClientListUI()
{
if (this.InvokeRequired)
{
this.Invoke(new MethodInvoker(this.updateClientListUI));
}
else
{
//Debug.WriteLine(clientNames[0]);
int basex = subPanelClient.Location.X;
int basey = subPanelClient.Location.Y;
subPanelClient.Controls.Clear();
Debug.WriteLine(clientNames.Count);
for (int i = 0; i < clientNames.Count; i++)
{
Button b = new Button();
b.Left = basex;
b.Top = basey;
b.Size = new Size(25, 25); // <== add this line
b.Dock = DockStyle.Top;
b.ForeColor = Color.Gainsboro;
b.FlatStyle = FlatStyle.Flat;
b.FlatAppearance.BorderSize = 0;
b.Padding = new Padding(35, 0, 0, 0);
b.TextAlign = ContentAlignment.MiddleLeft;
basey += 25;
b.Name = clientNames[i];
b.Text = clientNames[i];
subPanelClient.Controls.Add(b);
buttonsAdded.Insert(i, b);
}
}
}

How to create an array with pictureboxes in Windows Forms (C#)

I am fairly new to C# and I can't figure out how to create an array with visible picture boxes inside the cs file. In this example I want to create 200 picture boxes 10x20 to create an grid for a tetris game. This is my code, I can't get any of the pictures to show but the code runs just fine.
Image[] blockImage = {
TetrisSlutprojekt.Properties.Resources.TileEmpty,
TetrisSlutprojekt.Properties.Resources.TileCyan,
TetrisSlutprojekt.Properties.Resources.TileBlue,
TetrisSlutprojekt.Properties.Resources.TileRed,
TetrisSlutprojekt.Properties.Resources.TileGreen,
TetrisSlutprojekt.Properties.Resources.TileOrange,
TetrisSlutprojekt.Properties.Resources.TilePurple,
TetrisSlutprojekt.Properties.Resources.TileYellow
};
PictureBox[] blockBoxes = new PictureBox[200];
private void CreateBoxes()
{
for (int i = 0; i < blockBoxes.Length; i++)
{
blockBoxes[i] = new System.Windows.Forms.PictureBox();
blockBoxes[i].Name = "pbBox" + i;
blockBoxes[i].Size = new Size(30, 30);
blockBoxes[i].Visible = true;
}
}
private void PlaceBoxes()
{
for (int y = 0; y < rows; y++)
{
for (int x = 0; x < columns; x++)
{
blockBoxes[y].Top = y * blockWidth;
blockBoxes[x].Left = x * blockWidth;
}
}
}
private void FillBoxes()
{
for (int i = 0; i < blockBoxes.Length; i++)
{
blockBoxes[i].Image = blockImage[4];
}
}
Add them to the Form:
private void CreateBoxes()
{
for (int i = 0; i < blockBoxes.Length; i++)
{
blockBoxes[i] = new System.Windows.Forms.PictureBox();
blockBoxes[i].Name = "pbBox" + i;
blockBoxes[i].Size = new Size(30, 30);
blockBoxes[i].Visible = true;
this.Controls.Add(blockBoxes[i]); // <--- HERE
}
}

How to delete image created with code and how to interact with it at all

I am working on a game. For this game i create around 200 images in a box 20x10.
My problem is that pressing 1 button creates them a lot of times which garbages the Memory, which i want to avoid. So i created a little if/else function which is supposed to check wether the images were created or not. In case they weren't, code creates them, but if they were, the code should delete them, and i have no idea how to delete code generated images or how to interract with them at all.
public void GameStart(bool load = false)
{
Random rnd = new Random();
Pause.IsEnabled = true;
Save.IsEnabled = true;
Shuffle.IsEnabled = true;
byte datasave = 0;
int[,] TileID = new int[20,10];
for(int i = 0; i < 20; i++)
{
for(int j = 0; j < 10; j++)
{
if(TileID[i,j] != 0)
{
datasave = 1;
}
TileID[i, j] = rnd.Next(1,9);
CreateImage(i, j, TileID[i,j], datasave);
}
}
}
public void CreateImage(int a, int b, int TileID, byte datainfo)
{
if(datainfo != 0)
{
Image image = new Image();
image.Width = 40;
image.Height = 40;
image.Name = $"Tile{a}{b}";
image.HorizontalAlignment = System.Windows.HorizontalAlignment.Center;
image.VerticalAlignment = System.Windows.VerticalAlignment.Center;
image.Margin = new Thickness(-1000 + 80 * a, -200 + 80 * b, 0, 0);
string way = #"C:\Users\ignat\Desktop\Игра\Images\";
image.Source = new BitmapImage(new Uri(way + $"icon{TileID}.jpg", UriKind.Absolute));
Grid.Children.Add(image);
}
else
{
CreateImage(a, b, TileID, datainfo);
}

C# - How can I create 2 separate button arrays with different controls without them causing problems with the other?

I am currently trying to develop a form of battleships on c# windows form.
Here is the code I am trying to use.. the trouble I have been having is how to create a second set of buttons (another 10x10) behind the other, with two sets of controls so I can switch between the two.
I have everything like AI and automated setups, I just need to have 2 button controls. I hope someone can help me out with this! Many thanks!
private List<List<Button>> grid = new List<List<Button>>();
public UserForm()
{
InitializeComponent();
byte numRows = 10;
byte numCols = 10;
for (byte i = 0; i < numRows; i++)
{
grid.Add(ButtonRowCreator(numCols, 25, (i+1) * 50));
}
}
public List<Button> ButtonRowCreator(byte numOfBtnsNeeded, int x, int y)
{
List<Button> btns = new List<Button>();
for (int i = 0; i < numOfBtnsNeeded; i++)
{
Button btn = new Button();
btn.Size = new Size(50, 50);
btn.Location = new Point(x + (i * btn.Width), y);
btns.Add(btn);
btn.Font = new Font("Georiga", 10);
this.Controls.Add(btn);
btn.Click += new EventHandler(btn_Click);
}
return btns;
}
void btn_Click(object sender, EventArgs e)
{
Button btn = (Button)sender;
int curRow = -1, curCol = -1;
for(int i = 0; i < grid.Count; i++)
{
int index = grid[i].IndexOf(btn);
if (index != -1)
{
curRow = i;
curCol = index;
Console.WriteLine("curRow = " + curRow.ToString() + ", curCol = " + curCol.ToString());
}
}
// ... now you can use "curRow", "curCol" and "grid" to do something ...
foreach (List<Button> row in grid)
{
foreach (Button col in row)
{
col.ForeColor = Color.Gray;
}
}
if (board[curRow, curCol] == 1)
{
if (btn.Text == "Hit")
{
}
else
{
btn.Text = "Hit";
btn.BackColor = Color.Red;
hit++;
}
if (hit == 17)
{
MessageBox.Show("Congratulations, You Sunk Their Battleships!");
MessageBox.Show("Thanks For Playing!");
MessageBox.Show("Goodbye!");
}
}
else
{
btn.Text = "Miss!";
btn.BackColor = Color.Blue;
}
I think this is what you're after?
It looks like a lot of your code is used to figure out what button is clicked on. This information can be stored on the button object itself in the Tag property and greatly simplifies the code.
private Button[,] _grid1;
private Button[,] _grid2;
public UserForm()
{
InitializeComponent();
_grid1 = new Button[10, 10];
_grid2 = new Button[10, 10];
CreateGrid(_grid1, 10, 10, 25, 0, 20, true);
CreateGrid(_grid2, 10, 10, 25, 250, 20, false);
}
public void CreateGrid(Button[,] grid, int numOfRows, int numOfCols, int offsetX, int offsetY, int buttonSize, bool enabled)
{
for (byte i = 0; i < numOfRows; i++)
{
for (byte j = 0; j < numOfCols; j++)
{
grid[i,j] = ButtonCreator(i, j, offsetX, offsetY, buttonSize, enabled);
}
}
}
public Button ButtonCreator(int row, int col, int x, int y, int buttonSize, bool enabled)
{
Button btn = new Button();
btn.Size = new Size(buttonSize, buttonSize);
btn.Location = new Point(x + (col * buttonSize), y + (row * buttonSize));
btn.Font = new Font("Georiga", 10);
this.Controls.Add(btn);
btn.Click += new EventHandler(btn_Click);
btn.Tag = row + "," + col;
btn.Enabled = enabled;
return btn;
}
void btn_Click(object sender, EventArgs e)
{
Button btn = (Button)sender;
string[] coord = btn.Tag.ToString().Split(',');
int curRow = Convert.ToInt32(coord[0]);
int curCol = Convert.ToInt32(coord[1]);
Console.WriteLine(curRow = " + curRow + ", curCol = " + curCol);
// ... now you can use "curRow", "curCol" to do something ...
_grid1[curRow, curCol].BackColor = Color.Red;
}

Grid.Add.Children(UIElement) returns Parameter is incorrect exception

I am trying to add border in two pivot items.
When my border is added to grid in pivot item for the first time everything is working fine. But when i try to add border second time in same pivot item it throws an exception "The parameter is incorrect"
here is my code :
private void pivot_item1Loaded()
{
WebClient webClient2011 = new WebClient();
string Url2011 = "http://hostname/Details/Images?year=2011" + "&time=" + System.DateTime.UtcNow;
webClient2011.OpenReadAsync(new Uri(Url2011));
webClient2011.OpenReadCompleted += new OpenReadCompletedEventHandler(webClient_OpenReadCompleted2011);
}
private void pivot_item2Loaded()
{
WebClient webClient2012 = new WebClient();
string Url2012 = "http://hostname/Details/Images?year=2012" +"&time="+ System.DateTime.UtcNow;
webClient2012.OpenReadAsync(new Uri(Url2012));
webClient2012.OpenReadCompleted += new OpenReadCompletedEventHandler(webClient_OpenReadCompleted2012);
}
public void webClient_OpenReadCompleted2011(object sender, OpenReadCompletedEventArgs e)
{
StringBuilder output = new StringBuilder();
try
{
using (XmlReader reader = XmlReader.Create(e.Result))
{
while (reader.Read())
{
if (reader.NodeType == XmlNodeType.Element)
{
if (reader.Name == "iconPath")
{
string iconPath = reader.ReadElementContentAsString();
iconImages2011.Add(iconPath);
}
if (reader.Name == "imagePath")
{
string imagePath = reader.ReadElementContentAsString();
fullScreenImages2011.Add(imagePath);
}
}
}
}
int numOfRows = (iconImages2011.Count) / 3 + 1;
for (int j = 0; j < numOfRows; j++)
{
//pivot_item1
ContentPanel2011.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(150) });
}
int rowCount = 0;
int columnCount = 0;
for (int i = 0; i < iconImages2011.Count; i++)
{
Border border2011 = new Border();
border2011.Background = new SolidColorBrush(Colors.Blue);
border2011.Height = 110;
border2011.Width = 110;
border2011.CornerRadius = new CornerRadius(10);
Canvas canvas2011 = new Canvas();
canvas2011.Height = 110;
canvas2011.Width = 110;
BitmapImage AppImage = new BitmapImage(new Uri(iconImages2011[i], UriKind.Absolute));
Image img = new Image();
img.Source = AppImage;
img.Width = 90;
img.Height = 90;
img.Stretch = Stretch.Fill;
img.Margin = new Thickness(10, 10, 10, 10);
canvas2011.Children.Add(img);
border2011.Child = canvas2011;
border2011.Name = i.ToString();
Grid.SetColumn(border2011, columnCount);
Grid.SetRow(border2011, rowCount);
ContentPanel2011.Children.Add(border2011);
pivot2011.Content = ContentPanel2011;
if (columnCount < 2)
{
columnCount++;
}
else if (columnCount == 2)
{
columnCount = 0;
rowCount++;
}
}
}
catch (Exception x)
{
MessageBox.Show(x.Message);
}
}
This code works for the first time but gives exception after that and ContentPanel2011 viz pivot_item1 do not get filled with border2011
It is done.
just set content property on pivots to null before before setting the content again.
I have just added:
pivot2011.Content = null;
pivot2012.Content = null;
in pivot_item1Loaded() and pivot_item2Loaded()
and it is working fine.

Categories