I've a winform usercontrol, that has a Panel, which is containing some TableLayout(which have also some other user controls).
All my components have a Dock=Fill and Autosize=True properties.
Currently, when I resize the windows, I don't have any scrollbar, the overflow is just no show.
I found that if I set the AutoScrollMinSize of my panel to something, I'm having those scrollbar appearing when I reach the set size.
My problem is that I add/remove elements on runtime, and I've also some things that I display or not depending the configuration. So for me it's very hard to hardcode here a value, either I've scrollbar too soon, or too late.
I'm sure there should be a way to configure my userControl, without having to calculate myself the size, to have the component displaying scrollbar, when the children's content cannot be displayed, do you know how?
Thank you!
You can change the AutoScrollMinSize value on the panel resize event or the form's resize event. That way, it won't be a fixed value and there will be a scrollbar available if the panel's child controls go beyond the panel edges -
private void panel1_Resize(object sender, EventArgs e)
{
panel1.AutoScrollMinSize = new System.Drawing.Size(panel1.Width, panel1.Height);
}
Related
I have a splitContainer. I want to resize the form inside the splitContaner's panel to scale with when I move the splitter as below. But my form doesn't get redrawn. Any suggestion, thank so much!
private void splitContainer1_SplitterMoved(System.Object sender, System.Windows.Forms.SplitterEventArgs e)
{
// Define what happens when the splitter is no longer moving.
Cursor.Current = System.Windows.Forms.Cursors.Default;
statictisTableDisplayForm1.ClientSize = new Size(statictisTableDisplayForm1.Width, splitContainer1.SplitterDistance);
statictisTableDisplayForm1.Invalidate();
statictisTableDisplayForm1.Refresh();
Refresh();
}
Form supposed to be a top-level control which represents a window of your application. You should not embed forms as controls into other forms (well, unless there is no other option).
Usually, you should not resize and/or move controls manually. There are several layout options which allow automatic resizing of controls when the size of their container changes: Anchor, Dock.
So better create a UserControl which will contain controls and logic of your StatictisTableDisplayForm and place it to SplitContainer panel with Dock set to Fill. That will automatically resize user control when you move the splitter.
Note: if you have to use StatictisTableDisplayForm on it's own too, then just place same user control to this form.
How do I implement scrolling for my Custom Control? My control is fully custom drawn and its height is variable, and a part of the control contains a menu so if there are many items in the control, I'll need to be able to put scroll bars there. I've not really been able to find any clues on how to do this. I did see something about ScrollableControl, but I'm still not sure if that's what I need.
Also, how will my control know when it needs to show the scroll bars? Because my control is fully custom drawn so there's no real "controls" in there it's just a bunch of pixels that are drawn onto it so it's not like I can just set AutoScroll to true and I can't do that anyway because it's not the main part of the control that needs scrolling, it's a particular location on the control that will need to have the scrollbars.
If your custom control inherits from the Panel control, you just set the size of the content yourself in the custom control by this setting:
this.AutoScrollMinSize = New Size(yourWidth, yourHeight);
If your control's ClientSize.Height is greater than yourHeight, you won't get any scrollbars. If it's less, then you get a scrollbar.
In your paint method, add this to the beginning:
protected override void OnPaint(PaintEventArgs e) {
e.Graphics.TranslateTransform(this.AutoScrollPosition.X,
this.AutoScrollPosition.Y);
Now everything you paint gets automatically transformed to the scrolling coordinates.
You have two options.
The good new is that it is possible and both are not really hard.
The bad new is that for one option you will have to adapt all your drawing code:
First make your Control, I use a Panel, to have Autoscroll=true;
Then you need to add one dummy control, I use another Panel, maybe like this, far enough to the right and bottom to force the ScrollBars to show:
public Form1()
{
InitializeComponent();
Panel panelDummy = new Panel();
panelDummy.Size = new Size(1,1);
panelDummy.Location = new Point(yourMaxX,yourMaxY);
panel1.Controls.Add(panelDummy);
}
And then you need to adapt your drawing code. Here is how:
private void panel1_Paint(object sender, PaintEventArgs e)
{
int xx = panel1.HorizontalScroll.Value;
int yy = panel1.VerticalScroll.Value;
e.Graphics.FillRectangle(Brushes.Wheat, new Rectangle(11 - xx, 22 - yy, 22, 311));
e.Graphics.FillRectangle(Brushes.RosyBrown, new Rectangle(11 - xx, 280 - yy, 22, 3));
}
private void panel1_Scroll(object sender, ScrollEventArgs e)
{
panel1.Invalidate();
}
I have added an Invalidate to the Scroll event to avoid messed up painting results.
The other option is simpler: Make your control large enough to hold all your drawn controls and the put it inside a Panel with AutoScroll=true; this will delegate the whole scrolling business to the containing Panel.
you can use aPanel with AutoScroll = true. After that, if you put any controls inside it, as long as their size is larger than the size of panel, the panel will automatically show scroll bars.. The trick can be used for any custom control asa well, as long as you place it inside a AutoScroll panel, and size it as large as you need it to be.
I've partially solved this problem by creating a custom control that inherits from Control and that is completely drawn in OnPaint. My solution so far is to use ScrollBarRenderer to draw my scroll buttons, then I define a Rectangle for the scrollable area. I then create an Image to draw my scrollable content onto, and use TranslateTransform Scroll that Image into position before using DrawImage to draw into the Scrollable Content Rectangle that I created. It's showing promise, although I haven't gotten it completely working yet since I have to handle all of the MouseOver and Click events on my own.
I have a form with a tab control.
I want each tab to have its own interface with its own size, so that I can have button layouts as necessary.
I am, in this example, only altering height.
Currently I have the default form height and default tab height set (set by tab index 0).
I need a programmatic way to set each tab's height individually, and on event selectedIndexChanged, I am able to resize the form as needed relative to the currently selected tab, but I don't know how to change each tab's height individually.
How can I achieve this?
It sounds like you are talking more about the height of the form based on the selected tab than the height of each individual tab item.
Assuming the TabControl is Dock-Filled on a parent form, you can try this code to resize the form's height based on the content of the TabPage:
void tabControl1_SelectedIndexChanged(object sender, EventArgs e) {
var controls = tabControl1.SelectedTab.Controls.Cast<Control>();
if (controls.Any()) {
this.Height = controls.Max(x => x.Bottom) + 72;
}
}
The routine finds the lowest based control on the TabPage and then adds a fudge number of 72 to account for the height of the form's non-client area and other miscellaneous spacing issues.
But note, constantly changing the height of the form based on a tab selection can be a bit jarring to the end user, and is probably not considered a popular UX implementation.
Using WinForms in C#, I'm struggling to get an embedded user control to resize correctly. I can add it to the panel with no issue, and the panel resizes as I expect (and want) it to.
To add the UserControl, I'm doing the following:
content.Controls.RemoveAt(0);
content.Controls.Add(c);
content.Controls[0].Dock = DockStyle.Fill;
content.Refresh();
I cannot figure out how to get the newly added control to resize properly, I've also tried using Anchor with Top,Bottom,Left,Right but to no avail. Any help would be appreciated, thanks.
Adding below will resize the user control with the parent control size.
this.Dock = DockStyle.Fill;
But, if you want to resize the child controls of your user control you will have to set their dock values and anchor values properly. Otherwise, the main user control will resize but the inner child controls of the user control will stay as they are.
You have said;
<< the control moves down, instead of resizing down
If there are some child controls that you want to stretch vertically you might try FlowLayout panel.
Are you 100% sure that Controls[0] is in fact referrencing your control after the add?
Your local var to the control is still valid, you could test that you are setting dock to the right thing by c.Dock = DockStyle.Fill;
I've figured it out.
At the panel which is the base for all added panels add the handler for the Resize event.
At the OnResize() add:
private void SummaryData_Resize(object sender, EventArgs e)
{
foreach (MyPanel pan in this.Controls)
{
pan.Dock = DockStyle.Fill;
}
}
It worked for me.
I've debugged the code and it seems at the OnResize all my panels lost their Dock setting.
I have a Windows Form window containing a FlowLayoutPanel, an OK Button, and a Cancel Button. The Form and FlowLayoutPanel both have AutoSize enabled, and the FlowLayoutPanel grows or shinks depending on the items placed in it.
I am trying to figure out how to position the OK and Cancel Buttons in the same row directly below the FlowLayoutPanel. I can't just specify positions for them since the FlowLayoutPanel above them grows and shrinks.
Any ideas on how to solve this?
Anchoring the buttons to the bottom of the form smells like a solution. If not, you can throw more panels at the problem but that's fugly. Simply using the Resize event can do wonders:
private void flowLayoutPanel1_Resize(object sender, EventArgs e) {
OKButton.Top = CancelButton.Top = flowLayoutPanel1.Bottom + 10;
}
Put your two buttons in another panel (anything will do).
Then put these two panels in another FlowLayoutPanel which arranges them top to bottom.