I am having a panel in Winforms which loads panels in it during a method call.
In the method call I have written following code:
//to get number of panel present in main panel so that new panel position can be set
int counT = panel1.Controls.Count;
Panel p = new Panel();
p.Location = new Point(3, 3 + (counT * 197));
p.Size = new Size(280, 150);
//To add panel to parent panel
panel1.Controls.Add(p);
Every time I call the method it will load a panel in the main panel. Everything works fine if i didn't scroll the scroll bar. Once I scroll the Scroll bar to down and after that i call the method, the distance between panels increases.
As per logic written the distance between two panel should be 197 pixel along Y axis, but it is increasing by more.
I have set AutoScroll=true
Any help !!!
That's quite strange behavior which I didn't know until now (and I have a lot experience in WF). It can be seen when the parent panel is scrolled when the code above is executed. I was thinking that child control positions are relative to the ClientRectangle, but it turns out that they are accounting the DisplayRectangle.
Shortly, instead of this
p.Location = new Point(3, 3 + (counT * 197));
use this
var parentRect = panel1.DisplayRectangle;
p.Location = new Point(parentRect.X + 3, parentRect.Y + 3 + (counT * 197));
Panel.AutoScrollPosition affects Location property of all child controls. Scrolling works in this way. So you should keep in mind that, for example you could store current scroll position, move position to (0,0), add new controls, and restore scroll position after all
//to get number of panel present in main panel so that new panel position can be set
int counT = panel1.Controls.Count;
var pos = this.panel1.AutoScrollPosition; // Whe are storing scroll position
this.panel1.AutoScrollPosition = new Point(Size.Empty);
Panel p = new Panel();
p.Location = new Point(3, 3 + (counT * 197));
p.Size = new Size(280, 150);
p.BorderStyle = BorderStyle.FixedSingle;
//To add panel to parent panel
panel1.Controls.Add(p);
this.panel1.AutoScrollPosition = new Point(Math.Abs(pos.X), Math.Abs(pos.Y)); // We are restoring scroll position
Related
I have a windows form that has 2 panels inside it, one takes up left half of the form, one right. Now when a certain event occurs in my program (I receive a message from server for example), I want to add a new control (say a third panel) between the two existing, so I need to make make them smaller and move them to the sides of my form.
This can happen while the form is minimized and this is where my problem is. Panels Size returns [0,0] when the form is minimized so I cant use it for calculations.
So my first question is, how can I get "original" size of controls while the form is minimized?
And then, even if I somehow calculated the new Size (say I have 400px wide form with 2x 200px panels and I want the new 3rd panel to be 200px wide, so the old panels will become 100px wide), and applied it:
leftPanel.Size = new Size(100, 100);
then after the form is restored from minimized state to normal state, the panel will be way bigger than specified 100x100. Seems like it will restore to the forms ClientSize + the newly specified size
Therefore my question: how can I add and resize controls to form while the form is minimized?
Sample procedures to resize Panels hosted in a Form and adapt the Layout when a new Panel is inserted in the middle of the two existing.
The WindowState of the hosting Form Forms is not relevant (it can be minimized, maximized or in normal state).
► Using the first method, if the Form is maximized, the Panels will retain the initial Height.
► Using the second method, as it is now, the Panels' Height will be set to the Form's ClientSize.Height. It can of course be changed, setting the TableLayoutPanel Row(s) to an Absolute height instead of AutoSize.
Using the Docking feature alone:
Set the Form AutoSizeMode = Dpi
Add two Panels to the Form (e.g., panelLeft and panelRight)
Set the Width of both Panels to 200
Set panelLeft to Dock = DockStyle.Left and panelRight to Dock = DockStyle.Right
Right-click the Panel on the left and select SendToBack (!important)
Adjust the Form Size: it should be: (418, 138). Not important, just for a visual confirmation
In the Form constructor set this.ClientSize = new Size(400, 100);
Add a new public method to the Form:
public void AdjustPanelsWidth(int newWidth)
{
this.panelLeft.Width = newWidth;
this.panelRight.Width = newWidth;
}
When you need to add a new Panel in the middle of the two existing Panels:
(someForm represents the current instance of the minimized Form)
int newSize = 100;
someForm.AdjustPanelsWidth(newSize);
var p = new Panel() {
Size = new Size(newSize * 2, 100),
Dock = DockStyle.Fill
};
p.BringToFront();
someForm.Controls.Add(p);
Using a TableLayoutPanel:
Add a TableLayoutPanel to the Form
Set it to Dock = DockStyle.Top
Edit Columns and Rows to have 3 Columns and 1 Row
Set the Columns Styles in the TLP Designer as:
Columns:
(0) Percent 50%
(1) AutoSize
(2) Percent 50%
Row:
(0) AutoSize
Closing the TLP Designer, it should appear to have just two Columns: since the central one is auto-sized and it has no content, its Width is currently 0.
Add two Panels to the Form (not to the TableLayoutPanel directly)
Set the Size of the Panels = (200, 100)
Drag one Panel inside the left Column of the TLP and the other to the Column on the right
! Verify, in VS Property panel, that the Column property of Panel on the Left is Column 0
The same for the Panel on the Right: the Colum property must be Column 2
If the Column is wrong, edit it manually.
Select both Panels and set both to Dock = DockStyle.Fill
(now you should see the TLP completely filled by the Panels, both occupying 50% of the TLP Size)
Adjust the Form size as before (still not actually important)
In the Form constructor set this.ClientSize = new Size(400, 100); (as before)
Add a public method to the Form:
public void AddControl(Control control)
{
// Add a Control to Column 1 - Row 0
this.tableLayoutPanel1.Controls.Add(control, 1, 0);
panel.Dock = DockStyle.Fill;
}
To add a new Panel in the middle Column:
var p = new Panel() {
Size = new Size(200, 100),
BackColor = Color.Red,
Margin = new Padding(0)
};
someForm.AddControl(p);
Structure of a Form that implements the TableLAyoutPanel method described:
ClockMinimize() => Minimizes the Clock size, squeezing it between two other Panels
ClockShow() => Enlarges the Clock to overlap the other Panels, which will resize to completely fill the Form's ClientArea:
using System.Drawing;
using System.Windows.Forms;
public partial class frmClock : Form
{
public frmClock() => InitializeComponent();
private int m_ClientHeight = 0;
public void ClockShow()
{
this.panClock.Parent = this;
this.panClock.Size = new Size(360, 80);
this.panClock.Location = new Point(20, 10);
// Adjust the Clock Font Size here
this.panClock.BringToFront();
}
public void ClockMinimize()
{
this.panClock.Size = new Size(200, 40);
tableLayoutPanel1.Controls.Add(this.panClock, 1, 0);
this.panClock.Margin = new Padding(0, (m_ClientHeight - this.panClock.Height) / 2, 0, 0);
// Adjust the Clock Font Size here
AdjustPanelsWidth(panClock.Width / 2);
}
public void AdjustPanelsWidth(int newWidth)
{
this.panLeft.Width = newWidth;
this.panRight.Width = newWidth;
}
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
this.MinimumSize = this.Size;
m_ClientHeight = this.ClientSize.Height;
}
protected override void OnClientSizeChanged(EventArgs e)
{
base.OnClientSizeChanged(e);
if (this.ClientSize.Height > 0) {
m_ClientHeight = this.ClientSize.Height;
}
}
}
I have come up with this workaround: I'm postponing resizing/moving until the form returns from minimized state, using async/await.
Instead of my original function:
public void changeControlPositionAndSize() {
//calculate new size and location based on size and location of neighboring controls
myPanel.Location = ...
myPanel.Size = ...
}
I'm now using:
public async Task changeControlPositionAndSize()
{
while (WindowState == FormWindowState.Minimized)
{
await Task.Delay(2000);
}
//calculate new size and location based on size and location of neighboring controls
myPanel.Location = ...
myPanel.Size = ...
}
I need help to make vertical scrollbar work with the panel to scroll down the panel, i tried to make AutoScroll = true but not work, so how I can set yp the vertical scrollbar??
Thanks
Assuming your panel is named panel1(or else replace it),try the following and you shall see the scrollbars:
Button b = new Button();
b.Location = new Point(20, panel1.Height + 20);
panel1.Controls.Add(b);
I just added a button for demonstration purposes you add whatever you need.
Or as i said in the comments using the autoscrollminsize:
panel1.AutoScrollMinSize = new Size(panel1.Width + 50, panel1.Height + 50);
My form1 size is 800,600
Then i have two panels in the form1 designer:
Panel1 is at location: 0,24 size: 200,437
Panel2 is at location: 584,24 size: 200,437
The result is two panels at each side of the form.
Now i did in my program when you put the mouse somewhere in the form1 area its showing a pictureBox i create in the form1 constructor:
pb = new AnimatedPictureBox.AnimatedPictureBoxs();
pb.Visible = false;
pb.Size = new Size(500, 350);
pb.Location = new Point((ClientSize.Width - pb.Width) / 2,
(ClientSize.Height - pb.Height) / 2);
The problem is that the new pictureBox variable pb is not in the size that will fill all the area between the two panels.
I want the size of the pictureBox to fill almost all the space between the two panels Width and Height maybe to leave some space like 5 spaces each side so there will be a border.
How can i calculate what the pictureBox size should be ?
EDIT**
This is an image where the program is working regular. On each panel on the left and right i added 4 pictureBoxes.
When i move my mouse cursor inside one of the pictureBoxes area its showing its content in a larger pictureBox in the middle.
And this is how it looks like when i put the mouse cursor in one of the pictureBoxes area the pictureBox in the middle is not big enough its Width and Height dosent make the big pictureBox to be excatly between the two panels. The big pictureBox not high and not wide enough.
if you want to make your layout stable even after resizing you should use Dock property for your panels and set Anchor for your picture box. Like that:
panel1.Dock = DockStyle.Left;
panel2.Dock = DockStyle.Right;
pb.Anchor = AnchorStyles.Left | AnchorStyles.Right;
And in general to place it in the center you can use something like that:
var width = this.Width - panel1.Width - panel1.Margin.Horizontal
- panel2.Width - panel2.Margin.Horizontal;
pb.Size = new Size(width, 300); // put your needed height here
pb.Top = this.Height/2 - pb.Height/ 2;
pb.Left = panel2.Left + panel2.Width + panel2.Margin.Right;
I want create manually PictureBox and Label on horizontal Panel, The count of PictureBox and Label on panel Unknown maybe 200 or more or less, I use the below code to do that but i face two troubles first one:
I want add the new object created in the first not in the end for example if i created items "A B C D E" want it add on Panel "E D C B A" want always the new come to first.
Note: Panel width "230" Height "710"
Second trouble:
Currently when i use Panel scroll bar to go down than add new objects find happen big free space between the last object created and the new and if i used scroll again to go down and created new object on panel happen more big free space.
int Right = 50, Top = 0;
// Create Image + Text
PictureBox pbox = new PictureBox();
pbox.Size = new Size(140, 80);
pbox.Location = new Point(Right, Top);
pbox.Image = Image.FromFile("");
Panel1.Controls.Add(pbox);
// Create label
Label lblPlateNOBAR = new System.Windows.Forms.Label();
lblPlateNOBAR.Text = lblPlateNO.Text;
lblPlateNOBAR.Location = new Point(Right + 20, Top + 80);
Panel1.Controls.Add(lblPlateNOBAR);
Top = Top + 150;
In order to make the objects insert into the panel, you'd need to move the controls which already exist in the panel:
int right = 50;
// Create Image + Text
PictureBox pbox = new PictureBox();
pbox.Size = new Size(140, 80);
pbox.Location = new Point(right, 0);
pbox.Image = Image.FromFile("");
// Create label
Label lblPlateNOBAR = new System.Windows.Forms.Label();
lblPlateNOBAR.Text = lblPlateNO.Text;
lblPlateNOBAR.Location = new Point(right + 20, 80);
foreach(var control in Panel1.Controls)
{
control.Top = control.Top + 150;
}
Panel1.Controls.Add(pbox);
Panel1.Controls.Add(lblPlateNOBAR);
I know it might seem that I'm not answering your question, but you can take little time to know my suggestion too. I don't know what you wanna achieve, but when you want to make such a sophisticated program, it's a better practice that you do all the work needed yourself, not relying on Windows Forms Controls. Trying to add, remove, change location of lots of controls will reduce the application performance very much. I suggest that you draw, for example your pictures, yourself, using Graphics and Image objects and Paint event. Also handle things like clicking and selecting pictures by MouseEvents. It might seem a little hard at first, but after you've done this you have far better performance and flexibility. This becomes more important considering you mentioned you wanna place 200 pictures in the panel. This also prevents trouble of flickering that appears when you change position of many controls. It's good to mention that to do scrolling in this case, you can place a Panel inside of a Parent Panel and use AutoScroll feature only for the parent panel to handle scrolling. This way you don't have to care about the scrolling anymore.
Adding some gui modifications and I want to have a button which is 10pixels away from the forms left and right border. With this code the right border of the button is around 20-30 pixel outside the form window. Why is that? How can I position my button to be exactly 10pixels away from the form borders ?
int margin = 10;
meny1 = new Button();
meny1.Top = 50;
meny1.Left = margin;
meny1.Size = new Size(this.Width - (2*margin), 30);
You should calculate with this.ClientWidth although I would expect the difference to be just the BorderSize, not 20 pixels.
Use the Form.ClientWidth. This code worked for me.
button1.Left = 10;
button1.Width = this.ClientRectangle.Width - 20;