Getting up to Speed in .NET
Total Page:16
File Type:pdf, Size:1020Kb
Getting Up to Speed in .NET
The purpose of this lecture is to show you how to do in .NET some of the things you already know how to do in MFC, specifically
create and respond to menus draw graphic output such as rectangles, ellipses, etc. draw text in a specified size, font, and color
The basic ideas are not changed, but the syntax is changed and the Visual Studio interface is sometimes different. In many cases things are simpler than in MFC. You will see that it won’t take you long to transfer your knowledge from MFC to .NET.
Some of the differences are due to using C# instead of C++. There are no header files, and there is the systematic use of namespaces. There are no worries about memory leaks and when or whether to delete objects. There are no classes on the stack, so there are no worries about whether to pass by reference or by value.
Some of the differences are due to using .NET to directly produce programs, instead of using the underlying Win32 API. Now there is no .rc file. When you use a dialog or menu editor, it produces initialization code in your form class, as we will see, rather than text in the .rc file. Many differences are due to the fact that the FCL was designed from the beginning in an object- oriented style, rather than being pasted on to the Win32 API after the fact. This is evident, for example, in the treatment of colors and fonts.
Some of the differences are cosmetic (programming interface only), e.g. double-clicking to get to the “code behind” rather than clicking and choosing several times to create a message handler. Graphics
Graphics in .NET is done through GDI+. The plus sign is supposed to indicate that the new system is better than GDI.
Your form class replaces your Doc and View classes. The document-view architecture is MFC-specific, and is dead in .NET. Right-click your form and open its property sheet. You’ll see the familiar lightning bolt for events. (Note: You can’t get to that same place by right-clicking your Form class in Class View. You must right-click the form in the form editor.)
Look down the list of events and you’ll find Paint. Double-click it (don’t try to use the list box as for MFC). You’ll be taken to edit Form1_Paint, which is what corresponds to OnDraw. The parameters of this function look like this:
Form1_Paint(object sender, System.Windows.Forms.PaintEventArgs e)
Where’s my pointer to a device context? In C#, as in Java, every class is passed by reference, so there is no pointer syntax (no & and no *). What corresponds to a device context is a Graphics object—there is a Graphics class. You get a Graphics object passed in as e.graphics, where e is the PaintEventArgs object passed as the second parameter to Form1_Paint.
Here’s a piece of sample code that draws a rectangle and some text, showing the use of fonts as well: private void Form1_Paint(object sender, System.Windows.Forms.PaintEventArgs e) { Pen redPen = new Pen(Color.Red, 1); // Draw rectangle with GDI+. e.Graphics.DrawRectangle(redPen, 10, 10, 100, 50); // Create string to draw. String drawString = "Damn the torpedoes, full speed ahead!"; // Create font and brush. Font drawFont = new Font("Arial", 16); SolidBrush drawBrush = new SolidBrush(Color.Black); // Create point for upper-left corner of drawing. float x = 50.0F; float y = 70.0F; // Set format of string. StringFormat drawFormat = new StringFormat(); // drawFormat.FormatFlags = StringFormatFlags.DirectionVertical; // Draw string to screen. e.Graphics.DrawString(drawString, drawFont, drawBrush, x, y, drawFormat); }
Here’s a screen shot of the running program (it also shows the menu, which we haven’t added yet, but will soon).
You can look these functions up in the documentation, either by using F1 or using Contents | Visual Studio.NET |.NET Framework | Reference|Class Library as shown in the next picture. Note that instead of the RGB macro, there is a Color class with some predefined constants for various colors. Note (using autocompletion) that there are a lot of overloaded versions of DrawString. Uncomment the line that assigns a value to drawFormat and see what it does to your output.
A Graphics object is similar to a device context except for one thing: it doesn’t come equipped with a font. You must create a font and pass it to DrawString. Also, SetTextColor is gone—DrawString uses a brush like every other Graphics function.
Note that since C# has garbage collection, we don’t have to think about memory leaks or about destroying brushes. Also, the business of “selecting” pens and brushes is history: but now, we do have to pass pens and brushes as parameters to all the drawing functions that need them.
Here’s the promised picture of how to find the documentation on FCL:
Menus Now let’s see how to put a menu on our program. In .NET, a menu is just another object that you can add to your form. You’ll find Main Menu listed in the Toolbox along with the controls. Drag one to your form. Now you’ll recognize the menu editor functionality that you used when making MFC programs—you can type the menu items in just as you are used to doing. To add the handlers for these menu items, just double click the menu items in the form editor, the same as you did for the edit boxes in the calculator example. I added a Color menu with two choices, Red and Blue. Before adding the handlers, right-click each menu item and choose Edit Names. Give them names like menuRed, menuBlue, etc. Otherwise you’ll end up with MenuItem1, MenuItem2, etc. And if you wait until you’ve added the handler and then decide to change the names, there are lot of places where it needs to be changed.
Notice that since there are no header files and no preprocessor in C#, menus and controls get names rather than #-defined numbers as in MFC.
Let’s use the newly created menu to change the color in which the rectangle is drawn. To do that, we will need a member variable for the color. It seems that the easiest way to add a member variable is just to type in the definition using the text editor. Go to where the other member variables of your form are and just type. Since there is no header file, all the code is in one place and it is easy to add a variable:
private System.Windows.Forms.MenuItem menuBlue; private System.Windows.Forms.MenuItem menuRed; private Color m_Color = Color.Red;
The first two lines were already there, added by Visual Studio’s form editor. The third one is the one to type in.
Now, you can double-click your menu items and add handlers like this one: private void menuBlue_Click(object sender, System.EventArgs e) { m_Color = Color.Blue; Invalidate(); } Bitmaps
You can add a PictureBox control and display an image in it. Just go to the property sheet and find the Image property. The PictureBox control can take a .jpg or .gif as well as a .bmp. You can even set the Picture Box to change the image it displays at run time. The following code looks for the image in MyDocuments. You could set the path explicitly. private void LoadNewPict() { // Note the escape character used (@) when specifying the path. pictureBox1.Image = Image.FromFile (System.Environment.GetFolderPath (System.Environment.SpecialFolder.Personal) + @"\MonaLisa.bmp"); }
Note that when using a PictureBox this way, with the Image.FromFile method, the image is not compiled into the program file. The image file must be present at run time. You could use a PictureBox and code shown above for fonts to write the last midterm program, Travel, in .NET.
Survey of the FCL
So far, we have looked at a few classes and methods in the namespaces System.Windows.Forms and System.Drawing. The following table will give you an idea of the scope of the FCL. (Credit: Jeff Richter’s book, Applied Microsoft .NET Framework Programming.)
Namespace Purpose System.Collections stacks, queues, hash tables, etc. System.Diagnostics help with debugging System.Drawing 2D graphics for Windows Forms System.EnterpriseServices for a web server—managed transactions, security, object pooling, etc. System.Globalization National language support (string compare, formatting, calendar) System.IO stream IO, directories and files System.Management help with network management System.Net network communications System.Reflection inspection of metadata, late binding System.Resources connections to databases System.Runtime.InteropServices allows managed code to access unmanaged code such as COM components and Win32 DLLs System.Runtime.Remoting accessing types remotely System.Runtime.Serialization serialization System.Security protect data and resources System.Text different encodings, e.g. Unicode System.Threading asynchronous operations and synchronizing access to resources System.XML XML
The Common Type System (CTS)
Code written in different languages can compile to MSIL byte code to be run by the CLR. This is made possible in part by a specification of the types to be used in MSIL. The different languages must, for example, compile an int to the same size integer. Programming in C#, you can declare
System.Int32 n; int n; and the same MSIL code will be generated.
Similarly, string s; System.String s; generate the same code. So if you’ve put in using namespace System; then string s; String s; also generate the same code. Types in the CTS go beyond the basic “value types” such as int and float, and allow types that are like classes: they can have fields, methods, properties, and events. In object-oriented programming, we have fields and methods. Properties are similar to fields, but implemented with Get and Set methods. Events are what makes the difference between “object- oriented programming” and “event-driven programming”. All types in the CTS inherit from System.Object. This type provides certain basic functionality, including
comparing two instances for equality query the true type of the (derived) object perform a shallow (bitwise) copy obtain a string representation of the instance object’s current state (“state” means the current values of all fields and properties)