Form Size and Location


During its lifetime, the form is likely to take up space at some location. The initial location for the form is governed by the StartPosition property, which can have one of several values from the FormStartPosition enumeration:

 enum FormStartPosition {   CenterParent,   CenterScreen,   Manual,   WindowsDefaultBounds,   WindowsDefaultLocation, //  default } 

These values have the following behavior:

  • WindowsDefaultLocation . The form's starting position will be determined by Windows , which will pick a location staggered from the upper-left corner of the screen toward the lower right in an attempt to make sure that new windows neither cover each other nor fall off the screen. The form will be shown with whatever the Size property was set to in the Designer.

  • WindowsDefaultBounds . Windows will be asked to determine a default size as well as location.

  • CenterScreen . The form will be centered on the desktop , that area not taken up by the shell taskbar and the like.

  • CenterParent . The form will be centered over the owner (or the currently active form, if there's no owner) when ShowDialog is used. If Show is used, the behavior is that of WindowsDefaultLocation.

  • Manual . Allows you to set the initial location and the size of the form without any Windows intervention.

The size and location of the form are exposed via the Size and Location properties, of type Size and Point, respectively (both from the System.Drawing namespace). As a shortcut, the properties of the size of a form are exposed directly via the Height and Width form properties, and those of the location are exposed via the Left, Right, Top, and Bottom properties. Figure 2.3 shows the basic size and location properties on a form.

Figure 2.3. The DesktopLocation, Location, ClientSize, and Size Properties

When the upper-left corner of a form changes, that's a move , which can be handled in the Move or LocationChanged event handler. When the width or height of a form changes, that's a resize , which can be handled in the Resize or SizeChanged event handler. [6] Sometimes one gesture of the mouse can cause all move and size events to happen. For example, resizing a form by dragging the top-left corner would change the location and the size of the form.

[6] Why are there two events for move and two more for resize? The XxxChanged events are so named to be consistent with data binding. The Move and Resize events are more familiar to Visual Basic programmers and are kept for their benefit. Both events are functionally equivalent.

The location of the form is in absolute screen coordinates. If you're interested in the location of the form relative to the desktop ”so that, for example, your form's caption never appears underneath the shell's taskbar ”then even if it's on the top edge, as shown in Figure 2.3, you can use the DesktopLocation property. Here's an example:

 void Form3_Load(object sender, EventArgs e) {   // Could end up under the shell's taskbar   this.Location = new Point(1, 1);  // Will always be in the desktop   this.DesktopLocation = new Point(1, 1);  // A simpler form of the preceding line   this.SetDesktopLocation(1, 1); } 

Locations are expressed via the Point structure from the System.Drawing namespace, the interesting parts of which are shown here:

 struct Point {   // Fields   public static readonly Point Empty;   // Constructors   public Point(int x, int y);   // Properties   public bool IsEmpty { get; }   public int X { get; set; }   public int Y { get; set; }   // Methods   public static Point Ceiling(PointF value);   public void Offset(int dx, int dy);   public static Point Round(PointF value);   public virtual string ToString();   public static Point Truncate(PointF value); } 

The PointF structure is very similar to the Point structure, but PointF is used in drawing applications when more precise floating point measurements are required. Sometimes you'll need to convert from a Point to a PointF object to be able to call some methods or set some properties. You can do so without any extra effort:

 // Can convert directly from Point to PointF Point pt1 = new Point(10, 20);  PointF pt2 = pt1; // Yields PointF(10.0f, 20.0f)  

However, because floating point numbers contain extra precision that will be lost in the conversion, you'll need to be explicit about how to convert from a PointF to a Point object using the static Truncate, Round, and Ceiling methods of the Point class:

 // Need to be explicit when converting from a PointF to a Point PointF pt1 = new PointF(1.2f, 1.8f);  Point pt2 = Point.Truncate(pt1); // Yields Point(1, 1);   Point pt3 = Point.Round(pt1); // Yields Point(1, 2);   Point pt4 = Point.Ceiling(pt1); // Yields Point(2, 2);  

The size of a window is reflected in the Size property, also from System.Drawing (Size also has a SizeF counterpart and provides the same capabilities for conversion):

 struct Size {   // Fields   public static readonly Size Empty;   // Constructors   public Size(int width, int height);   // Properties   public int Height { get; set; }   public bool IsEmpty { get; }   public int Width { get; set; }   // Methods   public static Size Ceiling(SizeF value);   public virtual bool Equals(object obj);   public static Size Round(SizeF value);   public virtual string ToString();   public static Size Truncate(SizeF value); } 

Although the Size property represents the size of the entire window, a form isn't responsible for rendering all of its contents. The form can have edges, a caption, and scrollbars, all of which are drawn by Windows. The part that the form is responsible for is the ClientSize, as shown in Figure 2.3. It's useful to save the ClientSize property between application sessions because it's independent of the current adornment settings the user has established. Similarly, resizing the form to make sure there's enough space to render your form's state is often related to the client area of the form and not to the size of the form as a whole:

 void Form2_Load(object sender, EventArgs e) {  this.ClientSize = new Size(100, 100); // Calls SetClientSizeCore   this.SetClientSizeCore(100, 100);  } 

A Rectangle combines a Point and a Size and also has a RectangleF counterpart. Structure RectangleThe Bounds property gives a rectangle of the form relative to the screen, whereas the DesktopBounds property is a rectangle relative to the desktop for top-level windows (and not for child windows). The ClientRectangle property is a rectangle relative to the form itself, describing the client area of the form. Of the three, ClientRectangle tends to be the most used, if for no other reason than to describe which area to use when drawing:

 void Form1_Paint(object sender, PaintEventArgs e) {   Graphics g = e.Graphics;  g.FillEllipse(Brushes.Yellow, this.ClientRectangle);   g.DrawEllipse(Pens.DarkBlue, this.ClientRectangle);  } 

Also, it's sometimes necessary to convert a point that's relative to the screen to one that's relative to the client or vice versa. For example, the HelpRequest event, generated when the user clicks on the Help button and then clicks on a control, is sent to the handler in screen coordinates. However, to determine which control was clicked on requires the mouse position in client coordinates. You can convert between the two coordinate systems by using PointToScreen and PointToClient:

 void Form1_HelpRequested(object sender, HelpEventArgs e) {  // Convert screen coordinates to client coordinates   Point pt = this.PointToClient(e.MousePos);  // Look for control user clicked on   foreach( Control control in this.Controls ) {     if( control.Bounds.Contains(pt) ) {       Control controlNeedingHelp = control;       ...       break;     }   } } 

To translate an entire rectangle between screen and client coordinates, you can also use RectangleToScreen and RectangleToClient.

Restricting Form Size

Often our careful control layouts or rendering requirements dictate a certain minimum amount of space. Less often, our forms can't be made to take advantage of more than a certain amount of space (although anchoring and docking, described later, should help with that). Either way, it's possible to set a form's minimum or maximum size via the MinimumSize and MaximumSize properties, respectively. The following example sets a fixed height of 200, a minimum width of 300, and a maximum width so large as to be unlimited:

 void Form2_Load(object sender, EventArgs e) {   // min width is 300, min height is 200  this.MinimumSize = new Size(300, 200);  // max width is unlimited, max height is 200  this.MaximumSize = new Size(int.MaxValue, 200);  } 

Notice that the code uses the maximum value of an integer to specify that there is no effective maximum width on the form. You may be tempted to use zero for this value instead, but if either the Width or the Height property of the Size used to set the minimum or maximum is nonzero, then both values are used. This would set the maximum size of your form to zero instead of "no maximum."

One other setting that governs a form's size and location is WindowState, which can be one of the values from the FormWindowState enumeration:

 enum FormWindowState {   Maximized,   Minimized,   Normal, // Form.WindowState default value } 

By default, the WindowState is set to Normal, which means that it's not maximized to take up the entire desktop, nor is it minimized so that none of the form shows at all and only a button is shown in the taskbar. Your program can get or set this property at will to manage the state of your form. However, if you're saving the size and location of your form between application sessions, you may decide to reset the WindowState to Normal so that the size being saved represents the size in the normal state and not the minimized or maximized size:

 void Form2_Closing(object sender, CancelEventArgs e) {   // Capture the properties before the form is gone  FormWindowState state = this.WindowState;   this.WindowState = FormWindowState.Normal;   Point location = this.Location;   Size size = this.ClientSize;  // ... save state, location and size properties between sessions ...   // ... restore properties in Load event ... } 

For a description of how and where to keep application settings between sessions, read Chapter 11: Applications and Settings.

Z-Order

Another location property that you may let your users influence or keep between sessions is the TopLevel property. So far I've discussed location in terms of x and y. However, as the user switches between windows, Windows also juggles the z-order , which dictates which windows are drawn on top of one another.

Furthermore, z-order is split into two tiers. Normal windows are drawn lowest z-order to highest, front to back. Above all the normal windows are the topmost windows, which are also drawn relative to each other, lowest z-order to highest, but no matter the z-order, are always drawn on top of any normal window. For an example of a topmost window, pressing Ctrl+Shift+ESC under many versions of Windows will bring up Task Manager. By default, it's a topmost window and always draws on top of normal windows, whether or not it is the active window. You can change this behavior (I always do) by unchecking the Options Always On Top setting. If Task Manager were implemented using WinForms, it would implement this feature by toggling the TopMost property on its main form.



Windows Forms Programming in C#
Windows Forms Programming in C#
ISBN: 0321116208
EAN: 2147483647
Year: 2003
Pages: 136
Authors: Chris Sells

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net