1
votes

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?

2

2 Answers

0
votes

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;
        }
    }
}
0
votes

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 = ...
    }