Prebuilt Dialogs

.NET provides some custom dialog types that you can use to show standard operating-system windows. The most common of these is the MessageBox class, which exposes a static Show() method. You can use this code to display a standard Windows message box (see Figure 3-8) MessageBox.Show(You must enter a name., Name Entry Error, MessageBoxButtons.OK, MessageBoxIcon.Exclamation) The message-box icon types are listed in Table 3-7. The button types you can use Show() method with a message box are as...

Simple Pop Ups

For really simple Help, you don't need to use a Help file at all. Instead, you can display a popup window with a short message (formerly referred to as What's This Help). To do so, make sure that you do not set the HelpProvider.HelpNamespace property to anything other than an empty string. Then, find the control you want to use, and supply the Help text by settings its HelpString property in the Properties window. Alternatively, you can do it programmatically by calling the SetHelpString()...

Getworkingarea Visual Basi

WorkingArea GetWorkingArea() (static) Returns an array of Screen objects, with one for each display on the system. This method is useful for systems that use multiple monitors to provide more than one desktop (otherwise, it returns an array with one Screen object). Returns the Screen object that represents the primary display on the system. Returns a Rectangle structure that represents the bounds of the display area for the current screen. Accepts a reference to a control, and returns a...

Positioning Controls

So far, you've seen how you can configure the sizing of rows and columns. But what about the individual controls inside each cell By default, controls appear in the top-left corner of the cell that contains them. As with the FlowLayoutPanel, you can use the Margin properties of each control to add spacing between the cell edges and the control edges. You also can use the TableLayoutPanel.Padding property, but it's less useful. It sets the space between the borders of the TableLayoutPanel and...

Watching the Mouse

The longest and most involved event handler in this application is the one that handles mouse movement. That's because there are three different tasks that you might perform at this point If dragging mode is enabled, move the control. If resizing mode is enabled, resize the control. If neither mode is enabled, check if the mouse pointer is near one of the borders of the focus square, and then update the mouse pointer accordingly. The first of these tasks is easy to accomplish and takes only a...

Tip You can set the Tool StripStretch property to true to force a Tool Strip to fill the whole row for a horizontal

Rearranging ToolStrip objects at runtime Figure 14-9. Rearranging ToolStrip objects at runtime If you want to add a ToolStrip into a ToolStripContainer at design time, you first must expand the panel where you want to place it. To do this, use the arrow buttons that appear along each edge of the ToolStripContainer. These buttons are a design-time convenience, and they don't appear at runtime. For example, if you want to add a ToolStrip to the right edge, start by clicking the right...

Container Controls

The .NET Framework defines a few controls that are designed explicitly for grouping other controls GroupBox. This control is drawn as a titled box and is commonly used for visually isolating related groups of controls. Panel. This control has no default appearance but supports scrolling and padding. SplitContainer. This control combines two Panel controls, separated by a splitter bar. TabControl. This control hosts one or more TabPage controls (only one of which can be shown at a time). The...

Data Aware Controls

Not all controls work well with data binding. For example, the popular TreeView and ListView controls need to be filled manually. In other circumstances, you may have controls that support data binding, but you want to take control of the entire process. Maybe you want to create a control that can't be filled all at once, but uses partial data reads or just-in-time queries to allow a user to browse through a large amount of data. .NET provides many opportunities for data integration without...

Smart Controls

So far you have seen two distinct ways to use controls from the .NET class library Create an instance of a generic control class as is. Then configure its properties. Define a new class that inherits from a generic control class, and customize this class for your needs. Then create an object based on this specialized class. The difference is shown in Figure 1-4. Figure 1-4. Two ways to interact with controls Visual Studio uses inheritance (the first method) when you create forms. When you...

Owner Drawn Custom Controls

So far, you've seen examples that use owner drawing support to customize the appearance of existing controls. In the remainder of this chapter, you'll step up to a more challenging task rendering entirely new controls from scratch. Owner-drawn custom controls are one of the most ambitious projects a developer can undertake. This is not because they are conceptually tricky (although sometimes they may be), but because a moderately sophisticated control needs a great deal of basic code just to...

About This Book

This book focuses relentlessly on Windows Forms, the .NET toolkit for building modern Windows interfaces. In this book you'll learn about several sides of user interface programming. Some of the key themes include the following Dissecting the .NET controls. Although this book is not a reference, it contains an exhaustive tour of just about every .NET user interface element you'll ever want to use. Best practices and design tips. As a developer, you need to know more than how to add a control to...

Restrict It to a Single Task

A wizard works well for a single task that can be accomplished in only one way (like adding a printer driver). As soon as you start adding an element of variety or creativity, the wizard can't keep up. Don't think that you should be proud of a complex wizard that branches out conditionally to use different windows depending on previous user selections. All you've done is created a traditional single-screen DOS program wherein tasks must be completed in separate windows and in a set order.

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 if you resize the form, the controls stay fixed in place. On the other hand, you can use .NET to anchor a control to a different corner or edge. For example, if you chose the top-right corner, the control moves as you expand the window width-wise to stay within a fixed...

The Hidden Designer Code

The only problem with automatically generated code is that it can be fragile. For example, if you try to edit the code that Visual Studio has generated, you may inadvertently end up removing something fundamental. If the problem is severe enough, Visual Studio will refuse to design the form at all instead, when you switch to design mode, you'll see an unhelpful error message, as shown in Figure 1-9. One or more errors encountered while loading the designer.The errors are listed helow. Some...

Button

Quite simply, buttons make things happen. The most important point to remember about buttons is that their Click events have a special meaning it occurs when you trigger the button in any way, including with the keyboard, and it is not triggered by right-clicks. Buttons are old hat to most developers, but Table 4-4 lists a few interesting members that may have escaped your attention. Clicks the button programmatically. In other words, it causes the button to fire the Click event. This method is...

Owner Drawn Controls

I n Chapter 7 you learned how to use GDI+ to draw text and complex shapes on a form by overriding the OnPaint() method. Although this technique works perfectly well, most of the time you'll want to build an application out of smaller controls that paint themselves individually. Taken to its logical extreme, you can use this technique to build hand-tooled interfaces with the latest in eye-catching graphics (something you'll consider again in Chapter 23). In this chapter, you'll start out on your...

Simple Owner Drawn List Box

The standard ListBox control is fairly unimpressive. You can configure various properties that affect the whole control, like Font, ForeColor, and BackColor, but you can't change individual items independently. For example, you can't create a list box that contains pictures, formatted text, or colored item backgrounds. And while you could develop a custom list control from scratch, there's a fair bit of boilerplate code you would need to write for managing the scrolling and selection behavior....

The Data GridView Objects

The DataGridView is a complex control that exposes dozens of properties, methods, and events. However, there are a few key collections that you should learn about to make the most of other features. These collections (Columns and Rows) allow you to work with the entire set of data that's displayed in the DataGridView. The Columns property provides a collection of DataGridViewColumn objects, one for each field or property in the bound data object. The Rows property provides a collection of...

Selecting Bar Item Objects at Design Time

There's one more frill you can add to the SimpleChart example. Now that you have the ability to create and configure BarItem objects at design time, you might also want to allow the developer to select individual BarItem objects from the form-design surface, and configure them directly in the Properties window. In the case of the SimpleChart control, this doesn't add a lot to the overall picture, but it's still a useful technique. It also demonstrates how to use the ISelectionService. The first...

Navigating to a Page

Once you've placed the WebBrowser control on a window, you need to point it to a document. Usually, you'll supply a URL that points to a local or remote location. However, you can also submit a complete HTML document, content and all, as a long string or a Stream-based object. The WebBrowser control gives you the choice of three properties Url. Set this to a remote URL (http mysite.com mypage.html) or a fully qualified file path (file c mydocument.text). You must use a Uri object (which you can...

The Designer Actionltem Collection

The DesignerActionItem class represents the individual items in a smart tag. The .NET Framework provides four basic classes that derive from DesignerActionItem, as described in Table 26-6. Table 26-6. Classes Derived from DesignerActionItem This item is rendered as a link. When you click it, it triggers an action by calling a method in your DesignerActionList class. This item is rendered as an edit control, using logic that's very similar to the Properties window. Strings are given edit boxes,...

Controls Can Contain Other Controls

The System.Windows.Forms.Control class provides a property called Controls, which exposes a collection of child controls. For example, a Windows Form uses this Controls property to store the first level of contained controls that appear in the window. If you have other container controls on the form, like group boxes, they might also have their own child controls. In other words, controls are linked together by containment using the Controls collection. Because every control is a class that...

Saving and Loading Images

One of the frills that you can implement quite easily is the ability to save all the shapes that are currently displayed into a file, and then retrieve and redisplay them later. This feature would have been more difficult to create with the control-based example, because controls can't be serialized directly. However, because you control the code for the Shape and ShapeCollection classes, you can ensure that both of them are serializable. .NET has great built-in smarts for dealing with...

Design Time Basics

Custom controls have two requirements. They need to interact with your code and the user at runtime, and they need to interact with Visual Studio and the developer at design time. These two tasks are related, but they can be refined and customized separately. Some of the most advanced Windows Forms controls include an impressive degree of design-time smarts. You've already seen how Visual Studio gives a basic level of support to all custom controls by adding them to the Toolbox automatically...

Playing MP3 Midi Wma and More

Once you've added a reference to the Quartz component, you can use it to play a wide range of audio files. Essentially, you can play any audio supported by Windows Media Player. This includes the following MP3, the high-quality compressed audio format that made song pirating famous. WMA (Windows Media Audio), Microsoft's MP3 clone that can be used in conjunction with strict licenses. MIDI, the lightweight format that stores a sequence of notes rather than digital audio. When you play a MIDI...

Testing the Bitmap Viewer Control

To see the final BitmapViewer control, follow these steps 1. Compile the BitmapViewer control. 2. Create a new test project and add it to the solution. 3. Drop the BitmapViewer control onto the form using the Toolbox. 4. Set the appropriate properties, like Directory, Dimension, and Spacing. In Figure 10-7, a dimension of 80 and spacing of 10 is used. (You can modify the declarations of the corresponding private member variables to establish some reasonable default values.) 5. Set the Directory...

Painting the Chart

The simplest part of the painting process is the OnPaintBackground() method, which fills the area behind the charts with a gentle blue gradient. To simplify this task, the region is filled using the VisualStyleRenderer class (described in Chapter 7), which uses Windows XP themes. Unfortunately, you can't assume that all computers support visual styles, so backup drawing logic uses a plainer solid fill if the operating system doesn't support themes or the user has switched them off. protected...

Markup Based User Interface

The future of user interface is probably an entirely different approach to programmatic control creation. This approach, first popularized with the Web, is markup based. Rather than writing code to programmatically create and insert controls into a container, with markup-based user interface you write a template (typically in an XML-based format) that defines each control. The user interface framework parses this file and then creates the corresponding controls (typically one for each tag it...

Drawing Program with Controls

The basic application (shown in Figure 24-1) allows the user to create rectangles, ellipses, or triangles of any color, and then resize them or drag them around the form to a new location. Rather than coding all the logic to manage the hit testing, selection, and layering, you can make use of a convenient shortcut by turning each shape into a custom control. Because each control has its own built-in smarts for handling user interaction like mouse clicks and key presses, this approach simplifies...

Dynamic Drawing with a Design Surface

Drawing programs exist in two basic flavors. The first type is painting programs, like Microsoft Paint, which allow users to create bitmaps with static content. In these programs, once the user draws a shape or types some text onto the drawing area, it can't be modified or rearranged. But in more-sophisticated vector-based drawing programs (everything from Adobe Illustrator to Microsoft Visio), the user's drawing is actually a collection of objects. The user can click and change any object at...

Implementing the Set Xxx and Get Xxx Methods

To complete the StatusStripHelpLabel, you need to add the implementation logic for the SetHelpText() and GetHelpText() methods. The first step is to fill in the SetHelpText() method, which requires the most coding. When the Help text is set, the provider needs to add the supplied ToolStrip to the internal collection for tracking, and then dynamically attach event handlers to receive the MouseEnter and MouseLeave events. Additionally, your code needs to politely detach the event handlers when a...

Advanced Media with Direct Show

The SoundPlayer and SystemSounds classes are easy to use, but they're relatively underpowered. In today's world, it's much more common to use compressed MP3 audio for everything except the simplest of sounds, instead of the original WAV format. But if you want to play MP3 audio or MPEG video, you need to turn to the world of unmanaged code. The solution is the Quartz COM component. This component is a key part of DirectX, and it's included with Windows Media Player and the Windows operating...

Providing Standard Values

The Properties window does a solid job of providing support for enumerations. For example, if you create a property that uses a custom enumeration, the Properties window automatically provides a drop-down list with the values from the enumeration. For example, consider the DisplayStyle property shown here SpecialDirectoryPictures, AllDirectoryPictures get return displayStyle set displayStyle value Tip You can hide individual values in an enumeration from appearing in the Properties window. Just...

Painting a Thumbnail

Type editors also give you the chance to get a little fancy by creating a custom thumbnail of the gradient in the Properties window. You might use this trick with the GradientPanel control. To add this extra bit of finesse, all you need to do is create a type editor for the GradientFill class, and override the PaintValue() method. Here's the complete code public class GradientFillEditor UITypeEditor public override bool GetPaintValueSupported( context) public override void PaintValue( e)...

Updating a Click Once Application

To see how a ClickOnce application can update itself automatically, follow these steps with the installation from the previous example 1. Make a minor but noticeable change in the application (for example, adding a button). 2. Recompile the application and republish it to the same location. 3. Run the application from the Start menu. The application will detect the new version, and ask you if you'd like to install it (see Figure B-7). 4. Once you accept the update, the new version of the...

Default Values for New Rows

Ordinarily, when the user begins adding a new row, the values of that new row are filled in with any defaults defined in the data source. (For example, if you're binding to a custom data object that sets certain defaults in its constructor, the constructor determines what text appears in the fields.) However, in many cases you need a more flexible, decoupled approach that allows you to set defaults that apply only to the DataGridView. This is actually quite easy to accomplish all you need to do...

Check Box and Radio Button

The CheckBox and RadioButton controls provide a Checked property that indicates whether the control is checked or filled in. After the state is changed, a CheckedChanged event occurs. You can create a special three-state check box by setting the ThreeState property to true. You need to check the CheckState property to examine whether it is Checked, Unchecked, or Indeterminate (shaded but not checked). By default, the control is checked and unchecked automatically when the user clicks it. You...

Visual Studio

Very few developers will ever attempt to write their user interface code by hand. Doing so is a recipe for endless headaches and a lot of tedium. Instead, integrated design tools like Visual Studio make it much easier to design forms and tweak controls. Visual Studio includes two project types designed for Windows applications Windows Application creates the standard stand-alone EXE application. Windows Control Library creates a DLL that you can use in other EXE applications. You'll use this...

Hiding Moving and Freezing Columns

Styles aren't the only detail that influences the appearance of your grid. You also can hide columns, move them from place to place, and freeze them so that they remain visible even as the user scrolls to the right. These features are all provided through the properties of the DataGridViewColumn class, as detailed in Table 15-6. Table 15-6. Appearance-Related DataGridViewColumn Properties Sets the position where the column will appear in the DataGridView. For example, a column with a...

Accessing the Graphics Object

There are essentially two ways to access a live instance of the Graphics class. The simplest and safest approach is to perform your painting inside a dedicated Paint event handler. In this case, the Graphics object is provided to your event handler through the PaintEventArgs parameter. For example, the code that follows draws a curve onto a form using the Graphics.DrawArcO method (see Figure 7-1) This code handles the Form.Paint event. private void Form_Paint(object sender,...

Invoking Help Programmatically

The examples so far require the user to press the F1 key. This automated approach doesn't work as well if you want to provide your own buttons that allow the user to trigger Help when needed. Sometimes, that sort of prominent reminder can reassure the user that Help is nearby. To trigger Help programmatically, you need to use the static ShowHelp() method of the Help class (in the System.Windows.Forms namespace). The Help class works analogously to the HelpProvider in fact, the HelpProvider uses...

Marshalling Calls to the Right Thread

This example leaves out one detail the code for updating the user interface. The problem is that .NET controls exhibit thread affinity, which means that their properties and methods can be called only by code running on the same thread that created the control. As a result, you can't modify the lblTimeTaken or txtResults controls from the CallAsyncWorker() method. A new debugging feature in .NET 2.0 helps you spot threading errors. By default, every Windows control included with .NET throws an...

User Interface Classes in NET

The first step when considering class design is to examine what rules are hard-wired into the .NET Framework. Your goal should be to understand how the assumptions and conventions of .NET shape user-interface programming. Once you understand the extent of these rules, you will have a better idea about where the rules begin and end and your object designs take over. In the following sections, you'll take a look at a number of examples that show how classes plug into the Windows Forms...

Taking Control of Overflow Menus

As you saw at the beginning of this chapter (in Figure 14-1), the ToolStrip uses an overflow menu when there isn't enough room to show all the buttons at once. By default, items are dropped off the end of the ToolStrip and added into the overflow menu. But more sophisticated programs that use overflow menus (like Microsoft Office) take a different approach they selectively eliminate commands that are deemed to be less important. You can implement the same sort of logic with the .NET ToolStrip....

Visual Style Support

There's a significant catch to using visual styles. Before you can use the VisualStyleRenderer in an application, you need to be sure that your environment supports visual styles. To have this support, four things need to be true The application must be running on an operation that supports visual styles (Windows XP or Windows 2003 Server). You can determine this by checking the IsSupportedByOS property of the VisualStyleInformation class. Visual styles must be enabled in the operating system....

Interacting with the Mouse

One dramatic difference between how controls work at runtime and how they work at design time is the handling of the mouse. In the design-time environment, mouse actions are ignored, and never passed on to the control. You can click a control to select it, but that won't fire the underlying control events. You have several options for extending how a control designer works with mouse actions, or changing this behavior entirely. For example, you can override the OnMouseEnter(), OnMouseHover(),...

Description

ControlAdded and ControlRemoved events Returns true if the Controls collection has at least one child control. A collection of contained controls. You can use this collection to examine the existing child controls, remove them, or add new ones. These events fire when controls are added to or removed from the Controls collection. You can use these events to automate layout logic. Chapter 21 deals with this issue in more detail. A reference to the parent control (the control that contains this...

Form Resources

Under certain situations, Visual Studio also generates a .resx file for a form. Two examples include when you add an ImageList to your form, and when you use localization (described later in this chapter). In both situations, Visual Studio automatically adjusts the serialized form code to use the form resources for retrieving data. The .resx file that's generated for a form always has the same name as the form, as in Forml.resx. However, you won't see the .resx file in the Solution Explorer...

Designer Transactions

Designer transactions ensure that when several small changes are made at design time as part of a logical operation, they can be reversed using the Undo command. Not only do designer transactions support the Undo feature, they also improve performance because the design surface isn't refreshed until the transaction is complete. For example, consider the DirectoryTreeDesigner. When you select an option from its context menu, the Drive property is changed. This is a single action, which means you...

Data Access Component

Before continuing, it makes sense to introduce the database class that's used in the following public DataTable GetProducts() When other forms need data, they call the StoreDB.GetProducts() method to retrieve a DataTable object. In this section, we're primarily interested with how ADO.NET objects like the DataTable and DataSet can be bound to Windows Forms controls. The actual process that deals with creating and filling these objects (as well as other implementation details, such as whether...

Advanced Design Time Support

I n Chapter 13 you explored how you could add a respectable level of design-time support to your control. You saw how attributes, type converters, and type editors could improve the Properties-window support for your control and ensure proper code serialization. In this chapter, you'll continue to add to your design-time skills by considering a few more topics. Control designers. Control designers allow you to manage the design-time behavior and the design-time interface (properties and events)...

Focus

The final step of the OnPaint() drawing method is to call a method named PaintFocusRectangle(), provided the button is focused and not disabled. At this point, the focus cue is drawn around the borders of the control, provided the PaintFocusCue property is true. (If it's false, the PaintFocusRectangle() method isn't called at all.) paintFocusCue value Invalidate() protected virtual void PaintFocusRectangle(Graphics g) ControlPaint.DrawFocusRectangle(g, this.ClientRectangle) Notice that the...

Licensing Custom Controls

Licensing in the .NET world is far more customizable and far less painful than it is with older component technologies like COM. The .NET Framework provides several licensing classes in the System.ComponentModel namespace. By using and extending these classes, you can grant or allow access to your control, using ordinary .NET code to check external resources like the Windows registry, an XML file, or even a remote Web service for registration information. There are four basic ingredients for...

Smart Tags

Visual Studio 2005 includes a new feature for creating a rich design-time experience smart tags. Smart tags are the pop-up windows that appear next to a control when you click the tiny arrow in the corner. Smart tags are similar to menus in that they have a list of items. However, these items can be commands (which are rendered like hyperlinks), or other controls like check boxes, drop-down lists, and more. They can also include static descriptive text. In this way, a smart tag can act like a...

The Collapse Button

The CollapsiblePanel control is divided into two pieces (not including the classes for designtime support) The CollapsiblePanel derives from the base Panel class, and adds the custom drawing code and the collapsing logic. The CollapseButton represents the header of the panel, including the title and the arrow button shown in the top-left corner, which you can use to collapse and expand the panel. Both of these controls draw their interfaces from scratch using the VisualStyleRenderer class,...

The Goals of Multithreading

If you decide to use multithreading, you'll need to code carefully to avoid minor mistakes that can lead to mysterious errors later on. Before you split your application into separate threads, carefully consider whether the additional work is warranted. There are essentially three reasons for using multiple threads in a program Making the client more responsive. If you run a time-consuming task on a separate thread, the user can still interact with your...

Data GridView Customization

The most impressive feature of the DataGridView is its support for customization. You can extend the DataGridView to suit your needs, and you can implement these extensions in a flexible and reusable way. Although many of the possible avenues for customization are outside the scope of this book (for example, you can fine tune details as minute as the asterisk symbol shown in the new record placeholder by deriving a custom class), the following sections will give you an overview of some common...

Hosting Other Controls in the Tool Strip

Sometimes, you'll want to put controls other than buttons and labels in a ToolStrip. The ToolStripControlHost makes this feat easy. You simply create a new instance of a ToolStripControlHost and pass any Control-derived class in the constructor. You can then add the ToolStripControlHost to the ToolStrip. Here's an example that uses this technique to add a DateTimePicker to a ToolStrip DateTimePicker dt new DateTimePicker() dt.Format DateTimePickerFormat.Short ToolStripControlHost item new...

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...

Data Providers

You don't need to use any database code to take advantage of data binding. .NET allows controls to bind to any class that implements the IList interface. Note IList is just a starting point. Other, more sophisticated interfaces extend IList with features for editing. As you'll see later in this chapter, interfaces like IBindingList and IEditableObject, allow two-way data binding, so you can modify a value in a control and have the control update the bound data object automatically. ADO.NET...

The Case for Dynamic User Interface

Before you start writing any code, you need to decide how dynamic your user interface should be. This chapter offers examples that do little more than add a few simple elements to a form, and others that build the Window dynamically from scratch. So which approach is best As usual, it all depends on your project and design goals. To determine where dynamic user interface fits in, you need to consider the role of the user interface designer. Some of the reasons that programmers rely on Visual...

Click Once Requirements

To successfully install an application with ClickOnce, the target computer must meet these minimum requirements Windows 98 or later, excluding Windows NT 4 The second requirement isn't as limiting as it might seem. The .NET Framework can be installed in a variety of ways, including via the Windows Update feature, and with enterprise distribution systems like Microsoft Systems Management Server (SMS). However, the most attractive option is to use the bootstrapping functionality that's part of...

Multithreading

One of the great advantages of rich client applications is their support for asynchronous operations in other words, their ability to perform multiple tasks at the same time and still remain responsive. The same feat isn't possible in a typical server-side Web application. Although Web browsers are themselves multithreaded pieces of software, most Web applications strictly separate the work that's done in the browser from the work that's done on the server, for both security and compatibility...

Get AsyncKey StateO

When you use the methods described so far, your code gets the virtual key state. This means it gets the state of the keyboard based on the messages you have retrieved from your input queue. This is not necessarily the same as the physical keyboard state. For example, consider what happens if the user types faster than your code executes. Each time your KeyPress event fires, you'll have access to the keystroke that fired the event, not the typed-ahead characters. This is almost always the...

Text Box

Another staple of Windows development, the text box allows the user to enter textual information. The previous chapter explained how you can react to and modify key presses in the text box. Interestingly, text boxes provide a basic set of built-in functionality that the user can access through a context menu (see Figure 4-2). Figure 4-2. The built-in TextBox menu Figure 4-2. The built-in TextBox menu Much of this functionality is also exposed through TextBox class members, and some of it is...

Tool StripItem Text

Each ToolStripItem supports an arbitrary amount of text through its Text property. However, text is never wrapped in a ToolStrip item, so it's a good idea to keep it as short as possible. A single word is ideal any more should go into the tooltip. Note The ToolStrip gives you a range of tooltip possibilities. If you don't set anything in the ToolTipText property, the ToolStripItem will use its Text property for tooltip text. To disable this behavior, set the AutoToolTip property to false. To...

The Presentation Tier

Though it doesn't explicitly state it, three-tier design requires a fair degree of consistency among user-interface controls. In the real world, this consistency doesn't exist. For example, making what is conceptually a minor change like substituting a ListView control for a Data-GridView requires a totally different access model. The DataGridView is filled exclusively by data binding. The ListView, on the other hand, acts like a collection of items. To get information into other ListView...

More Advanced License Providers

Control licensing doesn't need to be based on LIC files. In fact, you can create any type of licensing scheme imaginable. You can even perform tremendously annoying tricks like allowing controls to be registered only to specific computers. To implement a custom licensing scheme, you need to create two classes a custom license provider and a custom license. The custom license is the easiest ingredient. It simply derives from the base License class, overrides the LicenseKey property and the...

Bitmap Viewer Events

To make the BitmapViewer more useful, you can add an event that fires every time a picture box is selected. Because the BitmapViewer is built entirely from PictureBox controls, which natively provide a Click event, no hit testing is required. All you need to do is register to handle the Click event when the picture box is first created in the UpdateDisplay() method. pic.Click + new EventHandler(this.pic_Click) To send an event to the application, the event must first be defined in the user...

The Roles of Classes

It's important to remember that although all classes are created in more or less the same way in your code, they can serve different logical roles. Here are the three most common examples Classes can model real-world entities. For example, many introductory books teach object-oriented programming using a Customer object or an Invoice object. These objects allow you to manipulate data, and they directly correspond to an actual thing in the real world. Classes can serve as useful programming...

The Data Grid Legacy

Developers have been using grid controls for years. In the pre-.NET world, developers often relied on ActiveX controls like the MSFlexGrid, which provides a solid formatting model and access to individual cells. Though controls like the MSFlexGrid still can be used in .NET, they obviously can't support .NET data binding. If you want to use them, you'll need to write painstaking code to iterate through the rows of your data source and copy values into the grid. The DataGrid was the first native...

Creating a Nested Object with a Constructor

With the GradientPanel, the three GradientFill properties are changed independently. As you modify them, Visual Studio generates code like this in the InitializeComponent() method Color.Cyan this.gradientPanel1.GradientFill.ColorB Color.Plum LinearGradientMode.Horizontal This technique is great when it works. In some cases, you can't alter the properties of a nested object in an arbitrary order. Instead, you need to create the object in one step using a specific constructor. Fortunately, by...

Contents

About the About the Technical Acknowledgments PART 1 Windows Forms Fundamentals chapter 1 User Interface Classes and The Roles of Classes and User Interface Classes in .NET Controls Are Controls Can Contain Other Controls 10 Controls Can Extend Other Inheritance and the Form Accessing Interacting with a Overriding The View-Mediator Smart Smart Visual Studio Generating User-Interface Code in Visual Studio 25 The Component The Hidden Designer Application Designing Windows Forms Applications 33...

Encapsulation

Encapsulation is the principle that suggests classes should have separate, carefully outlined responsibilities. Everything that a class needs to fulfill these responsibilities should be wrapped up, hidden from view, and accomplished automatically wherever possible. Encapsulation is often identified as a pillar of object-oriented programming, but it's played a part in good program design since the invention of software. A properly encapsulated function, for example, performs a discrete...

ZOrder

Controls have built-in support for layering. You can use methods like BringToFront() and SendToBack() to change how controls overlap, and you can use the ControlCollection. SetChildIndexO and ControlCollection.GetChildIndex() to explicitly change the z-index. Tip Remember, the z-index is a number that represents the layer on which a control is placed. (Each control is on a separate layer.) A control with a smaller z-index is superimposed on a control with a larger z-index when they overlap. See...

Shaped Controls

You don't need to stop at shaped forms. You can apply similar techniques to create irregularly shaped controls. Most controls will let the background of the parent show through if you set a transparent BackColor. More powerfully, you can use the Control.Region property, which works the same as the Form.Region property, to assign a nonrectangular region to a form. Control mouse handling and control painting is performed only in the control's region. You'll see an example of irregularly shaped...

Attaching a Type Converter

There are two ways to attach a type converter. The approach you should use in most cases is to link the custom type to the type converter by adding the TypeConverter attribute to the class declaration. Another option is to apply the TypeConverter attribute to the property in your custom control. This option is most suitable if your control needs to serialize a nested object in a different way than usual. public GradientFill GradientFill If you use both approaches, the type converter that's...

Win Help

The WinHelp format used in Windows 3.0 still exists (see Figure 22-1), and can be used in the most modern Windows application. Unfortunately, it looks irredeemably garish. Help files from different authors tended to look and act differently. Node CVS commands. Next Invoking CVS, Prev Special Files, Up Top This appendix describes the overall structure of CVS commands, and describes some commands in detail (others are described elsewhere for a quick reference to CVS commands, see Invoking CVS)....

Accessing Controls

Once a custom form object has been instantiated, there are two different ways to access the controls it contains through the Controls collection or, more simply, using form-level member variables. In the previous example, the only control MainForm contains (a text box) is referenced with the member variable txtUserName. This means you can easily access it in other methods in your custom form class using code like this txtUserName.Text John It's up to you whether you want to make a control...

Affordances

Affordances are the visual clues designed to demystify a complex application. For example, Windows uses brief descriptions to provide a little information about your computer's Internet settings, as shown in Figure 22-14. 1 Content Connections Programs Advanced f. Move the slider to select a privacy setting for the Internet zone. f. Move the slider to select a privacy setting for the Internet zone. - Blocks third-party cookies that do not have a compact privacy policy - Blocks third-party...

Autosizing

In .NET 2.0, the Control class adds a new AutoSize property, which allows you to create controls that expand or shrink as their content changes. All .NET controls provide the AutoSize property, although some interpret it differently from others (and some, like TextBox, ignore it completely). If you set AutoSize to true for controls like the Label, LinkLabel, Button, CheckBox, and RadioButton, the control automatically expands to fit the displayed text. This is useful in two key scenarios You...

Key Press and Key Down

To understand the difference between KeyPress and KeyDown, consider what happens if the user holds down the Shift key and then presses the D key. In this scenario, the KeyPress event will fire once, and provide the exact character that was submitted (for example, the letter D). private void txt_KeyPress(object sender, KeyPressEventArgs e) lbl.Text Key Press + e.KeyChar.ToString() On the other hand, the KeyDown event will fire twice, once for the Shift key, and once for the D key. private void...

Binding Directly to a Database Table Adapters

The automatic binding features all work through the Data Sources window in Visual Studio. The basic idea is that you define a data source (which can be an external database, a separate class, or a Web service) in this window. You can then bind these data sources more or less directly to a form. The following steps take you through the simplest scenario, where you set up a data source for a database on the current computer or a local network. 1. Select Data menu > Show Data Sources to show the...

Application Rendervisualstyles

RadioButton control, 122 support for images, 152 raised image button, 832-835 Border3DStyle enumeration, 494 RaisedInner value Border3DStyle enumeration, 494 RaisedOuter value Border3DStyle enumeration, 494 RangeValidator control, 631 complexity of, 636, 637 EvaluateIsValid() method, 637 ReadImagesFromFile() method Bitmap Viewer user control, 354 ReadOnly property DataColumn class, 527 DataGridView class, 556, 559 TextBox control, 117 ReadOnlyTextAttribute class System.ComponentModel namespace,...

S

Satellite assemblies, 167 Save() method Bitmap class, 243 Graphics class, 219 SaveFile() method RichTextBox control, 117, 119 SaveFileDialog class, 92, 93 SaveSettings() method ToolStripManager class, 513 scalability and DataGridView class, 523-524 screen captures, 242-244 Screen class members, 78 PrimaryScreen property, 77 ScriptErrorsSuppressed property WebBrowser control, 600 DataGridViewDataErrorContexts enumeration, 563 scrollable forms, 81-82 ScrollableControl class base classes for...

Using the Custom Validators

It's easy to use all of the custom validation components that were built in the last section. All you need to do is compile the class library project the components it contains are automatically added to the Toolbox in Visual Studio (as described in Chapter 9). Then, you can drag validator components into the component tray, one for each control you want to validate. To configure how the validation works, adjust the appropriate properties (like the regular expression or maximum and minimum...

Hit Testing

The square painting program shown earlier presents some interesting possibilities. For example, you could use this code as the basis for a simple GDI+ drawing application. You probably would add controls that allow the user to draw more than one type of object. You would need to add a special class (perhaps called Shape) that encapsulates all the details about the drawn object, such as size, color, pen width, and so on. Your Paint event handler would then iterate through a collection of Shape...

Building the Chart

To use the SimpleChart, you must add one or more BarItem objects, and then call the public RebuildChart() method. This allows the client application to control exactly when the chart is generated. Instead of using the RebuildChart() method, you could track changes to the BarItem collection, and fire an event to notify the SimpleChart. The SimpleChart could then rebuild the chart each time a bar is added, removed, or changed. However, this approach hampers performance, because it causes the...

Authentic Dragand Drop

Real drag-and-drop operations are quite a bit different from fake ones. Essentially, they work like this 1. The user clicks a control (or a specific region inside a control) and holds down the mouse button. At this point, some information is set aside, and a drag-and-drop operation begins. 2. The user moves the mouse over another control. If this control can accept the current type of content (for example, a picture or text), the mouse cursor changes to a special drag-and-drop icon. Otherwise,...

Main Menu

Now that you've learned how to create a drop-down menu in a ToolStrip, you know almost everything you need to know to create main menus and context menus. Both controls use a similar set of ToolStripMenuItem objects. The only difference is the top-level container. To create a main menu, you begin by adding a MenuStrip to your form. It's usually enough to dock the MenuStrip to the top of your window, above any other docked ToolStrip objects. However, the MenuStrip can be placed in a...

Validating with Regular Expressions

To validate regular expressions in .NET, you can use the Regex class from the System.Text. RegularExpressions namespace. When you create this class, you specify the regular expression you want to use as a constructor argument. You can then call the IsMatch() method to check if a given string (like the text in a text box) matches the regular expression. Tip When you use validation with the Regex class, make sure your expression starts with the A metacharacter (representing the start of the...

Vb6 Form Ancestor Master Detail

Pens class, 223, 226 data access component, 268-269 data binding, 263 See also .NET data binding .NET data binding, 264-265 and DataGridView class, 524 automatic data binding, 304 binding directly to a custom object, 310-312 binding directly to a database, 304-309 using a strongly typed DataSet, 309-310 basic data binding, 266 binding to a grid, 272-273 binding to a list, 270-272 binding to any control, 273-274 data access component, 268-269 data consumers, 267 data providers, 267 single-value...

Detecting Mouse Clicks

Dealing with mouse clicks is an intricate issue. To determine what should happen, the application needs to determine which shape was clicked. The best approach is to follow these steps 1. Check if there is a currently selected shape. If there is, test for a hit on the focus square. This has highest precedence. 2. If there's no hit on the focus square, loop through all the shapes and perform a hit test on each one (checking both the surface and the border). This technique is easy thanks to the...

Publishing for a Web Server

You can create an installation for a Web server on a local intranet or the Internet. Visual Studio will generate an HTML file named publish.htm that simplifies the process. Users request this page in a browser, and click a link to download and install the application. You have several options for transferring your files to a Web server. If you want to take a two-step approach (publish the files locally and then transfer them to the right location), you simply need to copy the files from the...

Design Time Support for Custom Controls

The custom controls you have explored so far are full of promise. Being able to drop a tool-like directory browser or thumbnail viewer directly into your application without writing a line of extra code is a remarkable advantage. However, even though your custom code might work perfectly at runtime, that doesn't mean it will behave itself at design time. Common problems include properties that you can't edit at design time, and properties that are mysteriously reset when you recompile the...

Document View Architecture

Many developers will recognize document-view architecture as a staple of MFC design. In .NET, the emphasis is less critical because custom form classes can be equipped with most of the intelligence they need (as you saw in the multiple-window refresh example), and don't require an additional separation between the document and the view. Tasks that typically required views, like scrolling, are dealt with effortlessly with the built-in smarts of most .NET controls. On the other hand, there are...

An Owner Drawn Tree View

The TreeView and the ListView are two controls that developers commonly want to change. In .NET 1.x, this feat ranged from difficult to nearly impossible because of the way the TreeView and ListView interact with the Win32 API. (In fact, overriding the OnPaint() method for these controls has no effect.) As a result, developers who needed to change an aspect of the control's appearance (for example, giving the TreeView the ability to support multiple selections) were forced to create look-alike...

Visual Styles

A significant gap in the ControlPaint class is that it doesn't take visual style into account. If you're using Windows XP (or you have visual styles enabled for Windows 2003 Server), you have the ability to display modern interfaces with a slick new look. Painting an old-fashioned legacy control ruins the effect. .NET 2.0 introduces a solution to this problem with a new System.Windows.Forms. VisualStyles namespace that wraps the visual styles API. Unfortunately, because the API uses a radically...

Column Headers

Another reasonable change is to clean up the header text shown in each column. For example, the title Order Date looks more professional than the field name OrderDate. This change is easy enough to make. You simply need to retrieve the appropriate DataGridViewColumn from the DataGridView.Columns collection, and modify the header cell accordingly Order ID Writing this sort of code risks embedding a lot of database-specific code into your form class, which is never a good idea. One possible...

Saving and Restoring Form Location

A common requirement for a form is to remember its last location. Usually, this information is stored in the registry. The code that follows shows a helper class that automatically stores information about a form's size and position using a key based on the name of a form. public static string RegPath Software App public static void SaveSize(System.Windows.Forms.Form frm) Create or retrieve a reference to a key where the settings will be stored. RegistryKey key key.SetValue(Height, frm.Height)...