Form Size and Location


When a form isn't lurking in the background behind a notification icon or task bar button, it is visible in the foreground and takes up space in some location on the screen. A form's initial location is governed by the StartPosition property, which can be one of several FormStartPosition enumeration values:

enum FormStartPosition {   CenterParent = 4, // Center modeless owned forms and modal forms                     // over owner. Center modeless unowned forms over                     // currently active form   CenterScreen = 1, // Centered over the visible desktop   Manual = 0, // You use code to specify the initial start location   WindowsDefaultBounds = 3, // Windows is asked for a default location                             // and size   WindowsDefaultLocation = 2 // Windows picks a location staggered from                              // the top-left corner of the screen                              // (default) }


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.14 shows the basic size and location properties of a form.

Figure 2.14. The DesktopLocation, Location, ClientSize, and Size Properties (See Plate 3)


When the upper-left corner of a form changes, that's a move, which can be handled in either Move or LocationChanged event handlers. When the width or height of a form changes, that's a resize, which can be handled in the Resize or the SizeChanged event handler, the latter being fired after the former. [12] You can also handle ResizeBegin and ResizeEnd for more fine-grained control over resizing. Sometimes, one gesture of the mouse can cause all move and size events to happen. For example, resizing a form by dragging the upper-left corner changes the location and the size of the form.

[12] Why are there XxxChanged events for Move and 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. The two 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, you can instead lean on the DesktopLocation property:

void Form1_Load(object sender, EventArgs e) {   // Could end up under the shell's task bar   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); }


You might want to do this to ensure that your form's caption never appears underneath the shell's task bar, even if it's on the top edge, as shown in Figure 2.14.

Locations are expressed via the Point structure, the interesting parts of which are shown here:

namespace System.Drawing {    struct Point {      // Fields      static readonly Point Empty;      // Constructors      Point(int x, int y);      // Properties      bool IsEmpty { get; }      int X { get; set; }      int Y { get; set; }      // Methods      static Point Ceiling(PointF value);      void Offset(int dx, int dy);      static Point Round(PointF value);      override string ToString();      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 need to convert from a Point to a PointF object to call certain methods or set certain 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 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 (Size also has a SizeF counterpart and provides the same capabilities for conversion):

namespace System.Drawing {    struct Size {      // Fields      static readonly Size Empty;      // Constructors      Size(int width, int height);      // Properties      int Height { get; set; }      bool IsEmpty { get; }      int Width { get; set; }      // Methods      static Size Add(Size sz1, Size sz2);      static Size Ceiling(SizeF value);      static Size Round(SizeF value);      override string ToString();      static Size Truncate(SizeF value);      static Size Subtract(Size sz1, Size sz2);    } }


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 scroll bars, all of which are drawn by Windows. The area the form is responsible for is marked by ClientSize, as shown in Figure 2.14. 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 Form1_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 only 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 eventwhich is generated when the user clicks on the Help button and then clicks on a controlis passed the mouse position in screen coordinates. [13] However, to determine which control was clicked on, you must have the mouse position in client coordinates. You can convert between the two coordinate systems by using PointToScreen and PointToClient:

[13] Adding the Help button to a form is discussed later in this chapter.

void Form1_HelpRequested(object sender, HelpEventArgs e) {   // Convert screen coordinates to client coordinates   Point pt = this.PointToClient(e.MousePos);   // Look for the control that the 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

Our careful control layouts or rendering requirements often 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 and 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 Form1_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, thinking that it is a way of saying "no maximum." However, if either the Width or the Height property of the Size used to set the minimum or maximum is nonzero, then both values of that Size are used for the specified property. That sets the maximum size of our 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:

namespace System.Windows.Forms {   enum FormWindowState {     Maximized = 2,     Minimized = 1,     Normal = 0 // default   } }


By default, the WindowState property is set to Normal, that is, visible but neither maximized nor minimized. Your program can get or set this property at will to manage the state of your form.

Form Z-Order

In addition to being located in terms of x and y, forms live in a third dimension known as the z-order, the order that dictates whether one form is drawn above or below another form. Furthermore, z-order is split into two tiers. Normal windows are drawn lowest z-order to highest, front to back. On top of 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, topmost forms are always drawn on top of any normal window. Figure 2.15 illustrates this two-tiered forms z-order.

Figure 2.15. Topmost Window Z-Order in Relation to Normal Window Z-Order


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 by unchecking the Options | Always On Top setting. [14] If Task Manager were implemented using Windows Forms, it would implement this feature by toggling the TopMost property on its main form.

[14] Chris always does!




Windows Forms 2.0 Programming
Windows Forms 2.0 Programming (Microsoft .NET Development Series)
ISBN: 0321267966
EAN: 2147483647
Year: 2006
Pages: 216

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