User:Foxall/06

Ka Wiktionary

Hour 6. Building Forms�Part II[wax ka badal]

A form is just a canvas, and although you can tailor a form by setting its properties, you'll need to add controls to it to make it functional. In the previous hour, you learned how to add forms to a project, how to set basic form properties, and how to show and hide forms. In this hour, you'll learn all about adding controls to a form, including arranging and aligning controls to create a pleasing and functional interface. You also learn how to create advanced multiple document interfaces (MDIs), as employed in applications such as Word. After you complete the material in this hour, you'll be ready to learn the details about the various controls available in C#.

The highlights of this hour include the following:

  • [file:///C:/Documents%20and%20Settings/dani/Asztal/c%23in24h/ch06lev1sec1.htm#ch06lev2sec1 Adding controls to a form]
  • [file:///C:/Documents%20and%20Settings/dani/Asztal/c%23in24h/ch06lev1sec1.htm#ch06lev2sec2 Positioning, aligning, sizing, spacing, and anchoring controls]
  • [file:///C:/Documents%20and%20Settings/dani/Asztal/c%23in24h/ch06lev1sec1.htm#ch06lev2sec3 Creating intelligent tab orders]
  • [file:///C:/Documents%20and%20Settings/dani/Asztal/c%23in24h/ch06lev1sec1.htm#ch06lev2sec4 Adjusting the z-order of controls]
  • [file:///C:/Documents%20and%20Settings/dani/Asztal/c%23in24h/ch06lev1sec3.htm#ch06lev1sec3 Creating transparent forms]
  • [file:///C:/Documents%20and%20Settings/dani/Asztal/c%23in24h/ch06lev1sec2.htm#ch06lev1sec2 Creating forms that always float over other forms]
  • [file:///C:/Documents%20and%20Settings/dani/Asztal/c%23in24h/ch06lev1sec5.htm#ch06lev1sec5 Creating multiple-document interfaces]

Working with Controls[wax ka badal]

As discussed earlier, controls are the objects that you place on a form for users to interact with. If you've followed the examples in the previous hours, you've already added controls to a form. However, you'll be adding a lot of controls to forms, and it's important for you to understand all aspects of the process. Following the drill-down in this hour, the next two hours will teach you the ins and outs of the very cool controls provided by C#.

 Adding Controls to a Form 

All the controls that you can add to a form can be found in the toolbox. By default, the toolbox appears as a docked window on the left side of the design environment. This location is useful when you're only occasionally adding controls to forms. However, when doing serious form-design work, I find it best to dock the toolbox to the right side of the design environment, where it doesn't overlap so much (if at all) onto the form with which you're working.

graphics/bookpencil.gif Remember that before you can undock a toolbar to move it to a new location, you must make sure it isn't set to Auto Hide.

The buttons on the toolbox are actually considered tabs because clicking one of them displays a specific page of controls. For most of your design, you'll use the controls on the Win Forms tab. However, as your skills progress, you may find yourself using more complex and highly specialized controls found on the other tabs.

You can add a control to a form in three ways, and you're now going to perform all three methods. Create a new Windows Application called Adding Controls. Change the name of the default form to fclsAddingControls and set its Text property to Adding Controls. Update the main entry point in the Main() function to reflect the new class name by clicking the View Code button on the Solution Explorer toolbar and then locating the reference to Form1 and replacing it with fclsAddingControls. Click Form1.cs [Design] to return to the form designer.

The easiest way to add a control to a form is to double-click the control in the toolbox. Try this now: display the toolbox and double-click the TextBox tool. C# creates a new text box in the upper-left corner of the form. Of course, you're free to move and size the text box as you please. Nevertheless, when you double-click a control in the toolbox, C# always creates the control in the upper-left corner, with the default size for the type of control you're adding.

If you want a little more authority over where the new control is placed, you can drag a control to the form. Try this now: display the toolbox and then click the Button control and drag it to the form. When the cursor is roughly where you want the button created, release the mouse button.

The last and most precise method of placing a control on a form is to "draw" the control on a form. Display the toolbox now and click the ListBox tool once to select it. Next, move the pointer to where you want the upper-left corner of the list box to appear and then click and hold the mouse button. Drag the pointer to where you want the bottom-right corner of the list box to be and release the button. The list box is created with its dimensions set to the rectangle you drew on the form. This is by far the most precise method of adding controls to a form.

graphics/bulb.gif If you prefer to draw controls on your forms by clicking and dragging, I strongly suggest that you dock the toolbox to the right or bottom edge of the design environment or float it. The toolbox tends to interfere with drawing controls when it's docked to the left edge, because it obscures part of the form.

It's important to note that the very first item on the Windows Forms tab, titled Pointer, isn't actually a control. When the pointer item is selected, the design environment is placed in Select mode rather than in a mode to create a new control. With the pointer selected, you can select a control simply by clicking it, displaying all its properties in the Properties window. This is the default behavior of the development environment.

 Manipulating Controls 

Getting controls on a form is the easy part. Arranging them so that they create an intuitive and attractive interface is the challenge. Interface possibilities are nearly endless, so I can't tell you how to design any given interface. However, I can show you the techniques to move, size, and arrange controls so that they appear the way you want them to. By mastering these techniques, you'll be much faster at building interfaces, freeing your time for writing the code that makes things happen.

 Using the Grid (Size and Snap) 

When you first install C#, all forms appear with a grid of dots on them. When you draw or move controls on a form with a grid, the coordinates of the control automatically snap to the nearest grid coordinate. This offers some precision when adjusting the size and location of controls. In practical use, I often find the grid to be only slightly helpful because the size or location you want to specify often doesn't fit neatly with the grid locations. You can, however, control the granularity and even the visibility of the grid, and I suggest you do both.

You're now going to assign a higher level of granularity to the grid (the space between the grid points will be smaller). I find that this helps with design, without causing edges to snap to unwanted places.

To adjust the granularity of the grid on a form, you change the GridSize property (or the Width and Height subproperties of the GridSize property). Setting the Width or Height of the grid to a smaller number creates a smaller grid, which allows for finer control over sizing and placement, whereas using larger values creates a much larger grid and offers less control. With a larger grid, you'll find that edges snap to grid points much easier and at larger increments, making it impossible to fine-tune the size or position of a control. Change the GridSize property of your form now to 4,4. Notice that a lot more grid dots appear (see [file:///C:/Documents%20and%20Settings/dani/Asztal/c%23in24h/06.htm#ch06fig01 Figure 6.1]).

Figure 6.1. Grids can be distracting.

graphics/06fig01.jpg

Try dragging the controls on your form or dragging their edges to size them. Notice that you have more control over the placement with the finer grid. Try changing the GridSize to a set of higher numbers, such as 25,25 and see what happens. When you're finished experimenting, change the GridSize values back to 4,4.

An unfortunate side effect of a smaller grid is that the grid can become quite distracting. Again, you'll decide what you like best, but I generally turn grids off on my form. You do this by setting the DrawGrid property of the form to false. Try hiding the grid of your form now.

graphics/bookpencil.gif This property determines only whether the grid is drawn, not whether it's active; grids are always active, regardless of whether they're visible.
Selecting a Group of Controls 

As your skills grow, you'll find your forms becoming increasingly complex. Some forms may contain dozens, or even hundreds, of controls. C# has a set of features that makes it easy to align groups of controls.

Create a new Windows Application titled Align Controls. Change the name of the default form to fclsAlignControls and set its Text property to Control Alignment Example. Next, update the main entry point in the Main() function to reflect the new class name by clicking the View Code button on the Solution Explorer toolbar and then locating the reference to Form1 and replacing it with fclsAlignControls. Click Form1.cs [Design] to return to the form designer.

Double-click the TextBox tool in the toolbox to add a text box to the form. Set its properties as follows:

Property Value
Name txt1
Location 20, 20
Multiline True
Size 100, 30
Text txt1
graphics/bookpencil.gif If you don't set the Multiline property of a text box to true, C# ignores the Height setting (the second value of the Size property) and instead, keeps the height at the standard height for a single-line text box.

Use the same technique (double-click the TextBox item in the toolbox) to add two more text boxes to the form. Set their properties as follows:

Text Box 2:

Property Value
Name txt2
Location 90, 80
Multiline True
Size 50, 50
Text txt2

Text Box 3:

Property Value
Name txt3
Location 140, 200
Multiline True
Size 100, 60
Text txt3

Your form should now look like the one in [file:///C:/Documents%20and%20Settings/dani/Asztal/c%23in24h/06.htm#ch06fig02 Figure 6.2]. Save the project now by clicking the Save All button on the toolbar.

Figure 6.2. It's easy to align and size controls as a group.

graphics/06fig02.jpg

By default, clicking a control on a form selects it while deselecting any controls that were previously selected. To perform actions on more than one control, you need to select a group of controls. You can do so in one of two ways, the first of which is to lasso the controls. To lasso a group of controls, you first click and drag the mouse pointer anywhere on the form. As you drag the mouse, a rectangle is drawn on the form. When you release the mouse button, all controls intersected by the rectangle become selected. Note that you don't have to completely surround a control with the lasso (also called a marquee), you only have to intersect part of the control to select it. Try this now: click somewhere in the upper-right corner of the form and drag the pointer toward the bottom of the form without releasing the button (see [file:///C:/Documents%20and%20Settings/dani/Asztal/c%23in24h/06.htm#ch06fig03 Figure 6.3]). When the rectangle has surrounded or intersected all the controls, release the button and the controls will be selected (see [file:///C:/Documents%20and%20Settings/dani/Asztal/c%23in24h/06.htm#ch06fig04 Figure 6.4]).

Figure 6.3. Click and drag to create a selection rectangle.

graphics/06fig03.jpg

Figure 6.4. All selected controls appear with a hatched border and sizing handles.

graphics/06fig04.jpg

When a control is selected, it has a hatched border and a number of sizing handles (the rectangles in the hatched border at the corners and midpoints of the control). Pay careful attention to the sizing handles. The control with the black-centered sizing handles is the active control in the selected group. When you use C#'s tools, such as the alignment and formatting features, to work on a group of selected controls, the values of the active control are used. For example, if you were to align the left side of the selected controls shown in [file:///C:/Documents%20and%20Settings/dani/Asztal/c%23in24h/06.htm#ch06fig04 Figure 6.4], each of the controls would have its Left property value set to that of the active control. When you use the lasso technique to select a group of controls, you really don't have much authority over which control C# makes the active control. In this example, you want to align all controls to the control at the top, so you'll have to use a different technique to select the controls. Deselect all the controls now by clicking anywhere on the form (other than on a control).

graphics/bookpencil.gif When the sizing handle of an active control is colored white, you can click and drag the handle to alter the size of the control. Not all sizing handles are movable at all times. For example, before you set the Multiline property of a text box to true, C# won't allow you to change the height of the text box, so only the sizing handles at the left and right edges are movable and therefore are colored white.

The second technique for selecting multiple controls is to use the Shift or Ctrl key; this method is much like selecting multiple files in Windows Explorer. Click the bottom control (txt3) now to select it. Notice that its sizing handles are outlined in black; because it's the only control selected, it's automatically made the active control. Now hold down the Shift key and click the center control (txt2); txt2 and txt3 are now selected. However, txt2 is the active control (when multiple controls are selected, the active control has black-filled sizing handles rather than white). When you add a control to a group of selected controls, the newly selected control is always made the active control. Finally, with the Shift key still pressed, click txt1 to add it to the group of selected controls. All the controls should now be selected and txt1 should be the active control.

graphics/bookpencil.gif Clicking a selected control while Shift is held down deselects the control.

You can combine the two selection techniques when needed. For instance, you could first lasso all controls to select them. If the active control isn't the one you want it to be, you could hold the Shift key down and click the control you want made active, thereby deselecting it. Clicking the control a second time while still holding down the Shift key would again select the control. Because the control would then be the last control added to the selected group, it would be made active.

graphics/bookpencil.gif If you must click the same control twice, such as to deselect and then reselect, do so slowly. If you click too fast, C# interprets your actions as a double-click, and it creates a new event handler for the control.
Aligning Controls 

Now that you've selected all three controls, open C#'s Format menu (see [file:///C:/Documents%20and%20Settings/dani/Asztal/c%23in24h/06.htm#ch06fig05 Figure 6.5]). The Format menu has a number of submenus containing functions to align, size, and format groups of controls. Open the Align submenu now to see the available options (see [file:///C:/Documents%20and%20Settings/dani/Asztal/c%23in24h/06.htm#ch06fig06 Figure 6.6]).

Figure 6.5. Use the Format menu to quickly whip an interface into shape.

graphics/06fig05.jpg

Figure 6.6. The Align menu makes it easy to align an edge of a group of controls.

graphics/06fig06.jpg

The top three items on the Align menu are used to align the selected controls horizontally, and the middle three items align the selected controls vertically. The last item, To Grid, will snap the corners of all the selected controls to the nearest grid points. Choose Align Lefts now, and C# aligns the left edges of the selected controls. Notice how the Left edge of the active control is used as the baseline for the alignment (see [file:///C:/Documents%20and%20Settings/dani/Asztal/c%23in24h/06.htm#ch06fig07 Figure 6.7]).

Figure 6.7. The property values of the active control are always used as the baseline values.

graphics/06fig07.jpg

 Making Controls the Same Size 

In addition to aligning controls, you can als o make all selected controls the same size�Height, Width, or Both. To do this, use the Make Same Size submenu on the Format menu (see [file:///C:/Documents%20and%20Settings/dani/Asztal/c%23in24h/06.htm#ch06fig08 Figure 6.8]). Make all your controls the same size now by choosing Both from the Make Same Size menu. As with the Align function, the values of the active control are used as the baseline values.

Figure 6.8. Use this menu to quickly make a group of controls the same size.

graphics/06fig08.jpg

 Evenly Spacing a Group of Controls 

As many a salesman has said, "…and that's not all!" You can also make the spacing between controls uniform using the Format menu. Try this now: open the Vertical Spacing submenu of the Format menu and then choose Make Equal. All the controls are now evenly spaced. Next, choose Decrease from the Vertical Spacing menu and notice how the spacing between the controls decreases slightly. You can also increase the vertical spacing or completely remove vertical space from between controls using this menu. To perform the same functions on the horizontal spacing between controls, use the Horizontal Spacing submenu of the Format menu. Save your project now by clicking the Save All button on the toolbar.

 Setting Property Values for a Group of Controls 

You can change a property value in the Properties window when multiple controls are selected, and the change will be made to all controls. To do this, make sure all three controls are still selected and then display the Properties window.

When a group of controls is selected, the Properties window appears with some modifications (see [file:///C:/Documents%20and%20Settings/dani/Asztal/c%23in24h/06.htm#ch06fig09 Figure 6.9]):

  • No Name property is shown. This occurs because it's not allowable to have two controls with the same name, so C# won't even let you try.
  • Only properties shared by all controls are displayed. If you had selected a label control and a text box, for example, only the properties shared by both control types would appear.
  • For properties in which the values of the selected controls differ (such as the Location property in this example), the value is left empty in the Properties window.
Figure 6.9. You can view the property values of many controls at once, with some caveats.

graphics/06fig09.jpg

Entering a value in any property changes the corresponding property for all selected controls. To see how this works, change the BackColor property to a shade of yellow, and you'll see that all controls have their BackColor set to yellow.

 Anchoring and Autosizing Controls 

One of my favorite additions to the forms engine in C# is the capability to anchor controls to one or more edges of a form so that controls can now size themselves appropriately when the user sizes the form. In the past, you had to use a (usually cumbersome) third-party component or resort to writing code in the form Resize event to get this behavior, but it's an intrinsic capability of C#'s form engine.

The default behavior is that controls are docked to the top and left edges. What if you want a control to always appear in the lower-left corner of a form? This is precisely what the Anchor property is designed to handle.

The easiest way to understand how anchoring works is to do it.

  1. Create a new Windows Application called Anchoring Example.
  2. Change the name of the default form to fclsAnchoringExample and set the form's Text property to Anchoring Example.
  3. Change the main entry point to reflect the new form name.
  4. Add a new button to the form and name it btnAnchor.
  5. Run the project by pressing F5.
  6. Click and drag the border of the form to change its size.

Notice that no matter what size you change the form to, the button stays in the upper-left corner of the form (see [file:///C:/Documents%20and%20Settings/dani/Asztal/c%23in24h/06.htm#ch06fig10 Figure 6.10]).

Figure 6.10. By default, controls are anchored to the upper-left corner of the form.

graphics/06fig10.jpg

Stop the running project now by choosing Stop Debugging from the Debug menu. Click the button on the form to select it, click the Anchor property, and then click the drop-down arrow that is displayed. You'll see a drop-down box that is unique to the Anchor property (see [file:///C:/Documents%20and%20Settings/dani/Asztal/c%23in24h/06.htm#ch06fig11 Figure 6.11]).

Figure 6.11. You use this unique drop-down box to set the Anchor property of a control.

graphics/06fig11.jpg

The gray square in the center of the drop-down box represents the control whose property you are setting. The thin rectangles on the top, bottom, left, and right represent the possible edges to which you can dock the control; if a rectangle is filled in, the edge of the control facing that rectangle is docked to that edge of the form.

  1. Click the rectangle above the control so that it's no longer filled in, and then click the rectangle to the right of the control so that it is filled in.
  2. Click any other property to close the drop-down box. The Anchor property should now read LeftRight.
  3. Press F5 to run the project, and then drag an edge of the form to make it larger.

Pretty odd, huh? What C# has done is anchored the left edge of the button to the left edge of the form and anchored the right edge of the button to the right edge of the form (see [file:///C:/Documents%20and%20Settings/dani/Asztal/c%23in24h/06.htm#ch06fig12 Figure 6.12]). Really, anchoring means keeping an edge of the control a constant relative distance from an edge of the form, and it's an unbelievably powerful tool for building interfaces. Now you can make forms that users can resize, but you write little or no code to make the interface adjust accordingly. One caveat: depending on their anchor settings, controls may disappear if the form is shrunk quite small.

Figure 6.12. Anchoring is a powerful feature for creating adaptable forms.

graphics/06fig12.jpg

 Creating a Tab Order 

Tab order is something that is often (emphasis on often) overlooked. You're probably familiar with tab order as a user, although you may not realize it. When you press Tab while on a form, the focus moves from the current control to the next control in the tab order. This allows easy keyboard navigation on forms. The tab order for controls on a form is determined by the TabIndex properties of the controls. The control with the TabIndex value of 0 is the first control that receives the focus when the form is shown. When you press Tab, the control with the TabIndex of 1 receives the focus. When you add a control to a form, C# assigns the next available TabIndex value. Each control has a unique TabIndex value, and TabIndex values are always used in ascending order.

If the tab order isn't set correctly for a form, pressing Tab will cause the focus to jump from control to control in no apparent order. This really isn't a way to impress users.

The forms engine in C# has a far superior way to set the tab order for controls on a form. Create a new Windows Application named Tab Order, change the name of the default form to fclsTabOrder, set the Text property of the form to Tab Order Example and update the entry point with the fclsTabOrder reference.

Add three text box controls to the form and set their properties as follows:

Property Value Property Value Property Value
Name TextBox1 Name TextBox2 Name TextBox37
Location 90,120 Location 90,50 Location 90,190

Save the project by clicking the Save All button on the toolbar and then press F5 to run the project. Notice how the middle text box is the one with the focus. This is because it's the first one you added to the form and therefore has a TabIndex value of 0. Press Tab to move to the next control in the tab order (the top control); then press Tab once more and the focus jumps to the bottom control. Obviously, this isn't productive. Stop the project now by choosing Stop Debugging from the Debug menu (or simply close the form).

You're now going to set the tab order via the new visual method. Choose Tab Order from the View menu; notice how C# superimposes a set of numbers over the controls (see [file:///C:/Documents%20and%20Settings/dani/Asztal/c%23in24h/06.htm#ch06fig13 Figure 6.13]). The number on a control indicates its TabIndex property value. Now it's very easy to see that the tab order is incorrect. Click the top control. Notice how the number over the control changes to 0. Click the middle control and you'll see its number change to 1. As you click controls, C# assigns the next highest number to the clicked control. Choose Tab Order from the View menu again to take the form out of Tab Order mode. Run the project again and you'll see that the top control is the first to get the focus, and pressing Tab now moves the focus logically.

Figure 6.13. The numbers over each control indicate the control's TabIndex.

graphics/06fig13.jpg

graphics/bookpencil.gif To programmatically move the focus via the tab order, use the SelectNextControl() method of a control or a form.

To remove a control from the tab sequence, set its TabStop property to false. When a control's TabStop property is set to false, users can still select the control with the mouse, but they can't enter the control using the Tab key. You should still set the TabIndex property to a logical value so that if the control receives the focus (such as by being clicked), pressing Tab will move the focus to the next logical control.

 Layering Controls (Z-Order) 

Tab order and visual alignment are key elements for effectively placing controls on forms. However, these two elements address control placement in only two dimensions�the x,y axis. At times, you may need to have controls overlap, although it's rare that you'll need to do so. Whenever two controls overlap, whichever control is added to the form most recently appears on top of the other (see [file:///C:/Documents%20and%20Settings/dani/Asztal/c%23in24h/06.htm#ch06fig14 Figure 6.14]). You can control the ordering of controls using the Order submenu of the Format menu (see [file:///C:/Documents%20and%20Settings/dani/Asztal/c%23in24h/06.htm#ch06fig15 Figure 6.15]).

Figure 6.14. Controls can overlap.

graphics/06fig14.jpg

Figure 6.15. The Order menu is used to adjust the layering order of overlapping controls.

graphics/06fig15.jpg

To send a control backward in the layering order, click it once to select it and then choose Send to Back from the Order menu. To bring the control forward in the layering order, select the control and choose Bring to Front from the Order menu.

graphics/bulb.gif You can accomplish the same thing in C# code by invoking the BringToFront or SendToBack methods of a control.
>

Creating TopMost Windows

As you're probably aware, when you click a window it usually comes to the foreground and all other windows appear behind it. At times, you may want a window to stay on top of other windows, regardless of whether it's the current window (that is, it has the focus). An example of this is the Find window in C# and other applications such as Word. Regardless of which window has the focus, the Find form always appears floating over all other windows. Such a window is created by setting the form's TopMost property to true. Not exactly rocket science. However, that's the point; often a simple property change or method call is all it takes to accomplish what may otherwise seem to be a difficult task.

>

Creating Transparent Forms

A new property of forms that I think is very cool, yet I still can't come up with a reason to use it in a production application, is the Opacity property. This property controls the opaqueness of the form as well as all controls on the form. The default Opacity value of 100% means that the form and its controls are completely opaque (solid), whereas a value of 0% creates a completely transparent form (no real point in that). A value of 50% then, creates a form that is between solid and invisible (see [file:///C:/Documents%20and%20Settings/dani/Asztal/c%23in24h/06.htm#ch06fig16 Figure 6.16]). I suppose you could write a loop that takes the Opaque property from 100% to 0% to fade out the form. Other than that, I don't know where to take advantage of this technique. But ain't it cool?

graphics/06fig16.jpg

[file:///C:/Documents%20and%20Settings/dani/Asztal/c%23in24h/ch06lev1sec2.htm Previous Section] [file:///C:/Documents%20and%20Settings/dani/Asztal/c%23in24h/ch06lev1sec4.htm Next Section]
[file:///C:/Documents%20and%20Settings/dani/Asztal/c%23in24h/06.htm#toppage ]

Creating Scrollable Forms

A scrollable form is a form that can display scrollbars when its contents are larger than the physical size of the form. Not only is this a cool and necessary feature, it's also trivial to implement in your own applications.

The scrolling behavior of a form is determined by the following three properties:

Property Description
AutoScroll This property determines whether scrollbars will ever appear on a form.
AutoScrollMinSize The minimum size of the scroll region (area). If the size of the form is adjusted so that the client area of the form (the area of the form not counting borders and title bar) is smaller than the AutoScrollMinSize, scrollbars will appear.
AutoScrollMargin This property determines the margin given around controls during scrolling. This essentially determines how far past the edge of the outermost controls you can scroll.

Again, it's easiest to understand this concept by doing it. Create a new Windows Application named AutoScroll Example, rename the default form to fclsAutoScroll, set the text of the form to AutoScroll Example, and update the entry point in Main().

Add a new Button control to the form by double-clicking the Button tool on the toolbox. Set the button's properties as follows:

Property Value
Name btnTest
Location 110,120
Text Test

Save the project and press F5 to run it. Drag the borders of the control to make it larger and smaller. Notice that no matter how small you make the form, no scrollbars appear. This makes it possible to have controls on the form that are only partially visible or that can't be seen at all (see [file:///C:/Documents%20and%20Settings/dani/Asztal/c%23in24h/06.htm#ch06fig17 Figure 6.17]).

Figure 6.17. Without scrollbars, it's possible to have controls that can't be seen.

graphics/06fig17.jpg

Stop the project now by choosing Stop Debugging from the Debug menu or by closing the form. Change the AutoScroll property of the form to true. At this point you still won't get scrollbars, because you need to adjust at least one of the other scroll properties. Change the AutoScrollMargin property to 50,50 and run the project once more. Make the form smaller by dragging a border or a corner, and you'll see scrollbars appear (see [file:///C:/Documents%20and%20Settings/dani/Asztal/c%23in24h/06.htm#ch06fig18 Figure 6.18]). The AutoScrollMargin property creates a virtual margin (in pixels) around all the outermost controls on the form. If the form is sized to within the margin area of a control, scrollbars automatically appear.

Figure 6.18. Scrollbars allow the user to view all parts of the form without needing to change the form's size.

graphics/06fig18.jpg

The final property that affects scrolling is the AutoScrollMinSize. Use the AutoScrollMinSize property to create a fixed-size scrolling region. If the form is ever sized such that the visible area of the form is smaller than the scrolling region defined by AutoScrollMinSize, scrollbars appear.

Creating MDI Forms 

All the projects you've created so far have been single-document interface (SDI) projects. In SDI programs, every form in the application is a peer of all other forms; no intrinsic hierarchy exists between forms. C# also lets you create multiple-document interface (MDI) programs. A MDI program contains one parent window (also called a container) and one or more child windows. A classic example of a MDI program is Microsoft Word 95 (200 behaves slightly different, depending on how it's set up). When you run Word 97, a single parent window appears. Within this parent window, you can open any number of documents, which appear in child windows. In a MDI program, all child windows share the same toolbar and menu bar, which appears on the parent window. One restriction of child windows is that they can exist only within the confines of the parent window. [file:///C:/Documents%20and%20Settings/dani/Asztal/c%23in24h/06.htm#ch06fig19 Figure 6.19] shows an example of Word running with a number of child document windows open.

Figure 6.19. MDI applications consist of a single parent window and one or more child windows.

graphics/06fig19.gof

graphics/bookpencil.gif MDI applications can have any number of normal windows (dialog boxes, for example) in addition to child windows.

You're now going to create a simple MDI project. Create a new Windows Application named MDI Example. Change the name of the default form to fclsMDIParent, change its Text property to MDI Parent, update the entry point, and change its IsMdiContainer property to true (If you don't set the IsMdiContainer property to true, this example won't work). The first thing you'll notice is that C# changed the client area to a dark gray and gave it a sunken appearance. This is the standard appearance for MDI parent windows, and all visible child windows appear in this area.

Create a new form by choosing Add Windows Form from the Project menu. Name the form fclsChild1.cs and change its Text property to Child 1. Add a third form to the project in the same way. Name it fclsChild2.cs and set its Text property to Child 2. Any form can be a child form (except, of course, a MDI parent form). To make a form a child form, you set its MDIParent property to a form that is defined as a MDI container.

Make sure the fclsMDIParent parent form is visible in the form designer. If it's not, you can display it by double-clicking it in the Solution Explorer. Next, double-click the form to access its default event�the Load event. Enter the following code:

fclsChild1 objChild = new fclsChild1();
objChild.MdiParent = this;
objChild.Show();

By now, you should know what this code does. The first statement creates a new object variable of type fclsChild1 and initializes it to hold a new instance of a form. The last statement simply shows the form. What we're interested in here is the middle statement. It sets the MdiParent property of the form to the current form (this always references the current object), which is a MDI parent form because its IsMdiContainer property is set to true. When the new form is shown, it's shown as a MDI child. Save your work and then press F5 to run the project. Notice how the child form appears on the client area of the parent form. If you size the parent form so that one or more child windows can't fully be displayed, scrollbars appear (see [file:///C:/Documents%20and%20Settings/dani/Asztal/c%23in24h/06.htm#ch06fig20 Figure 6.20]). If you were to remove the statement that set the MdiParent property, the form would simply appear floating over the parent form and would not be bound by the confines of the parent (it wouldn't be a child window).

Figure 6.20. Child forms appear only within the confines of the parent form.

graphics/06fig20.jpg

Stop the project by choosing Stop Debugging from the Debug menu. Display the Solution Explorer and double-click the fclsChild1 form in its designer to display it in the designer. Add a button to the form and set its properties as follows:

Property Value
Name btnShowChild2
Location 105,100
Size 85,23
Text Show Child 2

Double-click the button to access its Click event, and then add the following code:

fclsChild2 objChild = new fclsChild2();
objChild.MdiParent = this.MdiParent;
objChild.Show();

This code shows the second child form. Note that two differences exist between this code and the code you entered earlier. First, the objChild variable creates a new instance of the fclsChild2 form rather than the fclsChild1 form. The second difference is how the parent is set. Because the child form is not a parent form, you can't simply set the second child's MdiParent property to this, because this doesn't refer to a parent form. However, you know that this.MdiParent references the parent form because this is precisely the property you set to make the form a child in the first place. Therefore, you can simply pass the parent of the first child to the second child, and they'll both be children of the same form.

Press F5 to run the project now. You'll see the button on the child form, so go ahead and click it (if you don't see the button, you may have mistakenly added it to the second child form). When you click the button, the second child form appears. Notice how this is also bound by the constraints of the parent form (see [file:///C:/Documents%20and%20Settings/dani/Asztal/c%23in24h/06.htm#ch06fig21 Figure 6.21]).

Figure 6.21. Child forms are peers with one another.

graphics/06fig21.jpg

graphics/bookpencil.gif The MDI parent form has an ActiveMdiChild property, which you can use to get a reference to the currently active child window.
graphics/bookpencil.gif To make the parent form larger when the project is first run, you set the Height and Width properties of the form either at design time or at runtime in the Load event of the form.

One thing about forms that is important to note is that you can create as many instances of a form as you desire. For instance, you could change the code in the button to create a new instance of fclsChild1. The form that would be created would be the same as theform that created it, complete with a button to create yet another instance. Although you probably won't apply this technique because you're just getting started with C#, you may find it quite useful in the future. For instance, if you wanted to create a text editor, you might define the text entry portion as one form but create multiple instances of the form as new text files are opened, much like Word does with documents.

Setting the Startup Object 

The Startup object in Windows Applications is, by default, the first form added to the project. This also happens to be the form that C# creates automatically when you create the new Windows Application project. Although the Startup object of a project was discussed briefly in a previous hour, it's worth mentioning here as well. Every project must have a Startup object as the entry point to the program.

The class that contains the Main() method that you want called as the entry point of the application is determined by the Startup Object property. You can change the Startup object by right-clicking the project name in the Solution Explorer and choosing Properties. The Startup Object property appears on the first property page that displays (see [file:///C:/Documents%20and%20Settings/dani/Asztal/c%23in24h/06.htm#ch06fig22 Figure 6.22]).

Figure 6.22. The Startup Object property determines the first class that gets initialized and executed.

graphics/06fig22.jpg

graphics/bookpencil.gif The setting of the Startup Object property isn't required if only one Main() method exists in the project.

If MDI forms still confuse you, don't worry. Most of the applications you'll write as a new C# programmer will be SDI programs. As you become more familiar with creating C# projects in general, start experimenting with MDI projects. Remember, you don't have to make a program a MDI program simply because you can; make a MDI program if the requirements of the project dictate that you do so.

Summary 

Understanding forms is critical because forms are the dynamic canvases on which you build your user interface. If you don't know how to work with forms, your entire application will suffer. Many things about working with forms go beyond simply setting properties, especially as you begin to think about the end user. As your experience grows, you'll get into the groove of form design and things will become second nature to you.

In this hour, you learned how to do some interesting things, such as creating transparent forms, as well as some high-end techniques, such as building an MDI application. You also learned how to create scrolling forms (an interface element that shouldn't be overlooked), and you spent a lot of time on working with controls on forms, which is important because the primary function of a form is as a place to host controls. In the next two hours, you'll learn the details of many of C#'s powerful controls that will eventually become important weapons in your vast development arsenal.

>

Q&A

[file:///C:/Documents%20and%20Settings/dani/Asztal/c%23in24h/06.htm#qad1e19828 Q1:] Do I need to worry about the anchoring and scrolling capabilities of every form I create?
A1: Absolutely not. The majority of forms in most applications are dialog boxes. A dialog box is a modal form used to gather data from the user. A dialog box is usually a fixed size, which means that its border style is set to a style that cannot be sized. With a fixed-size form, you don't need to worry about anchoring or scrolling.
[file:///C:/Documents%20and%20Settings/dani/Asztal/c%23in24h/06.htm#qad1e19841 Q2:] How do I know if a project is a candidate for a MDI interface?
A2: If the program will open many instances of the same type of form, it's a candidate for a MDI interface. For instance, if you're creating an image-editing program and the intent is to allow the user to open many images at once, MDI makes sense. Also, if you'll have many forms that will share a common toolbar and menu, you might want to consider MDI.

Workshop

The Workshop is designed to help you anticipate possible questions, review what you've learned, and get you thinking about how to put your knowledge into practice. The answers to the quiz are in [file:///C:/Documents%20and%20Settings/dani/Asztal/c%23in24h/app01.htm#app01 Appendix A], "Answers to Quizzes/Exercises."

 Quiz 
[file:///C:/Documents%20and%20Settings/dani/Asztal/c%23in24h/app01lev1sec6.htm#ch06ans01 1:] True or False: The first control selected in a series is always made the active control.
[file:///C:/Documents%20and%20Settings/dani/Asztal/c%23in24h/app01lev1sec6.htm#ch06ans02 2:] How many methods are there to add a control to a form from the toolbox?
[file:///C:/Documents%20and%20Settings/dani/Asztal/c%23in24h/app01lev1sec6.htm#ch06ans03 3:] If you double-click a tool in the toolbox, where on the form is it placed?
[file:///C:/Documents%20and%20Settings/dani/Asztal/c%23in24h/app01lev1sec6.htm#ch06ans04 4:] Which property fixes an edge of a control to an edge of a form?
[file:///C:/Documents%20and%20Settings/dani/Asztal/c%23in24h/app01lev1sec6.htm#ch06ans05 5:] Which property do you change to hide the grid on a form?
[file:///C:/Documents%20and%20Settings/dani/Asztal/c%23in24h/app01lev1sec6.htm#ch06ans06 6:] Which menu contains the functions for spacing and aligning controls?
[file:///C:/Documents%20and%20Settings/dani/Asztal/c%23in24h/app01lev1sec6.htm#ch06ans07 7:] Which property do you set to make a form a MDI parent?
Exercises
  1. Use your knowledge of the Anchor property and modify the Picture Viewer project you built in [file:///C:/Documents%20and%20Settings/dani/Asztal/c%23in24h/ch01.htm#ch01 Hour 1] so that the main form can be sized. The buttons should always stay the size that they are and in the relative location in which they're placed, but the picture box should change size to show as much of the picture as possible, given the size of the form.
  2. Modify the MDI Example project in this hour so that the first child form shows another instance of itself, rather than showing an instance of the second child form.