Dynamic GroupBoxes always align to top - c#

I have this application where several groupboxes are in a vertical line. They can be enabled and disabled individually. I want to always align the groupboxes to the top, no matter if the ones normally being in between to is enabled or not.
Say we have three groupboxes (1, 2, 3). The middle one (2) gets disabled. Normally the two other boxes (1,3) locations wont be affected by this. But I want the last groupbox (3) to then take the place that the middle groupbox (2) would normally be in.
Any ideas how to accomplish this the most simple way?
This is what im doing at the moment which isnt good enough for scaling
if (isForgeIncluded == "True" | isForgeIncluded == "true")
{
forgeBox.Visible = true;
if (headerPic == "False" | headerPic == "false")
{
PictureBox1.Visible = false;
forgeBox.Location = new Point(6, 5);
pathBox.Location = new Point(6, 112);
}
else
{
}
}
else
{
forgeBox.Visible = false;
if (headerPic == "False" | headerPic == "false")
{
PictureBox1.Visible = false;
pathBox.Location = new Point(6, 5);
}
else
{
pathBox.Location = new Point(6, 168);
}
}

set groupbox2 location(x,y) to groupbox3 location(x,y) while your groupbox2 disables - might be from a specific event.

I managed to figure out a solution to this, which is "more dynamic" but not 100% dynamic, as i will have to go add new GroupBoxes to an array manually. However, this does work, and takes care of the picturebox in the beginning
int nextBoxLocation = 0;
int boxHeightAdd = 0;
int spacing = 6;
if (headerPic == "True" | headerPic == "true")
{
PictureBox1.Visible = true;
nextBoxLocation = PictureBox1.Height + spacing;
}
if (isForgeIncluded == "True" | isForgeIncluded == "true")
{
forgeBox.Visible = true;
}
GroupBox[] boxes = {forgeBox , pathBox , typeBox};
foreach(GroupBox box in boxes)
{
if (box.Visible == true)
{
box.Location = new Point(6, nextBoxLocation);
boxHeightAdd = box.Height;
}
if (box.Name == "pathBox" && (minecraftPathVar == Environment.ExpandEnvironmentVariables("C:\\Users\\" + Environment.UserName + "\\AppData\\Roaming\\.minecraft")))
{
defRadioPath.Visible = false;
minecraftRadioPath.Visible = false;
box.Height = 75;
boxHeightAdd = 75;
}
nextBoxLocation += boxHeightAdd + spacing;
boxHeightAdd = 0;
}

Related

How to make two pictures not visible after a certain time

I'm making a memotest and I need to press two different images and they need to keep visible for 3-5 seconds. I've tried Thread.Sleep(5000) but it doesn't show me the second one. What should I do?
The only way I've founded to see for some seconds the images was by putting a MessageBox but that isn't the idea and I don't know other way to do it.
if (pic != null && pic.Name == fondos[i].Name)
{
if (CantClick == 0)
{
ParejaActual = listRandom[i].pareja;
CantClick = 1;
primerI = i;
picAnterior = pic;
imgAnterior = img;
pic.Visible = false;
}
else if (CantClick == 1)
{
pic.Visible = false;
if (ParejaActual == listRandom[i].pareja)
{
SoundPlayer simpleSound = (new SoundPlayer(Configuracion.RootFolder + "aplau.wav"));
simpleSound.Play();
Ganando++;
label3.Text = Ganando.ToString();
//MessageBox.Show("Si");
//NO SE DESTAPA LA SEGUNDA.
//Thread.Sleep(5000);
CantClick = 0;
img.Visible = false;
imgAnterior.Visible = false;
Application.DoEvents();
}
else
{
(new SoundPlayer(Configuracion.RootFolder + "sad.wav")).Play();
MessageBox.Show("No");
Mal++;
CantClick = 0;
label4.Text = Mal.ToString();
pic.Visible = true;
picAnterior.Visible = true;
}
}
}
Thank you!
Instead of using Thread.Sleep , use System.Timers class. After an interval, just hide one image and show the other. Tell me if you want any other help.

TableLayoutPanel is only able to find Controls by Point that were in the visible area on startup

I have a TableLayoutPanel with a scrollbar (because the total height of the Controls is bigger than the height of the TableLayoutPanel). I try to scroll programmatically to the next/previous row with the PageUp- and PageDown-Keys.
Scrolling works, but only as far as I want to scroll to a Control that was already in the visible area when the program started. When I try to get a Control further down (that has meanwhile entered the visible area), tlp.GetChildAtPoint(new Point(1, tlp.AutoScrollPosition.Y * -1 + 2)) returns null.
Can someone please help me to resolve this issue?
Note: I found a workaround (see my answer), but I am of course open to other solutions.
Code to reproduce the problem:
public class FormTLPTest : Form
{
TableLayoutPanel tlp;
public FormTLPTest()
{
Height = 200;
Width = 200;
KeyPreview = true;
tlp = new TableLayoutPanel();
tlp.Dock = DockStyle.Fill;
tlp.CellBorderStyle = TableLayoutPanelCellBorderStyle.Single;
tlp.AutoScroll = false;
tlp.VerticalScroll.Visible = true;
tlp.HorizontalScroll.Visible = false;
tlp.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 40));
Controls.Add(tlp);
tlp.SuspendLayout();
for (int i = 0; i < 20; i++)
{
Label lb2 = new Label();
lb2.Margin = new Padding(0);
lb2.Dock = DockStyle.Fill;
lb2.BackColor = Color.White;
lb2.Text = "Line " + i;
tlp.Controls.Add(lb2, 0, i);
tlp.RowStyles.Add(new RowStyle(SizeType.Absolute, 18));
tlp.RowCount++;
}
tlp.ResumeLayout();
tlp.AutoScroll = true;
KeyDown += FormTLPTest_KeyDown;
}
private void FormTLPTest_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.PageUp || e.KeyCode == Keys.PageDown || e.KeyCode == Keys.Next)
{
Control currentTopControl = tlp.GetChildAtPoint(new Point(1, tlp.AutoScrollPosition.Y * -1 + 2));
int currentRow = 0;
if (currentTopControl != null)
currentRow = tlp.GetPositionFromControl(currentTopControl).Row;
int nextRow = -1;
if (e.KeyCode == Keys.PageUp)
nextRow = currentRow - 1;
else
nextRow = currentRow + 1;
if (nextRow < 0 || nextRow > tlp.RowCount - 1)
return;
Control nextTopControl = tlp.GetControlFromPosition(0, nextRow);
tlp.AutoScrollPosition = nextTopControl.Location;
}
}
}
I found a solution avoiding the GetChildAtPoint-method. It checks the location of every control of the first column to get the first visible column.
I also had to replace .AutoScrollPosition = ... with a scroll to the last control and then to the desired control (I want the control to be at the top of the visible area).
changed KeyDown-listener:
private void FormTLPTest_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.PageUp || e.KeyCode == Keys.PageDown || e.KeyCode == Keys.Next)
{
int currentRow = 0;
for (int y=0;y<tlp.RowCount;y++)
{
Control c = tlp.GetControlFromPosition(0, y);
if (c.Location.Y >= 0)
{
currentRow = y;
break;
}
}
int nextRow = -1;
if (e.KeyCode == Keys.PageUp)
nextRow = currentRow - 1;
else
nextRow = currentRow + 1;
if (nextRow < 0 || nextRow > tlp.RowCount - 1)
return;
Control nextTopControl = tlp.GetControlFromPosition(0, nextRow);
tlp.ScrollControlIntoView(tlp.GetControlFromPosition(0, tlp.RowCount - 1));
tlp.ScrollControlIntoView(nextTopControl);
}
}

how to give a panel its exact size in c#?

I'm not an English user,so forgive me for grammatical problems please. Smile | :)
I have some paper forms that i want to print some labels on them.these papers have special size(24 cm * 14).so I made a panel(907 pixel * 529 pixel) and i put my labels on it(I converted cm to pixel and i put labels in the special parts of my panel).these labels are going to be printed in empty fields of my paper forms.but the problem is that, just the first form can be printed in the right style.others are printed in upper place of the form. I thought it may be because of I didn't give my panel and labels exact size in pixel. but i couldn't give my panel exact size in pixels,coz it doesn't accept pixels in decimal. any ideas?
this is a part of my code:
private void printDocument1_PrintPage(object sender, System.Drawing.Printing.PrintPageEventArgs e)
{
Pen blackPen = new Pen(Color.Black, 1);
e.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
e.Graphics.DrawLine(blackPen, 188, 400, 302, 400);
e.Graphics.DrawRectangle(blackPen, 330, 319, 122, 55);
e.Graphics.DrawString(label20.Text, label20.Font, new SolidBrush(label20.ForeColor), label20.Location);
e.Graphics.DrawString(label21.Text, label21.Font, new SolidBrush(label21.ForeColor), label21.Location);
e.Graphics.DrawString(label23.Text, label23.Font, new SolidBrush(label23.ForeColor), label23.Location);
e.Graphics.DrawString(label24.Text, label24.Font, new SolidBrush(label24.ForeColor), label24.Location);
e.Graphics.DrawString(label25.Text, label25.Font, new SolidBrush(label25.ForeColor), label25.Location);
e.Graphics.DrawString(label26.Text, label26.Font, new SolidBrush(label26.ForeColor), label26.Location);
e.Graphics.DrawString(label27.Text, label27.Font, new SolidBrush(label27.ForeColor), label27.Location);
e.Graphics.DrawString(lbl_kod.Text, lbl_kod.Font, new SolidBrush(lbl_kod.ForeColor), lbl_kod.Location);
e.Graphics.DrawString(lbl_ttarikh.Text, lbl_ttarikh.Font, new SolidBrush(lbl_ttarikh.ForeColor), lbl_ttarikh.Location);
e.Graphics.DrawString(lbl_ctot25.Text, lbl_ctot25.Font, new SolidBrush(lbl_ctot25.ForeColor), lbl_ctot25.Location);
e.Graphics.DrawString(lbl_pricetot25.Text, lbl_pricetot25.Font, new SolidBrush(lbl_pricetot25.ForeColor), lbl_pricetot25.Location);
e.Graphics.DrawString(lbl_pricetot.Text, lbl_pricetot.Font, new SolidBrush(lbl_pricetot.ForeColor), lbl_pricetot.Location);
e.Graphics.DrawString(lbl_pricetoth.Text, lbl_pricetoth.Font, new SolidBrush(lbl_pricetoth.ForeColor), lbl_pricetoth.Location);
e.Graphics.DrawString(lbl_name.Text, lbl_name.Font, new SolidBrush(lbl_name.ForeColor), lbl_name.Location);
e.Graphics.DrawString(lbl_dtarikh.Text, lbl_dtarikh.Font, new SolidBrush(lbl_dtarikh.ForeColor), lbl_dtarikh.Location);
}
and the print region for each paper form:
for (int i = 0; i < dataGridView1.RowCount && k < 3878; i++)
{
k = Convert.ToInt32(dataGridView1.Rows[i].Cells[0].Value);
bool found = false;
ctot25 = Convert.ToInt32(dataGridView1.Rows[i].Cells[13].Value);
ctot50 = Convert.ToInt32(dataGridView1.Rows[i].Cells[14].Value);
ctot100 = Convert.ToInt32(dataGridView1.Rows[i].Cells[15].Value);
foreach (object row1 in hoome)
if (row1.ToString() == (dataGridView1.Rows[i].Cells[0].Value).ToString())
{
found = true;
}
if (found == false)
{
if (i > 0 && ctot25 != 0 || ctot50 != 0 || ctot100 != 0)
{
#region tarikh
string date = dataGridView1.Rows[i].Cells[8].Value.ToString();
var aStringBuilder = new StringBuilder(date);
aStringBuilder.Insert(2, "/");
aStringBuilder.Insert(5, "/");
lbl_dtarikh.Text = aStringBuilder.ToString();
lbl_ttarikh.Text = datestringbuilder.ToString();
#endregion
decimal pricetot25;
pricetot25 = ctot25 * price25;
lbl_name.Text = (dataGridView1.Rows[i].Cells[1].Value).ToString();
lbl_kod.Text = (dataGridView1.Rows[i].Cells[0].Value).ToString();
lbl_ctot25.Text = (ctot25).ToString();
lbl_pricetot25.Text = (pricetot25).ToString();
lbl_pricetoth.Text = num2str(pricetot.ToString()) + " ریال" + "//";
#region print
System.Drawing.Printing.PrintDocument doc = new System.Drawing.Printing.PrintDocument();
doc.PrintPage += new System.Drawing.Printing.PrintPageEventHandler(printDocument1_PrintPage);
PrintDialog PrintSettings = new PrintDialog();
PrintSettings.Document = doc;
PageSettings pgsetting = new PageSettings();
doc.Print();
#endregion
}
}
}
here is a link to my screenshot:
my panel
Since your question is a little unclear, I think you better not to add your panel in design layout and create it programmatically. It'd be better if u take a screenshot of your second page.
EDIT:
Try creating labels in your FOR loop. You can drop panel in this way. I hope it works
if (found == false)
{
if (i > 0 && ctot25 != 0 || ctot50 != 0 || ctot100 != 0)
{
//Somthethin
Label lbl_Name = new Label { Location = new Point(50, 50), Text = (dataGridView1.Rows[i].Cells[1].Value).ToString() };
this.Controls.Add(lbl_Name);
//The rest of the codes
}
}

Shorting long if statement

I have spent hours making a tic tac toe game just using mainly if else statements, some of the code I just copy and pasted...
How would I just create one instance of the code, then refer to it later on? - when I need that code, instead of just copy and pasting massive lines of code each time. In this block of code, I am getting a random number between 1 to 10 this number will be stored in RI... then when it's Ai's turn the computer will randomly input an X in the button, then using this code it will check to determine if the computer has won. I hope that make sense =)
do
{
storeRI = rc.Next(0, 10); //storing random number into storeRI so it can be used later on in life.
if (storeRI == 1 && btn1.Text == "")
{
btn1.Text = "X";
Turn = 1;
if (btn1.Text == "X" & btn2.Text == "X" & btn3.Text == "X")
{
btn1.BackColor = Color.Green;
btn2.BackColor = Color.Green;
btn3.BackColor = Color.Green;
XScore += 1;
lblPScoreX.Text = XScore.ToString();
foreach (Button btn in buttonList)
btn.Enabled = false;
}
else if (btn1.Text == "X" & btn4.Text == "X" & btn7.Text == "X")
{
btn1.BackColor = Color.Green;
btn4.BackColor = Color.Green;
btn7.BackColor = Color.Green;
XScore += 1;
lblPScoreX.Text = XScore.ToString();
foreach (Button btn in buttonList)
btn.Enabled = false;
}
}
}
for example this code, is some of the code, that I have copied atleast 10 times, and it just makes me code look ugly and really hard to read.
for example this code, is some of the code, that I have copied atleast 10 times
Any time you have copied code, you should try to move it into a method. You can then just call the method directly. In your case, a method could easily accept the three buttons to affect, and work on them directly.
bool TestWin(Button btnA, Button btnB, button btnC)
{
if (btnA.Text == "X" & btnB.Text == "X" & btnC.Text == "X")
{
btnA.BackColor = Color.Green;
btnB.BackColor = Color.Green;
btnC.BackColor = Color.Green;
XScore += 1;
lblPScoreX.Text = XScore.ToString();
foreach (Button btn in buttonList)
{
btn.Enabled = false;
}
return true;
}
return false;
}
if (!TestWin(btn1, btn2, btn3))
TestWin(btn1, btn4, btn7);
The refactoring technique you may want to look into is Consolidate Duplicate Conditional Fragments
if (btn1.Text == "X" & btn2.Text == "X" & btn3.Text == "X")
{
btn2.BackColor = Color.Green;
btn3.BackColor = Color.Green;
}
else if (btn1.Text == "X" & btn4.Text == "X" & btn7.Text == "X")
{
btn4.BackColor = Color.Green;
btn7.BackColor = Color.Green;
}
else
{
return/break/continue; // hard to tell which you what as you have a do without a corresponding while
}
btn1.BackColor = Color.Green;
XScore += 1;
lblPScoreX.Text = XScore.ToString();
foreach (Button btn in buttonList)
{
btn.Enabled = false;
}
if (btn1.Text == "X")
{
btn1.BackColor = Color.Green;
if(btn2.Text == "X" & btn3.Text == "X")
btn2.BackColor = Color.Green;
btn3.BackColor = Color.Green;
}
else if (btn4.Text == "X" & btn7.Text == "X")
{
btn4.BackColor = Color.Green;
btn7.BackColor = Color.Green;
}
XScore += 1;
lblPScoreX.Text = XScore.ToString();
foreach (Button btn in buttonList)
{
btn.Enabled = false;
}
}
Nothing wrong with a long if else statement; it's better to have long readable code than short unmanageable code.
The one thing I can see that might help is to add in a method (with some changed to match your types):
public void ChangeButtonColor(Color thisColor, params Button[] buttons)
{
foreach (Button thisButton in buttons)
{
thisButton.BackColor = thisColor
}
}
then you can just add in to you code:
ChangeButtonColor(Color.Green, btn1, btn2, btn3);
This would save you some duplicated code.

radio button is clicked in any of the groupboxes, that it removes the click from which ever groupbox was previously clicked

I have an application that requires a set of questions that may range from 1 to 1000.
The questions are set up by the user and I need the groupbox to contain the
2 radio buttons indicated below.
The code does create multiple groupboxes containing 2 radio buttons.
This code is in a loop that is determined by how many questions are needed.
The issue is that when a radio button is clicked in any of the groupboxes,
that it removes the click from which ever groupbox was previously clicked.
How do I resolve this?
GroupBox grpAnswerType = new GroupBox(); // new groupbox
if (intZ < 9)
{
grpAnswerType.Name = "grpAnswerType00" + strQNumber;
}
if (intZ >= 10 & intZ <= 99) // intZ is the counter in the loop
{
grpAnswerType.Name = "grpAnswerType0" + strQNumber; // name is used later
}
if (intZ >= 100 & intZ <= 999)
{
grpAnswerType.Name = "grpAnswerType" + strQNumber;
}
grpAnswerType.Location = new Point(290, intR + 20);
grpAnswerType.Size = new Size(150, 45);
grpAnswerType.ForeColor = System.Drawing.Color.Red;
grpAnswerType.BackColor = SystemColors.Control;
grpAnswerType.Font = font;
grpAnswerType.Text = "Choose answer type ";
this.Controls.Add(grpAnswerType);
grpAnswerType.Show();
clsGlobals.gGroupBoxRadioButton3[intZ] = grpAnswerType; // add to array for later storage to database
pnlQ11.Controls.Add(grpAnswerType); // add to the dynamic panel on the form
RadioButton rbtnA1 = new RadioButton(); // Radio Button1
if (intZ < 9)
{
rbtnA1.Name = "rbtnA100" + strQNumber;
}
if (intZ >= 10 & intZ <= 99)
{
rbtnA1.Name = "rbtnA10" + strQNumber;
}
if (intZ >= 100 & intZ <= 999)
{
rbtnA1.Name = "rbtnA1" + strQNumber;
}
rbtnA1.Location = new Point(295, intR + 38);
rbtnA1.Size = new Size(60, 25);
rbtnA1.Text = "One";
rbtnA1.Font = font;
rbtnA1.ForeColor = System.Drawing.Color.Blue;
rbtnA1.BackColor = SystemColors.Control;
grpAnswerType.Controls.Add(rbtnA1);
pnlQ11.Controls.Add(rbtnA1); // if this is not commented, it appears on the panel, if not it does not
rbtnA1.Show();
clsGlobals.gRadioButtonOne[intZ] = rbtnA1;
rbtnA1.BringToFront();
RadioButton rbtnA2 = new RadioButton(); // Radio Button 2
if (intZ < 9)
{
rbtnA2.Name = "rbtnA200" + strQNumber;
}
if (intZ >= 10 & intZ <= 99)
{
rbtnA2.Name = "rbtnA20" + strQNumber;
}
if (intZ >= 100 & intZ <= 999)
{
rbtnA2.Name = "rbtnA2" + strQNumber;
}
rbtnA2.Location = new Point(355, intR + 38);
rbtnA2.Size = new Size(70, 25);
rbtnA2.Text = "All"; ;
rbtnA2.Font = font;
rbtnA2.ForeColor = System.Drawing.Color.Blue;
rbtnA2.BackColor = SystemColors.Control;
grpAnswerType.Controls.Add(rbtnA2);
pnlQ11.Controls.Add(rbtnA2); // if this is not commented, it appears on the panel, if not it does not
rbtnA2.Show();
clsGlobals.gRadioButtonAll[intZ] = rbtnA2;
rbtnA2.BringToFront();
I think it is because pnlQ11 is another UserControl (I am guessing you're using Windows Forms) and, acording to MSDN, a control can only be assigned to one Control.ControlCollection (http://msdn.microsoft.com/en-us/library/system.windows.forms.control.controlcollection.add%28v=vs.100%29.aspx).
So, your RadioButton is removed from the GroupBox and added to pnlQ11, which is the same control where all other RadioButtons belong. Then, the solution is to avoid adding the RadioButton to that other control and keep it only in the GroupBox

Categories