NET User Interfaces in Csharp Windows Forms and Custom Controls [Electronic resources] نسخه متنی

اینجــــا یک کتابخانه دیجیتالی است

با بیش از 100000 منبع الکترونیکی رایگان به زبان فارسی ، عربی و انگلیسی

NET User Interfaces in Csharp Windows Forms and Custom Controls [Electronic resources] - نسخه متنی

Matthew MacDonald

| نمايش فراداده ، افزودن یک نقد و بررسی
افزودن به کتابخانه شخصی
ارسال به دوستان
جستجو در متن کتاب
بیشتر
تنظیمات قلم

فونت

اندازه قلم

+ - پیش فرض

حالت نمایش

روز نیمروز شب
جستجو در لغت نامه
بیشتر
لیست موضوعات
توضیحات
افزودن یادداشت جدید




































Resizable Forms



Every week, Windows developers from every programming language spend countless hours trying to solve the problem of resizable windows. Some purchase third-party ActiveX controls designed to transform static forms into resizable wonders automatically. These components are easy to use, but generally provide mediocre results that aren't suitable for professional applications. Other developers ignore the problem, and stubbornly lock interfaces into fixed-size dialog boxes, making them seem unmistakably primitive. Most developers eventually give in, and write lengthy code routines to resize their forms by hand.


In .NET the picture has finally improved. Two new features-anchoring and docking-provide built-in support for resizable forms. These features allow you to configure a few properties, and end up with intelligent controls that adjust themselves automatically. The catch? It's extremely easy to create the equivalent of the mediocre ActiveX resizing control. In other words, you can end up with a window that resizes its controls in an embarrassingly unprofessional way with far less effort than was needed before.


Matching a good resizing approach with a sophisticated interface is possible, but it requires a little more subtlety and a few tricks. This chapter describes these tricks, such as adding container controls and using the DockPadding property. Along the way, you learn how to create scrollable windows and controls, and see a full-fledged Explorer-style application that uses automatic resizing the right way.



The Problem of Size



The resizable forms dilemma stems from the fact that the Windows operating system supports a variety of monitors at several different resolutions. A window that looks decently sized on one computer may shrink to a toy-like box on another, or even stretch beyond the bounds of the desktop, obscuring important controls.


For many simple applications, these types of problems are not serious because programmers usually design their applications for a set minimum standard resolution (such as 640 × 480 or, more commonly today, 800 × 600). It's also generally accepted that users with much larger viewable areas expect to run several programs at once, and purchased larger screens so that they can put different programs side-by-side. They don't expect to use up the extra viewable area with larger fonts or extra white space in a dialog box.


However, a document-based application can't afford to ignore these considerations. Users with more available space expect to be able to use it to see more information at a time. Programs that ignore this consideration (see for example Figure 5-11) are irredeemably frustrating.




Figure 5-11: A frustrating window



Tip


Generally, a form needs to be resizable as soon as it stores more content than it can show at once. For example, a configuration window with a few settings does not need to be resizable, because all the information is available. On the other hand, a window that shows a scrolled text view or a data grid can benefit from more space, and so should be resizable.Ever since the dawn of Windows 95 and 32-bit programming, developers have found it increasingly difficult to avoid writing manual code to resize windows (in the older days of Windows programming, they just didn't bother at all). The emphasis on MDI interfaces has also contributed to this change. In an MDI (Multiple Document Interface) application, users expect to be able to resize, maximize, minimize, tile, and otherwise arrange all the child windows.


One common solution is to write procedures that dynamically resize the window, by responding to a resize event or message. Unfortunately, if your window has more than a couple of controls, this code becomes long, repetitive, and ugly. It's also hard to alter or debug when the form changes even slightly, and a nightmarish example of hard-coded values and cryptic lines of code. In .NET, the picture improves considerably.





Minimum and Maximum Size



The first useful feature the Form class introduces for managing size is the MaximumSize and MimimumSize properties. These properties stop users abruptly when they try to resize a form outside its set limits. For example, the Address Book program included with Windows 2000/XP won't let you shrink it any smaller than the size of the toolbar (see Figure 5-12).




Figure 5-12: The Address Book's minimum size


If you have the Show window contents while dragging environment setting enabled, the border suddenly becomes fixed when you hit the minimum size, as though it's glued in place. Similarly, you can set a maximum size, although this is less conventional. In this case, even when you try to maximize a window, it won't go beyond the set size, which can confuse the user.


The Visual Studio .NET IDE also stops you from resizing your form to an invalid size at design time when you have these properties set. If you set the form size to an invalid value in code, no error will occur. Instead, your window just automatically shrinks or expands to a valid size if it's outside the bounds of the allowed MinimumSize or MaximumSize properties.


One final caveat: both of these settings are ignored if you make your window a MDI child inside another window. In that case, your window is freely resizable.





Anchoring



Anchoring allows you to latch a control on to one of the form's corners. Anchored controls always stay a fixed distance from the point they are bound to. By default, every control is anchored to the top left corner. That means that when you move the window (and hence the top left corner), the controls follow. If you resize the form, however, the controls stay in place, because the position of the top left corner hasn't changed.


On the other hand, you can use .NET to anchor a control to a different corner. For example, if you chose the top right corner, the control moves as you expanded the window width-wise to stay within a fixed distance of the corner. If you expand the form height-wise, the control stays in place, because it's anchored to the top. It doesn't need to follow the bottom edge.


To anchor a button in .NET, you set the Anchor property using one of the values from the AnchorStyles enumeration. It's almost always easiest to set anchoring at design-time using the Properties window. A special designer lets you select the edges you are anchoring to by clicking them in a miniature picture, as shown in Figure 5-13. You don't need to run your program to test your anchoring settings; the Visual Studio .NET IDE provides the same behavior.




Figure 5-13: Setting control anchoring at design-time


Resizing controls with anchoring



Anchoring to one corner works best with controls that don't need to change size, but should remain in a consistent position. This typically includes buttons (for example, OK and Cancel should always remain at the bottom of the window) and simple controls like labels and text boxes. If you use this type of anchoring on every control, you create a window that gradually spreads out as it enlarges, providing that dreaded "third-party component" effect.


Instead, you can anchor a control to more than one side at once. Then, as you expand the window, the control needs to expand to keep a fixed distance from all the anchored sides. Table 5-9 lists some of the ways that you can combine anchor settings for different effects, and Figure 5-14 shows a window that uses fixedcorner anchoring for a button, and side-to-side anchoring for a text box.











Table 5-9: Common Anchoring Choices






AnchoringDescription















Top + LeftEquivalent to no anchoring. Controls remain a fixed distance from the top left corner, but they don't move or expand as the form changes size.










Bottom + RightThe control moves to keep a fixed distance from the bottom right corner.










Bottom + LeftThe control moves to stay at the bottom of the form, but it does not move to the side.










Top + RightThe control moves to stay at the right of the form, but it does not move down.










Top + BottomThe control's height expands as the form lengthens.










Right + LeftThe control's width expands as the form widens.










Top + Bottom + Right + LeftThe control's width and height expand as the form is enlarged.









Figure 5-14: Two ways to use anchoring



Tip


When using a resizable ListBox control, be sure to set the IntegralHeight property to false. This ensures that the ListBox can grow evenly. Otherwise, the ListBox is automatically resized to ensure that no list item is partially displayed. This causes it to "jump" awkwardly between valid sizes as its height grows or shrinks.The controls that benefit the most from anchoring to more than one side are those that contain more information than they can display at once. For example, a DataGrid, RichTextBox, or even ListBox control may present a scrolled view into a large amount of information. It makes sense for these controls to resize to use available screen area. On the other hand, a button should never be set to resize. Doing so impersonates the low-quality add-in controls that performed resizing automatically.



Note


The problems I keep mentioning with ActiveX controls for automatic resizing is that most tried to apply the same strategy to every window (there are a couple of rare exceptions). The result is that every control resized itself in pretty much the same way. In a real window, however, some controls are more important and need more space. Other controls don't need to change at all, and can look rather ridiculous if they are sized radically bigger than their contents. Ultimately, resizing is another area where you must follow user interface design conventions from established Windows applications.





Containers and anchoring



Rather than try to anchor every control in a window, you should use one or more container controls to save some work. Containers also make it easier to rearrange portions of user interface at once, or even transplant them from one form to another.


To use anchoring with container controls, you need to understand that anchoring is always relative to the container. That means that if you place a button inside a group box and you anchor it to the bottom right, it will be anchored to the bottom right corner of the group box. It won't move when the size of the form changes; it will move only when the size of the container changes. For example, consider the button shown in Figure 5-15. The form is resized, but the group box doesn't change, and so the button also remains in place.




Figure 5-15: Anchored controls follow a corner in the container.


Nothing happens in the previous example, because there's no change in the container. To get around this, you could anchor the group box to all sides of the window. Then, as the group box grows, the button will move to keep a consistent distance from the bottom right corner. This version is shown in Figure 5-16.




Figure 5-16: Anchoring the control and its container


Container controls become particularly important when you start to add docking and split windows to your designs.







Docking



Docking allows a control to bind itself to an edge in the form or container control. When you resize the container, the control resizes itself to fit the entire edge. A control can be bound to any one edge, or it can be set to fill the entire available area. The only limitation is that you can't dock and anchor the same control (if you think about it for a moment, you'll realize that it wouldn't make sense anyway).


For example, you can solve the problem you saw with the button in the container control by docking the group box to the right edge of our form. Now, when you resize the window, the group box expands to fit the edge. Because the button inside is anchored to the bottom right corner of the group box, it also moves to the right side as the form is enlarged. Similarly, you could set the group box docking to fill, so that it would automatically resize itself to occupy the entire available area. Figure 5-17 shows an example of this behavior.




Figure 5-17: A docked group box


To configure docking, you set the control's Dock property to one value from the DockStyle enumeration. Typically, you use the Property window to choose a setting at design-time.


If you experiment with docking, your initial enthusiasm quickly drains away, as you discover that:





Docked controls insist on sitting flush against the docked edge. This results in excessive crowding, and doesn't leave a nice border where you need it.





Docked controls always dock to the entire edge. There's no way to tell a docked control to bind to the first half (or 50 percent) of an edge. It automatically takes the full available width, which makes it difficult to design a real interface.





Every control that derives from the ScrollableControl class has an additional feature called dock padding. Dock padding allows you to insert a buffer of empty space between a container and its docked controls. The only important classes that derive from ScrollableControl are Panel, Form, and UserControl. The GroupBox control does not provide any padding.


Figure 5-18 shows another example with a group box and a contained button. Because the Form is the container for the group box, you need to modify the form's padding property by finding DockPadding in the properties window, expanding it, and setting All to 10 (pixels). Now the group box will still bind to all sides, but it will have some breathing room around it.




Figure 5-18: A docked group box with padding


At this point you may wonder why you need docking at all. It seems like a slightly more awkward way to accomplish what anchoring can achieve easily. However, in many cases, anchoring alone is not enough. There are two common scenarios:





You are using an advanced window design that hides and shows various window elements. In this scenario, docking forces other controls to resize and make room, while anchoring leads to overlapping controls.





You want to create a window that the user can resize, like a split window design. In this case, you need to use docking, because it allows controls to resize to fit the available space.





You examine both of these designs in the next section.



Tip


The sample code for this chapter includes a program that lets you play with a number of different combinations of anchoring and docking, so you can see how they do or don't solve a problem.







/ 142