How can I make two controls share the same height. I have set the Size to be the same for both controls but when I run it, I am seeing a difference.
this.txtUserName.Size = new System.Drawing.Size(382, 45);
this.btnLogin.Size = new System.Drawing.Size(75, 45);
Actually both have the same Height as you set them. However in order to accomodate various BorderStyles (or FlatStyles as it is called in the case of Buttons) the full size is not always visible.
So, the Button will look to be one pixel smaller on each side than the Height is has with these (current) appearances:
button1.FlatStyle = FlatStyle.Standard
button1.FlatStyle = FlatStyle.System
The full Size will be visible with
button1.FlatStyle = FlatStyle.Popup
button1.FlatStyle = FlatStyle.Flat
If you are sure about your choice of FlatStyle you may want to adapt their Height (and Location!) accordingly..
To further complicate thing the TextBox's visible Height will change if you set its BorderStyle from FixedSingle or Fixed3D to None: It will shrink by 7 (!) pixels..
Note that as far as I remember, all those details of the borderstyles depend on the Windows version & Visual Styles on the target machine.. I am running W8.1 here
Open the Form.Designer.cs and go to InitializeComponent() method for the form, you'll see initialization code for all components on the form.
If you are setting these values prior to InitializeComponent() call from the constructor, it'll be lost. Otherwise you may need to check Margin and Padding of the components.
http://msdn.microsoft.com/en-us/library/vstudio/ms229627(v=vs.100).aspx
Related
I have a form which contains a Menu Strip docked to the top, a Status Strip docked to the bottom, and a Panel docked to fill the entire space between the aforementioned controls. I have set the attributes to the following values for the form:
During the design phase:
AutoScaleMode: Dpi
AutoSize: false
AutoSizeMode: GrowOnly
DoubleBuffered: true
SizeGripStyle: Show
During runtime (in the form's constructor):
// Calculate the default size of the window on the basis of the ratio of the dimensions of the window to the dimension of the screen resolution of the machine used in development as the default dimensions of the window is aligned to that of the machine used to design it
this.Size = new Size(Screen.GetWorkingArea(this.Location).Size.Width * (widthOfWindowInDesignPhase /horizontalResolutionOfTheDisplayInDesignPhase), Screen.GetWorkingArea(this.Location).Size.Height * (heightOfWindowInDesignPhase / verticalResolutionOfTheDisplayInDesignPhase));
this.MinimumSize = new Size(this.Size.Width, this.Size.Height);
My first attempt to resolve this issue was to tinker around with the AutoSize and AutoSizeMode properties, but I require this to be set to the aforestated values as changing them would not allow the user to resize the form. The other approach I tried, which also failed, was by setting the AutoSize properties of the aforementioned controls to false as to force the child containers of the form to not resize.
Thanks in advance.
PS Screenshot of the concerned form:
A (blunder) numeric error occurs when calculating the size of the form as the statements (widthOfWindowInDesignPhase /horizontalResolutionOfTheDisplayInDesignPhase) and (heightOfWindowInDesignPhase / verticalResolutionOfTheDisplayInDesignPhase) return a floating point value that cannot be stored as an integer.
The appropriate statement is as follows:
this.Size = new Size(Convert.ToInt32(Screen.GetWorkingArea(this.Location).Size.Width * (Convert.ToDouble(widthOfWindowInDesignPhase) / Convert.ToDouble(horizontalResolutionOfTheDisplayInDesignPhase))), Convert.ToInt32(Screen.GetWorkingArea(this.Location).Size.Height * (Convert.ToDouble(heightOfWindowInDesignPhase) / Convert.ToDouble(verticalResolutionOfTheDisplayInDesignPhase))));
The Windows Forms have Size and ClientSize Properties. Windows Forms also have a MinimumSize property that lets you set the smallest allowed size of the form. I am looking for a way to set the minimum ClientSize of a form. I'm new to c# and I am unsure of the best way to do this.
It occurred to me that I could use the Form.SizeChanged event to check and restrict the form size but this seemed messy and I am looking for another way of doing it.
Note: If the form border size is changed I want the Minimum Client Size to be maintained.
How to set a minimum Size of a Form's Client Area.
The Form.MinimumSize property sets the minimum size of the Form as a whole, including the current borders, the Caption and the subtle internal padding that is applied when the Form is resized and a new Layout is performed (many factors determine this activity).
It may be imperceptible, because it's fast (and, usually, nobody cares), but the relation between the Form Size and the Client Size is not constant. It can change when the Form is resized, dragging its borders. Or a System event causes this to happen.
Plus, changing the System settings, in many departments (the properties of the Windows, the Theme, Dpi, Font size etc.), can determine a change in the relations between the Form size and the size of its client area.
The good thing is that the Form is aware of these changes and, when notified of a System event that alters the aspect of Windows in some way, re-performs its layout.
When this happens (and it can happen frequently, always when a Form is resized), the OnLayout method is called.
Overriding OnLayout, allows to update values that rely on the Window/Client area measures.
➨ It can be interesting to see what happens when System settings,
affecting the aspect of the Windows, are changed while the application
is running. In this specific context, how many times the OnLayout
method is called and what the LayoutEventArgs properties are set
to.
This all considered, we can create a public MinimumClientSize Property.
We override OnLayout and reset the Form.MinimumSize to the new Form.MinimumClientSize plus the difference between the Form.Size and the Form.ClientSize.
For example, if we need to keep the Client Area size to a minimum of (500, 500):
private Size m_MinimumClientSize = new Size(500, 500);
public Size MinimumClientSize {
get => m_MinimumClientSize;
set { m_MinimumClientSize = value;
PerformLayout();
}
}
protected override void OnLayout(LayoutEventArgs e) {
base.OnLayout(e);
MinimumSize = m_MinimumClientSize + (Size - ClientSize);
}
If we add to the OnLayout method:
Console.WriteLine($"ClientSize: {ClientSize}");
Console.WriteLine($"MinimumSize: {MinimumSize}");
Console.WriteLine($"Size: {Size}");
it becomes clear that the relation between Form.Size and Form.ClientSize is not always the same.
We could also calculate the difference between Size and ClientSize this way:
var borderSize = new Size(
(SystemInformation.FrameBorderSize.Width * SystemInformation.BorderMultiplierFactor
+ (SystemInformation.Border3DSize.Width * 2)) * 2,
(SystemInformation.FrameBorderSize.Height * SystemInformation.BorderMultiplierFactor
+ (SystemInformation.Border3DSize.Height * 2)) * 2);
var captionSize = new Size(0, SystemInformation.CaptionHeight);
MinimumSize = MinimumClientSize + borderSize + captionSize;
These fixed measures are correct. In normal situations, they provides the same values.
Not always, though. Never, when a Form is resized to its MinimumSize.
Plus, we're only considering a Form with a 3d Border.
Well, we could also override WndProc...
I am trying to get an accurate Form.Width on FormClosing().
I have a zoom() method I use to scale a picture in the Form. The form's width is then manually re-sized by me to fit. I then, set the MaximumSize's Width limit to the new width of the form. For our purpose, let's say the width and maxwidth are now 1386.
If I re-size the form in the Windows interface by dragging its edge to the left, the width is being reduced just fine. FormClosing reports the re-sized width accurately. Let's say 1107.
However, if go through the zoom() method I wrote, even though I drag to the left to the same position, FormClosing is reporting the ORIGINAL 1386 width. The only things I do to form size in the zoom() method are set width and maxwidth.
I am at a loss to handle this behavior. I need FormClosing to report the correct size. I think FormClosing is setting the Width to MaximumWidth when it fires. I think I read something about how the Form is set to Hidden by the time the FormClosing event is fired. Maybe being Hidden reverts its size to MaxWidth.
Any help would be much appreciated. I have been struggling with this for a few hours and can't find anything.
Thanks.
Here is the relevant code:
private void zoom()
{
// Re-size form width to slightly more than page width.
// This is percentage-based, meaning 100 = default size.
Size picSize = new Size
{
Width = (int)(originalRenderingSize.Width * integerUpDownZoom.Value / 100),
Height = (int)(originalRenderingSize.Height * integerUpDownZoom.Value / 100),
};
// some code here which I commented-out, and still, the problem exists.
// Set maximum to prevent ugly sizing.
this.MaximumSize = new Size(picSize.Width + 40, Screen.FromControl(this).WorkingArea.Height);
// The problem is this: When this method processes, as shown, a page is rendered and sized according to
// a user-provided zoom level represented by an integerUpDown control. Once rendered, the form should
// re-size its width to match the newly-scaled page's width. This works, too. So far, so good.
//
// But!!! If the user grabs the right side of the form and drags it to the left to reduce the width
// of the form (mind you, this is Windows OS doing this), upon Form.Form_Closing(), you can see a
// quick flash of the form fully-open and unscrolled. Then, in the FIRST line of Form_Closing(),
// the debugger reports the form's width as the fully-open and UNSCROLLED width.
//
// The goal is to set the width upon the conclusion of this zoom, but then, on closing
// get the width of the Form in order to persist it for use the next time the app is run.
//
// 2 options have been tried. Both cause Form_Closing to erroneously report the fully-open width.
// But if BOTH are commented-out, the re-sizing occurs and Form_Closing() reports properly the
// form's scrolled width.
// Bear in mind that Form_Closing is one of those things that can happen anytime or never. This means
// the bug is triggered by EITHER and ONLY the two options below.
// Option 1: Tried first. It sets the width fine.
//
// this.Width = picSize.Width + 40;
// Option 2: It also sets the width fine.
// I think this option causes width to change (it invokes width change, and somewhere in the
// OS's width change, the error occurs.
//this.MinimumSize = new Size(MaximumSize.Width - 1, this.Height);
//this.MinimumSize = new Size(0, 0);
}
Edit: I have new information which should help. The culprit is FormClosing(). Here's what I did: I re-sized the form in Windows until it occupied maybe 500 pixels in width. The horizontal scrollbar on my panel was showing. Then, in the FormClosing event, I added the line: Form.Show(). After that, I put a MessageBox.Show("Hi."). Sure enough, the Show() caused the form to repaint in its full, unscrolled width. It did not maintain its scroll state.
I think I have the solution and will post back after trying. Namely, I need to check Scroll values and operate on those values as well.
Edit 2: FormClosing() also re-sets HorizontalScroll.Value and VerticalScroll.Value to 0. This is a bummer! I wonder how to work around this. I also looked at e.Cancel, but there seems to be no way to take advantage of it, either. It seems e.Cancel just re-shows() the form in its unhidden state.
Sorry I cannot post the code. It would be pointless anyway. Think about it. The Windows OS handles the resizing. Not me. When the user re-sizes the form, it's all on Windows. If user re-sizes the form to 500 pixels wide, but FormClosing() reports it is 1386 pixels wide, no amount of my coding will show us anything new. This is a behavior issue. There is no code to show you how the Windows OS handles form re-sizing.
On FormClosing Event Use:
MessageBox.Show(this.Width.ToString());
You're using another Instance of your form's class, Form.Show() should not work in this event cause Dispose function is called and if you have referenced the same instance it will be disposed as well.
I've encountered an annoying problem:
When I set my form's ClientSize property to match 300*300, the size indeed does change, but it's totally not 300*300. Actually, it's not even x*x but rather x*y, since its width is greater than its height.
This is a picture of my program after setting my form's ClientSize = new Size(300, 300); and creating a black Panel inside it with size 250*250.
I measured them with photoshop and the black Panel was indeed 250*250, whereas the form's client size was more like 280*260 or so.
Why is this happening, have I understood the ClientSize property's meaning wrong?
If so, how can I get the actual "drawing area" of my form to accurately match the size I want?
Check have you set min or max size of your form.
I would like to have a form in which the controls on the form are fully visible but the form itself is invisible. If I change the form's Opacity, this makes both the form and the controls on it semi-transparent, so this doesn't work.
I can't do this by setting the form's TransparencyKey, since I have a PictureBox on the form. If the image in the PictureBox happens to contain pixels that match the TransparencyKey, they appear as openings in the form, which I don't want.
TransparencyKey is the only way to get this. Pick the right color. Color.Fuchsia has a long tradition of being the color of choice, going back to the early days of Win32 development. Assault your eye with it to see its merits.
With the caveat that I've never used it, just ran across it once, thought "neat!" and moved on...
Look into System.Drawing.Drawing2D.GraphicsPath and setting the form's Region property. I added two buttons to the basic Windows forms application:
public Form1()
{
InitializeComponent();
Rectangle r1 = new Rectangle(button1.Location, button1.Size);
Rectangle r2 = new Rectangle(button2.Location, button2.Size);
GraphicsPath gp = new GraphicsPath();
gp.AddRectangle(r1);
gp.AddRectangle(r2);
this.Region = new Region(gp);
}
I've approximated the shape of the button with a rectangle; with this code, you can see the form background color at the buttons' corners. You'll need to work out the enclosing path for each of your controls and add them to the path individually. You'll need to take into account any offset introduced by the form title bar or border style.
Update: I did some investigation and have a couple of possible approaches for the problem:
Using the GraphicsPath method, set pictureBox.Visible to False if there is no image loaded.
When you load an image into the picture box, analyze the image to get a list of all the colors in it, then randomly generate one that isn't. Set the form's BackColor and TransparencyKey properties to match this new color, Hans Passant's answer.