I am adding a new button in a Form in which there are already 2 existing ones. The problem occurs when btnCancel's content changes to a longer string, which makes the button auto-resize - hence, overlapping the button that I have added.
The Proxy Settings is the button that I added. If I change Don't sign in to a much longer string, then the middle button would overlap mine.
The code for the buttons is below:
//
// btnLogin
//
this.btnLogin.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.btnLogin.BackgroundImageLayout = System.Windows.Forms.ImageLayout.None;
this.btnLogin.Location = new System.Drawing.Point(340, 50);
this.btnLogin.Margin = new System.Windows.Forms.Padding(2);
this.btnLogin.Name = "btnLogin";
this.btnLogin.Size = new System.Drawing.Size(82, 24);
this.btnLogin.TabIndex = 0;
this.btnLogin.Text = "Sign in...";
this.btnLogin.UseVisualStyleBackColor = true;
this.btnLogin.Click += new System.EventHandler(this.btnLogin_Click);
//
// btnCancel
//
this.btnCancel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.btnCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel;
this.btnCancel.Location = new System.Drawing.Point(239, 50);
this.btnCancel.Margin = new System.Windows.Forms.Padding(2);
this.btnCancel.Name = "btnCancel";
this.btnCancel.Size = new System.Drawing.Size(94, 24);
this.btnCancel.TabIndex = 1;
this.btnCancel.Text = "Don\'t sign in";
this.btnCancel.UseVisualStyleBackColor = true;
//
// btnProxySettings
//
this.btnProxySettings.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.btnProxySettings.Location = new System.Drawing.Point(138, 50);
this.btnProxySettings.Margin = new System.Windows.Forms.Padding(2);
this.btnProxySettings.Name = "btnProxySettings";
this.btnProxySettings.Size = new System.Drawing.Size(92, 24);
this.btnProxySettings.TabIndex = 2;
this.btnProxySettings.Text = "Proxy Settings";
this.btnProxySettings.UseVisualStyleBackColor = true;
this.btnProxySettings.Click += new System.EventHandler(this.btnProxySettings_Click);
How can I make the latter button distance itself dynamically?
Edit as I noticed that my post got downvoted. I have tried several "calculations" using the data within btnCancel like location, size, width, etc. but I could not figure out a "rule" so to say. Or maybe there's even a method that I could not find which does everything "magically"? So it's not like I'm asking for you to do my homework or anything, but I found it useless for the current situation to showcase my poor attempts.
Put the buttons in a flowLayoutPanel with a RightToLeft FlowDirection. This should guarantee proper separation without any need to manually calculate any positions. Whenever you work with auto-scaling controls it is usually a good idea to use some kind of panel with an automatic layout.
Related
I'm fairly new to programming and this is my first Forms program.
I'm trying to place buttons inside a panel in a manner that they get automatically sorted by alphabetical order.
At first I was trying with a FlowLayoutPanel, which displayed the buttons with the correct size and placement, but not sorted by Alphabetical order:
With FlowLayoutPanel. Ideal Size and placement, but no sorting.
I also had a few problems while trying to automatically scale it to screen size.
After failing with a FlowLayoutPanel, I tried just a normal panel. It fixed all my previous problems, but would stretch the buttons when docked:
With a normal panel. Perfect sorting and scaling, but stretching.
Here is the code, if it matters:
Button modButton = new Button();
modButton.Location = new System.Drawing.Point(3, 3);
modButton.Name = skinName;
modButton.Size = new System.Drawing.Size(200, 200);
modButton.TabIndex = 0;
modButton.Text = skinName;
modButton.TextAlign = System.Drawing.ContentAlignment.BottomCenter;
modButton.UseVisualStyleBackColor = true;
modButton.BackgroundImageLayout = ImageLayout.Zoom;
modButton.Dock = System.Windows.Forms.DockStyle.Left;
modButton.Click += new System.EventHandler(this.modButton_Click);
modButton.TextImageRelation = System.Windows.Forms.TextImageRelation.ImageAboveText;
this.panel2.Controls.Add(modButton);
modList.Add(skinName);
And for the panel:
this.panel2.AutoScroll = true;
this.panel2.AutoSize = true;
this.panel2.BackColor = System.Drawing.SystemColors.Control;
this.panel2.Dock = System.Windows.Forms.DockStyle.Fill;
this.panel2.Location = new System.Drawing.Point(0, 0);
this.panel2.Name = "panel2";
this.panel2.Size = new System.Drawing.Size(636, 450);
this.panel2.TabIndex = 7;
I have a simple System.Windows.Forms.Label in a System.Windows.Forms.Form.
I want to dynamically resize the label to fit text loaded runtime, while keeping it Anchored to the right and bottom of its parent form.
According to the MSDN Documentation:
It is “always true” that the Location Property remains constant (i.e., that the top left position of the Control will never change).
It is “always true” that the Anchor property is respected when AutoSize is true (i.e., that the Location Property—the top-left corner—will be modified so that the Anchored Sides maintain their initial distance from the edges of their parent controls).
From my reading of this, I would expect that the second truth overrides the first when Anchor is anything but AnchorStyles.None.
However, this doesn't seem to bear out in practice.
Consider the following:
// From ExampleForm.Designer.cs
this.label = new System.Drawing.Label();
this.label.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.label.AutoSize = true;
this.label.Location = new System.Drawing.Point(600, 400);
this.label.Size = new System.Drawing.Size(170, 20);
this.label.Text = "[Populated at Runtime]";
this.label.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
// ...
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(800, 450);
this.Controls.Add(this.label);
// ...
// Sometime after Form Initialization, this is called
void PopulateLabel() {
var oldRight = label.Right;
label.Text = "Hey here's some new text. It's pretty long so the control will have to resize";
// Without this next line, the Right Anchor distance is not maintained.
// label.Left -= (label.Right - oldRight);
System.Diagnostics.Debug.Assert(label.Anchor.HasFlag(AnchorStyles.Right) && label.Right == oldRight, "The label didn't stay anchored to the right");
}
Obviously I can work around this by tracking the distance manually, as above.
I just wonder if there isn't some way this is “supposed” to work that I'm doing wrong.
The one observation I have to offer is this: it works if the label is not anchored to the bottom.
Do I need to call Suspend/Resume/PerformLayout on the Label? on the Form?
Are the docs wrong?
Am I being foolishly naïve or completely misunderstanding something?
Do I need some sort of intermediary Control for this to work and the docs assume I know this?
To address some possible complications that show up in similar questions (or that I dreamt up):
rightToLeft is false,
Dock is DockStyle.None,
the label's Parent is the form itself, not an intermediary panel or other control.
the Margin seems irrelevant
Anchoring to the Top or Bottom seems irrelevant to Right not working.
System.Windows.Form.Button works as expected. I haven't tested other controls.
Try using a TableLayout, it tends to obey the Control layout properties better. E.g:
public class MyForm : Form {
Label label = new Label() { BackColor = Color.Blue, ForeColor = Color.White };
public MyForm() {
TableLayoutPanel panel = new TableLayoutPanel() { BackColor = Color.Green };
panel.ColumnCount = 1;
panel.RowCount = 1;
panel.Controls.Add(label, 0, 0);
panel.Dock = DockStyle.Bottom;
panel.AutoSize = true;
panel.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
panel.Controls.Add(label);
//this.label.Anchor = AnchorStyles.Right | AnchorStyles.Top;// | AnchorStyles.Bottom; // ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
//this.label.Dock = DockStyle.Fill;
this.label.Dock = DockStyle.Right;
this.label.AutoSize = true;
this.label.Margin = Padding.Empty;
//this.label.Location = new System.Drawing.Point(600, 400);
//this.label.Size = new System.Drawing.Size(170, 20);
this.label.Text = "[Populated at Runtime]";
//this.label.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
// ...
//this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
//this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(800, 450);
//this.Controls.Add(this.label);
this.Controls.Add(panel);
// ...
Button btn = new Button { Text = "Change text" };
btn.Click += delegate {
PopulateLabel();
};
Controls.Add(btn);
}
// Sometime after Form Initialization, this is called
void PopulateLabel() {
var oldRight = label.Right;
label.Text = "Hey here's some new text. It's pretty long so the control will have to resize";
// Without this next line, the Right Anchor distance is not maintained.
// label.Left -= (label.Right - oldRight);
//System.Diagnostics.Debug.Assert(label.Anchor.HasFlag(AnchorStyles.Right) && label.Right == oldRight, "The label didn't stay anchored to the right");
}
}
Why my Ok and Cancel Button are not showing up on the UI screen? I see the form, the label and the text box but I can't see the Cancel and OK buttons.
To give you a background I am creating this dialog box programmatically and all I need a a couple of text boxes , and their labels of course. And an OK and Cancel button .
All these sizes that I have used here is by trial and error as I am not much experienced in the UI control area of Visual C# 2010.
public void function x ()
{
var fileNameDialog = new Form();
fileNameDialog.Text = "Save New Name";
Label fileLabel = new Label();
fileLabel.Size = new System.Drawing.Size(150, 40);
fileLabel.Text= "Enter Person Name";
fileNameDialog.Controls.Add(fileLabel);
TextBox fileTextBox = new TextBox();
fileTextBox.Location = new System.Drawing.Point(fileLabel.Location.X + 300, fileLabel.Location.Y);
fileTextBox.Size = new System.Drawing.Size(220, 40);
fileNameDialog.Controls.Add(fileTextBox);
fileTextBox.TextChanged += TextBox_TextChanged;
fileTextBox.Text= textboxValue;
Button okButton = new Button();
okButton.Visible = true;
okButton.Text = "OK";
okButton.Location = new System.Drawing.Point(fileTextBox.Location.X, fileTextBox.Location.Y - 80);
fileNameDialog.Controls.Add(okButton);
okButton.Click += new EventHandler(okButton_Click);
Button cancelButton = new Button();
cancelButton.Visible = true;
cancelButton.Text = "Cancel";
fileNameDialog.Controls.Add(cancelButton);
cancelButton.Click += new EventHandler(cancelButton_Click);
cancelButton.Location = new System.Drawing.Point(fileTextBox.Location.X+50, fileTextBox.Location.Y - 80);
fileNameDialog.ShowDialog();
}
Your fileTextbox.Location.Y is zero, so subtracting 80 puts in above the form.
Try fileTextBox.Bottom + 4 or something like that.
Using the designer to create this dialog form is probably the better route to take. Along with the placement of the controls, you can use Anchors to make the controls relate to the size of the form.
When i add a radio button in visual c# the text name of the radio button is aligned perfectly to the right . if i create a radio button dynamically and give it several properties etc.. when i debug and view it, the text or name of the radio button is shifted slighted up and to the right of the radio button? i am looked over several properties including padding etc.. but i am not able to figure out how to correct this dynamically. what is going on and how can i fix this?
here is example of the properties i am using right now
radio_ip_addresses[i] = new RadioButton();
radio_ip_addresses[i].Name = "radio_" + i;
radio_ip_addresses[i].Text = ip_addresses.Dequeue();
radio_ip_addresses[i].Location = new Point(x, y);
radio_ip_addresses[i].Font = new Font("Microsoft Sans Serif", 8, FontStyle.Bold);
radio_ip_addresses[i].ForeColor = Color.White;
radio_ip_addresses[i].TextAlign = ContentAlignment.MiddleLeft;
radio_ip_addresses[i].Visible = true;
radio_ip_addresses[i].Parent = this;
Thanks Rotem, i took your suggestion to check the designer.cs i should have thought of that. it was autosize that was the key :), see below from what i found in the designer.cs.
this.radioButton1.AutoSize = true;
this.radioButton1.Location = new System.Drawing.Point(192, 50);
this.radioButton1.Name = "radioButton1";
this.radioButton1.Size = new System.Drawing.Size(85, 17);
this.radioButton1.TabIndex = 71;
this.radioButton1.TabStop = true;
this.radioButton1.Text = "radioButton1";
this.radioButton1.UseVisualStyleBackColor = true;
I wish to add a button for every line in a file to a panel.
My code so far is:
StreamReader menu = new StreamReader("menu.prefs");
int repetition = 0;
while(!menu.EndOfStream)
{
Button dynamicbutton = new Button();
dynamicbutton.Click += new System.EventHandler(menuItem_Click);
dynamicbutton.Text = menu.ReadLine();
dynamicbutton.Visible = true;
dynamicbutton.Location = new Point(4+repetition*307, 4);
dynamicbutton.Height = 44;
dynamicbutton.Width = 203;
dynamicbutton.BackColor = Color.FromArgb(40,40,40);
dynamicbutton.ForeColor = Color.White;
dynamicbutton.Font = new Font("Lucida Console", 16);
dynamicbutton.Show();
menuPanel.Controls.Add(dynamicbutton);
repetition++;
MessageBox.Show(dynamicbutton.Location.ToString());
}
menu.Close();
The problem is that only the first control gets created.
The code looks fine but there could be a following situations.
1.You might have only one entry in the file, so you are experiencing only One Button added to the panel.
2.Your panel width is smaller than the sum of all the dynamic buttons width.
I suspect no 2 is the main reason that is causing problem.
So, I recommend that you use FlowLayoutPanel. To add a dynamic content as it automatically layout all the child controls.
Each time it is generating the same name for dynamic controls. That's the reason why it is showing only the last one. It simply overwrites the previous control each time.
int x = 4;
int y = 4;
foreach(PhysicianData pd in listPhysicians)
{
x = 4;
y = panPhysicians.Controls.Count * 30;
RadioButton rb = new RadioButton();
rb.CheckedChanged += new System.EventHandler(rbPhysician_CheckedChanged);
rb.Text = pd.name;
rb.Visible = true;
rb.Location = new Point(x, y);
rb.Height = 40;
rb.Width = 200;
rb.BackColor = SystemColors.Control;
rb.ForeColor = Color.Black;
rb.Font = new Font("Microsoft Sans Serif", 10);
rb.Show();
rb.Name = "rb" + panPhysicians.Controls.Count;
panPhysicians.Controls.Add(rb);
}
Try this code
StreamReader menu = new StreamReader("menu.prefs");
var str = menu.ReadToEnd();
var items = str.Split(new string[] {"\r\n" } , StringSplitOptions.RemoveEmptyEntries);
foreach (var item in items)
{
Button dynamicbutton = new Button();
dynamicbutton.Click += new System.EventHandler(menuItem_Click);
dynamicbutton.Text = item;
dynamicbutton.Visible = true;
dynamicbutton.Location = new Point(4+repetition*307, 4);
dynamicbutton.Height = 44;
dynamicbutton.Width = 203;
dynamicbutton.BackColor = Color.FromArgb(40,40,40);
dynamicbutton.ForeColor = Color.White;
dynamicbutton.Font = new Font("Lucida Console", 16);
dynamicbutton.Show();
menuPanel.Controls.Add(dynamicbutton);
repetition++;
}
The problem with Panel and similar controls other than the FlowLayoutPanel is when you create a control and a second one, the second is created at the same position if you are not changing it's location dynamically or setting it according to the other already added controls. Your control is there, it's in the back of the first control.
A flowLayoutPanel is better as it will add the controls next to each other as you add them while compromising more finer control at their positioning.
I also have similar problems with panels. For what you are doing it could be useful to just add strings to a listbox rather than using labels and a panel. That should be simpler.