- •Contents
- •What Is C#?
- •C# Versus Other Programming Languages
- •Preparing to Program
- •The Program Development Cycle
- •Your First C# Program
- •Types of C# Programs
- •Summary
- •Workshop
- •C# Applications
- •Basic Parts of a C# Application
- •Structure of a C# Application
- •Analysis of Listing 2.1
- •Object-Oriented Programming (OOP)
- •Displaying Basic Information
- •Summary
- •Workshop
- •Variables
- •Using Variables
- •Understanding Your Computer’s Memory
- •C# Data Types
- •Numeric Variable Types
- •Literals Versus Variables
- •Constants
- •Reference Types
- •Summary
- •Workshop
- •Types of Operators
- •Punctuators
- •The Basic Assignment Operator
- •Mathematical/Arithmetic Operators
- •Relational Operators
- •Logical Bitwise Operators
- •Type Operators
- •The sizeof Operator
- •The Conditional Operator
- •Understanding Operator Precedence
- •Converting Data Types
- •Understanding Operator Promotion
- •For Those Brave Enough
- •Summary
- •Workshop
- •Controlling Program Flow
- •Using Selection Statements
- •Using Iteration Statements
- •Using goto
- •Nesting Flow
- •Summary
- •Workshop
- •Introduction
- •Abstraction and Encapsulation
- •An Interactive Hello World! Program
- •Basic Elements of Hello.cs
- •A Few Fundamental Observations
- •Summary
- •Review Questions
- •Programming Exercises
- •Introduction
- •Essential Elements of SimpleCalculator.cs
- •A Closer Look at SimpleCalculator.cs
- •Simplifying Your Code with Methods
- •Summary
- •Review Questions
- •Programming Exercises
- •Introduction
- •Lexical Structure
- •Some Thoughts on Elevator Simulations
- •Concepts, Goals and Solutions in an Elevator Simulation Program: Collecting Valuable Statistics for Evaluating an Elevator System
- •A Deeper Analysis of SimpleElevatorSimulation.cs
- •Class Relationships and UML
- •Summary
- •Review Questions
- •Programming Exercises
- •The Hello Windows Forms Application
- •Creating and Using an Event Handler
- •Defining the Border Style of the Form
- •Adding a Menu
- •Adding a Menu Shortcut
- •Handling Events from Menus
- •Dialogs
- •Creating Dialogs
- •Using Controls
- •Data Binding Strategies
- •Data Binding Sources
- •Simple Binding
- •Simple Binding to a DataSet
- •Complex Binding of Controls to Data
- •Binding Controls to Databases Using ADO.NET
- •Creating a Database Viewer with Visual Studio and ADO.NET
- •Resources in .NET
- •Localization Nuts and Bolts
- •.NET Resource Management Classes
- •Creating Text Resources
- •Using Visual Studio.NET for Internationalization
- •Image Resources
- •Using Image Lists
- •Programmatic Access to Resources
- •Reading and Writing RESX XML Files
- •The Basic Principles of GDI+
- •The Graphics Object
- •Graphics Coordinates
- •Drawing Lines and Simple Shapes
- •Using Gradient Pens and Brushes
- •Textured Pens and Brushes
- •Tidying up Your Lines with Endcaps
- •Curves and Paths
- •The GraphicsPath Object
- •Clipping with Paths and Regions
- •Transformations
- •Alpha Blending
- •Alpha Blending of Images
- •Other Color Space Manipulations
- •Using the Properties and Property Attributes
- •Demonstration Application: FormPaint.exe
- •Why Use Web Services?
- •Implementing Your First Web Service
- •Testing the Web Service
- •Implementing the Web Service Client
- •Understanding How Web Services Work
- •Summary
- •Workshop
- •How Do Web References Work?
- •What Is UDDI?
- •Summary
- •Workshop
- •Passing Parameters and Web Services
- •Accessing Data with Web Services
- •Summary
- •Workshop
- •Managing State in Web Services
- •Dealing with Slow Services
- •Workshop
- •Creating New Threads
- •Synchronization
- •Summary
- •The String Class
- •The StringBuilder Class
- •String Formatting
- •Regular Expressions
- •Summary
- •Discovering Program Information
- •Dynamically Activating Code
- •Reflection.Emit
- •Summary
- •Simple Debugging
- •Conditional Debugging
- •Runtime Tracing
- •Making Assertions
- •Summary
GDI+: The .NET Graphics Interface
341
CHAPTER 3.5
LISTING 3.5.3 Continued
55:button1 = new Button();
56:button1.Location=new Point(5,5);
57:button1.Size=new Size(50,20);
58:button1.Text = “Caps”;
59:button1.Click+=new EventHandler(OnClickedButton1);
60:this.Controls.Add(button1);
61:
62: } 63:
64:static void Main()
65:{
66:Application.Run(new drawstar());
67:}
68:};
Compile this program with the following command line:
csc /t:winexe drawstar.cs
When you run the program, you will see a button in the top-left corner of the window, click it to change to rounded end caps. There are 11 different line cap styles altogether, including a custom style.
Already you can see that GDI+ is a great improvement over good old trusty GDI, and we’ve only really looked at lines and rectangles. Let’s now look at curves, paths, and splines.
Curves and Paths
GDI has had Bezier curves and temporary paths for some time. GDI+ expands these capabilities by providing a rich set of functionality for curves and a persistent path object.
The simplest form is the curve drawn from an array of points. The curve is drawn so that it passes through each point on the array. The tension of the curve for any particular point is controlled by the positions of the points on either side of it in the array. The true Bezier curve has two points associated with each node—a position and a control point. Tension of the curve is determined by the relationship of the control point to the direction of the line.
Listing 3.5.4 illustrates the use of the Graphics.DrawCurve method by creating a set of positions that bounce around in a rectangular area onscreen. A curve, or Cardinal Spline, is drawn along this array of points, and you can select the tension of the curve with a slider.
3.5
T GDI+:RAPHICSGNTERFACEI . HE NET
Windows Forms
342
PART III
LISTING 3.5.4 DrawCurve.cs: Using the DrawCurve Method
1:using System;
2:using System.Drawing;
3:using System.Drawing.Drawing2D;
4:using System.Collections;
5:using System.ComponentModel;
6:using System.Windows.Forms;
7:using System.Data;
8:
9:namespace Curves
10:{
11:/// <summary>
12:/// This simple object bounces points
13:/// around a rectangular area.
14:/// </summary>
15:class Bouncer
16:{
17:int dirx;
18:int diry;
19:int X;
20:int Y;
21:
22: Size size; 23:
24:public Bouncer()
25:{
26:dirx=diry=1;
27:}
28:
29:public void Move()
30:{
31:X+=dirx;
32:Y+=diry;
33:
34:if(X<=0 || X>=size.Width)
35:dirx*=-1;
36:
37:if(Y<=0 || Y>=size.Height)
38:diry*=-1;
39:}
40:
41:public Point Position
42:{
43:get{return new Point(X,Y);}
44:set{X=value.X; Y=value.Y;}
45:}
GDI+: The .NET Graphics Interface
343
CHAPTER 3.5
LISTING 3.5.4 Continued
46: |
|
47: |
public Size Size |
48: |
{ |
49: |
get{ return size;} |
50: |
set{size = value;} |
51: |
} |
52: |
} |
53: |
|
54: |
/// <summary> |
55: |
/// Summary description for Form1. |
56: |
/// </summary> |
57: |
public class Curves : System.Windows.Forms.Form |
58: |
{ |
59: |
|
60: |
Timer bounce,paint; |
61: |
TrackBar trk; |
62: |
|
63: |
Bouncer[] bouncers; |
64: |
|
65: |
void OnTickBounce(object sender, EventArgs e) |
66: |
{ |
67: |
foreach(Bouncer b in bouncers) |
68: |
b.Move(); |
69: |
} |
70: |
|
71: |
void OnTickPaint(object sender, EventArgs e) |
72: |
{ |
73: |
Invalidate(); |
74: |
} |
75: |
|
76: |
public void OnPaint(object sender, PaintEventArgs e) |
77: |
{ |
78: |
Pen p=new Pen(Color.Red,10); |
79: |
SolidBrush br=new SolidBrush(Color.Blue); |
80: |
Point[] points = new Point[bouncers.Length]; |
81: |
int i=0; |
82: |
// need to translate our bouncers to an array of points |
83: |
foreach(Bouncer b in bouncers) |
84: |
points[i++]=b.Position; |
85: |
//Draw the curve |
86: |
e.Graphics.DrawCurve(p,points,0,points.Length- |
1,(float)trk.Value);
87://now draw the nodes in the curve.
88:foreach(Point pn in points)
89:e.Graphics.FillEllipse(br,pn.X-5,pn.Y-5,10,10);
3.5
T GDI+:RAPHICSGNTERFACEI . HE NET
Windows Forms
344
PART III
LISTING 3.5.4 Continued
90:p.Dispose();
91:br.Dispose();
92:}
93:
94:public Curves()
95:{
96:this.Paint+=new PaintEventHandler(OnPaint);
97:// A timer to manage the bouncing
98:bounce=new Timer();
99:bounce.Interval=5;
100:bounce.Tick+=new EventHandler(OnTickBounce);
101:// A timer to manage the painting refresh
102:paint=new Timer();
103:paint.Interval=100;
104:paint.Tick+=new EventHandler(OnTickPaint);
105:// Random number generator for initial positions
106:Random r=new Random();
107:// the form initial size
108:this.Size=new Size(800,600);
109://iniialize an array of bouncing points
110:bouncers = new Bouncer[6];
111:for(int i=0;i<6;i++)
112:{
113:bouncers[i]=new Bouncer();
114:bouncers[i].Position=new Point(r.Next(800),r.Next(600));
115:bouncers[i].Size=new Size(800,600);
116:}
117:// turn on the timers
118:bounce.Enabled=true;
119:paint.Enabled=true;
120://create a trackbar for the line tension
121:trk = new TrackBar();
122:trk.Location=new Point(5,25);
123:trk.Size=new Size(100,20);
124:trk.Minimum=1;
125:trk.Maximum=10;
126:trk.Value=2;
127:this.Controls.Add(trk);
128://and label it nicely for the user
129:Label lb=new Label();
130:lb.Location=new Point(5,5);
131:lb.Size=new Size(100,20);
132:lb.Text=”Curve tension”;
133:this.Controls.Add(lb);
134:}
GDI+: The .NET Graphics Interface
345
CHAPTER 3.5
LISTING 3.5.4 Continued
135:
136:static void Main()
137:{
138:Application.Run(new Curves());
139:}
140:}
141:}
Compile Listing 3.5.4 with the following command line:
Csc /t:winexe drawcurve.cs
The work is done by two timers and a paint handler. Timer #1 (lines 98 and 65–69) makes the positions of the curve nodes bounce around the screen. Timer #2 (lines 102 and 71–74) invalidates the screen so that the painting is not done too frequently. The paint handler (lines 76–90) creates an array of points from the bounce object; sadly, Point is a sealed class so you cannot inherit from it, which would have been useful. Then line 86 draws the curve, the tension of which depends on the position of the TrackBar control. To illustrate where the individual points are, lines 88 and 89 draw them in blue. This demonstration clearly shows how line tension works for the simple curve.
Figure 3.5.3 shows the DrawCurves application running.
FIGURE 3.5.3
Drawing a curve with tension.
3.5
T GDI+:RAPHICSGNTERFACEI . HE NET
A Bezier Spline is somewhat different. For each line segment, two points define the start and end of the line, and another two determine the control points that add the line tension and curvature. Listing 3.5.5 shows how a Bezier curve is used.
Windows Forms
346
PART III
LISTING 3.5.5 Beziercurves.cs: Using the Bezier Curve
1:using System;
2:using System.Drawing;
3:using System.Drawing.Drawing2D;
4:using System.Collections;
5:using System.ComponentModel;
6:using System.Windows.Forms;
7:using System.Data;
8:
9:namespace Curves
10:{
11:/// <summary>
12:/// This simple object bounces points
13:/// around a rectangular area.
14:/// </summary>
15:class Bouncer
16:{
17:int dirx;
18:int diry;
19:public int X;
20:public int Y;
21:
22: Size size; 23:
24:public Bouncer()
25:{
26:dirx=diry=1;
27:}
28:
29:public void Move()
30:{
31:X+=dirx;
32:Y+=diry;
33:
34:if(X<=0 || X>=size.Width)
35:dirx*=-1;
36:
37:if(Y<=0 || Y>=size.Height)
38:diry*=-1;
39:}
40:
41:public Point Position
42:{
43:get{return new Point(X,Y);}
44:set{X=value.X; Y=value.Y;}
45:}
GDI+: The .NET Graphics Interface
CHAPTER 3.5
LISTING 3.5.5 Continued
46:
47:public Size Size
48:{
49:get{ return size;}
50:set{size = value;}
51:}
52:}
53:
54:/// <summary>
55:/// Summary description for Form1.
56:/// </summary>
57:public class BezierCurves : System.Windows.Forms.Form
58:{
59:
60:Timer bounce,paint;
61:63: Bouncer[] bouncers;
63:void OnTickBounce(object sender, EventArgs e)
64:{
65:foreach(Bouncer b in bouncers)
66:b.Move();
67:}
68:
69:void OnTickPaint(object sender, EventArgs e)
70:{
71:Invalidate();
72:}
73:
74:public void OnPaint(object sender, PaintEventArgs e)
75:{
76:Pen p=new Pen(Color.Red,10);
77:p.StartCap=LineCap.DiamondAnchor;
78:p.EndCap=LineCap.ArrowAnchor;
79:SolidBrush br=new SolidBrush(Color.Blue);
80://Draw the curve
81:e.Graphics.DrawBezier(p,new Point(550,300),
82: |
bouncers[0].Position, |
83: |
bouncers[1].Position, |
84: |
new Point(50,300)); |
85://now draw the nodes in the curve.
86:foreach(Bouncer b in bouncers)
87:e.Graphics.FillEllipse(br,b.X-5,b.Y-5,10,10);
88://and show the relation between the bouncing node
89://and the bezier end point
347
3.5
T GDI+:RAPHICSGNTERFACEI . HE NET
Windows Forms
348
PART III
LISTING 3.5.5 Continued
90:p=new Pen(Color.Black,1);
91:p.DashStyle=DashStyle.DashDotDot;
92:e.Graphics.DrawLine(p,bouncers[0].Position,new Point(550,300));
93:e.Graphics.DrawLine(p,bouncers[1].Position,new Point(50,300));
94:p.Dispose();
95:}
96:
97:public BezierCurves()
98:{
99:this.Paint+=new PaintEventHandler(OnPaint);
100:// A timer to manage the bouncing
101:bounce=new Timer();
102:bounce.Interval=5;
103:bounce.Tick+=new EventHandler(OnTickBounce);
104:// A timer to manage the painting refresh
105:paint=new Timer();
106:paint.Interval=100;
107:paint.Tick+=new EventHandler(OnTickPaint);
108:// Random number generator for initial positions
109:Random r=new Random();
110:// the form initial size
111:this.Size=new Size(800,600);
112://iniialize an array of bouncing points
113:bouncers = new Bouncer[2];
114:for(int i=0;i<2;i++)
115:{
116:bouncers[i]=new Bouncer();
117:bouncers[i].Position=new Point(r.Next(800),r.Next(600));
118:bouncers[i].Size=new Size(800,600);
119:}
120:// turn on the timers
121:bounce.Enabled=true;
122:paint.Enabled=true;
123:}
124:
125:static void Main()
126:{
127:Application.Run(new BezierCurves());
128:}
129:}
130: }