![](/user_photo/2706_HbeT2.jpg)
C# ПІДРУЧНИКИ / c# / Hungry Minds - C# Bible
.pdf![](/html/2706/1080/html_9cKTTofkDS.dOaC/htmlconvd-XeoWSs401x1.jpg)
class FileTestClass
{
private |
BinaryWriter |
Writer; |
private |
FileStream |
BinaryFile; |
public FileTestClass()
{
BinaryFile = new FileStream("test.dat", FileMode.Create, FileAccess.ReadWrite);
Writer = new BinaryWriter(BinaryFile);
}
public void WriteBinaryData()
{
Writer.Write('a');
Writer.Write(123);
Writer.Write(456.789); Writer.Write("test string");
}
}
class MainClass
{
static public void Main()
{
FileTestClass FileTest = new FileTestClass();
FileTest.WriteBinaryData();
}
}
The code in Listing 25-4 is structured with a class design similar to the design in Listing 25-3. The code contains a MainClass and a FileTestClass. The constructor of the FileTestClass class in Listing 25-4 creates a file stream and then creates a BinaryWriter object. A reference to the file stream is passed to the constructor of the BinaryWriter object, which sets up the relationship between the binary writer and the stream to which it writes its data. In Listing 25- 4, all data written to the binary writer eventually makes its way to the file stream set up in the constructor.
The WriteBinaryData() method writes a character, an integer, a double, and a string to the underlying stream. The BinaryWriter class implements several overloads of a method named Write(). The Write() method overloads support the writing of the following data types to the writer class:
•Booleans
•Bytes
•Arrays of bytes
•Characters
•Arrays of characters
•Decimal values
•Double values
•Signed and unsigned short integer values
•Signed and unsigned integer values
•Signed and unsigned long integer values
![](/html/2706/1080/html_9cKTTofkDS.dOaC/htmlconvd-XeoWSs402x1.jpg)
•Sbytes
•Floating-point values
•Strings
If you compile and execute the code in Listing 25-4, a file called test.dat is created. You can examine the contents of the new file in a hex editor to verify that binary representations of values were written to the file.
Reading from streams with BinaryReader
Listing 25-5 adds the BinaryReader class to the code in Listing 25-5. This class reassembles stream bytes back into their constituent data types and returns the values to the caller.
Listing 25-5: Working with the BinaryReader Class
using System; using System.IO;
class FileTestClass |
|
{ |
Reader; |
private BinaryReader |
|
private BinaryWriter |
Writer; |
private FileStream |
BinaryFile; |
public FileTestClass()
{
BinaryFile = new FileStream("test.dat", FileMode.Create, FileAccess.ReadWrite);
Writer = new BinaryWriter(BinaryFile); Reader = new BinaryReader(BinaryFile);
}
public void ReadBinaryData()
{
char ReadCharacter; double ReadDouble; int ReadInteger; string ReadString;
BinaryFile.Seek(0, SeekOrigin.Begin);
ReadCharacter = Reader.ReadChar();
ReadInteger = Reader.ReadInt32();
ReadDouble = Reader.ReadDouble();
ReadString = Reader.ReadString();
Console.WriteLine("Character: {0}", ReadCharacter); Console.WriteLine("Integer: {0}", ReadInteger); Console.WriteLine("Double: {0}", ReadDouble); Console.WriteLine("String: {0}", ReadString);
}
public void WriteBinaryData()
{
Writer.Write('a');
Writer.Write(123);
Writer.Write(456.789); Writer.Write("test string");
}
![](/html/2706/1080/html_9cKTTofkDS.dOaC/htmlconvd-XeoWSs403x1.jpg)
}
class MainClass
{
static public void Main()
{
FileTestClass FileTest = new FileTestClass();
FileTest.WriteBinaryData();
FileTest.ReadBinaryData();
}
}
Unlike the BinaryWriter class, which contained one overloaded method for all operations, the BinaryReader class contains separate read methods for each data type. The code in Listing 25- 5 uses some of these read methods, such as ReadChar() and ReadInt32(), to read values from the stream written in the WriteBinaryData() method. The values read from the stream are sent to the console. Executing Listing 25-5 should produce the following output on the console:
Character: a
Integer: 123
Double: 456.789
String: test string
Writing Well-Formed XML Using the XmlWriter Stream
Streams can do more than simply read from and write to various data streams. They can also add value to the data being sent through the stream. A good example of this technology is the XmlWriter class, which encapsulates data sent to a stream within well-formed XML elements. The result is a well-formed XML document that can be processed by any XML document processor, as shown in Listing 25-6.
Listing 25-6: Writing XML with the XmlWriter Class
using System; using System.IO; using System.Xml;
class XMLStreamWriterClass
{
private XmlTextWriter XmlWriter;
public void WriteXML()
{
XmlWriter = new XmlTextWriter(Console.Out);
XmlWriter.WriteStartDocument(); XmlWriter.WriteComment("This XML document was automatically
generated by C# code.");
XmlWriter.WriteStartElement("BOOK"); XmlWriter.WriteElementString("TITLE", "C# Bible"); XmlWriter.WriteElementString("AUTHOR", "Jeff Ferguson"); XmlWriter.WriteElementString("PUBLISHER", "Wiley");
![](/html/2706/1080/html_9cKTTofkDS.dOaC/htmlconvd-XeoWSs404x1.jpg)
XmlWriter.WriteEndElement();
XmlWriter.WriteEndDocument();
}
}
class MainClass
{
static public void Main()
{
XMLStreamWriterClass XMLStreamWriter = new XMLStreamWriterClass();
XMLStreamWriter.WriteXML();
}
}
The code in Listing 25-6 creates a new instance of the XmlWriter class and associates it with the console's output stream, which sends the stream's output to the application console. The code simply calls various methods in the XmlWriter class to output data, and the methods surround the data with XML elements names that are specified when the method is called. Take a look at the following line from Listing 25-6:
XmlWriter.WriteElementString("AUTHOR", "Jeff Ferguson");
This call instructs the XmlWriter class to write an XML element called <AUTHOR>, which has a value of Brian Patterson, to the stream output device. The method's implementation supplies the XML end tag automatically.
Compiling and executing the code in Listing 25-6 sends the following well-formed XML document to the application console:
<?xml version="1.0" encoding="IBM437"?>
<!--This XML document was automatically generated by C# code.--> <BOOK>
<TITLE>C# Bible</TITLE> <AUTHOR>Jeff Ferguson</AUTHOR> <PUBLISHER>Wiley</PUBLISHER> </BOOK>
Summary
Streams provide powerful support for both synchronous and asynchronous I/O for your C# applications. Streams operate at the byte level and require you to read and write blocks of bytes. Readers and writers encapsulate streams and provide access to data at a higher level.
You can use readers and writers to work with standard C# data types, enabling the readers and writers to translate between the data type values and their byte representations.
Your C# code will most likely work with readers and writers, as they provide support for working with the standard data types without forcing you to be concerned about translating between a data type value and its binary representation. Streams are available, however, should you feel the need to work with them directly. You might also want to work with streams if the data that you are reading is in a proprietary format that is not supported by the standard reader and writer classes shipped with the .NET Framework. You might also
consider developing your own reader class, derived from the base TextReader or StreamReader classes, and use your class to read from the proprietary format stream.
Chapter 26: Drawing with GDI+
In This Chapter
In Windows, programmatic access to the graphics subsystem was first accomplished using the GDI APIs available since Windows 3.1. GDI offered developers the capability to control any type of user interface element, and this capability has been reworked from the ground up in the .NET Framework. GDI+ has replaced GDI as the API that is used to access the graphics subsystems of Windows. With GDI+, you can access fonts, manipulate any type of image, and work with shapes in your C# applications. To get a complete picture of how to use GDI+ in your applications, you need to understand how to use the Graphics, Pen, Brush, and Color objects. With these four objects, you can accomplish nearly anything you need to do with the GUI and images in .NET. This chapter explores these objects, and familiarizes you with using GDI+ in C#. The available classes in GDI+ could cover their own thousand-page book, so you should still use the SDK as a reference to the more complex and less frequently used graphics functionality not covered in this chapter.
Working with Graphics
When working with GDI+ in .NET, the main object that you need to work with is the Graphics object. The Graphics object is the actual surface that you use to paint shapes, work with images, or display text. Visual Basic 6 and earlier offered limited built-in support for working with graphics, making it difficult for VB developers to write custom graphics applications. The one thing that VB did do was keep track of how forms and the objects on forms were painted on the screen. The AutoRedraw property enabled your forms to let Windows keep track of what was on top of other windows and, if necessary, automatically repaint a form if another form was on top of it for any period of time. You were hidden from having to deal with the actual painting process of the form. In .NET, the exact opposite is true. The Graphics object has no memory of when it was painted or what was painted with it. Therefore, you need to redraw objects as necessary if other windows end up on top of your window. This may seem like a pain, but the PaintEventArgs variable in the Paint event of a form can handle this nicely. If your painting code is kept there, then each time Windows paints the actual form, your objects will be painted correctly.
The following code snippet receives a reference to a Graphics object through the PaintEventArgs variable in the Paint event of a form:
private void Form1_Paint(object sender, System.Windows.Forms.PaintEventArgs p)
{
Graphics g = p.Graphics;
}
You can also create a Graphics object using the CreateGraphics method of a control or form. The following code demonstrates the CreateGraphics method:
private void createManually()
{
Graphics g;
g = this.CreateGraphics;
}
The third and final method of creating a Graphics object is to pass an image file directly to the object when you instantiate it, as the following code demonstrates by grabbing a bitmap image from the file system:
private void createFromFile()
{
Graphics g; Bitmap b;
b = new Bitmap(@"C:\Enterprise.bmp"); g = Graphics.FromImage(b);
}
If you have been adding these snippets to a WindowsForm, it is clear that nothing happens when any of the code executes. To actually implement some functionality, you need to use members of the Graphics class to make things happen.
Note If you create a Graphics object using the CreateGraphics method, you should call Dispose on that object after you finish using it. This ensures that the Graphics object is released from memory.
Table 26-1 lists the properties of the Graphics class, and Table 26-2 lists the available methods of the Graphics class. The Graphics class is located in the System.Drawing namespace, which is added as the default reference when you create a new Windows Forms application. This does not mean that you cannot use Graphics objects in ASP .NET; in fact, you can write extremely optimized image processing applications in ASP .NET using Graphics objects.
|
|
Table 26-1: Graphics Class Properties |
Property |
|
Description |
|
|
|
Clip |
|
Gets or sets a Region object that limits the drawing region of this |
|
|
Graphics object |
|
|
|
ClipBounds |
|
Gets the RectangleF structure that bounds the clipping region of |
|
|
this Graphics object |
|
|
|
CompositingMode |
|
Gets a value that specifies how composited images are drawn to |
|
|
this Graphics object |
|
|
|
CompositingQuality |
|
Gets or sets the rendering quality of composited images drawn to |
|
|
this Graphics object |
|
|
|
DpiX |
|
Gets the horizontal resolution of this Graphics object |
|
|
|
DpiY |
|
Gets the vertical resolution of this Graphics object |
|
|
|
InterpolationMode |
|
Gets or sets the interpolation mode associated with this Graphics |
|
|
object |
|
|
|
IsClipEmpty |
|
Gets a value indicating whether the clipping region of this |
|
|
Graphics object is empty |
|
|
|
|
|
Table 26-1: Graphics Class Properties |
||
|
|
|
|
|
Property |
|
Description |
||
|
|
|
|
|
IsVisibleClipEmpty |
|
Gets a value indicating whether the visible clipping region of this |
||
|
|
Graphics object is empty |
||
|
|
|
|
|
PageScale |
|
Gets or sets the scaling between world units and page units for |
||
|
|
this Graphics object |
||
|
|
|
|
|
PageUnit |
|
Gets or sets the unit of measure used for page coordinates in this |
||
|
|
Graphics object |
||
|
|
|
|
|
PixelOffsetMode |
|
Gets or sets a value specifying how pixels are offset during |
||
|
|
rendering of this Graphics object |
||
|
|
|
|
|
RenderingOrigin |
|
Gets or sets the rendering origin of this Graphics object for |
||
|
|
dithering and for hatch brushes |
||
|
|
|
|
|
SmoothingMode |
|
Gets or sets the rendering quality for this Graphics object |
||
|
|
|
|
|
TextContrast |
|
Gets or sets the gamma correction value for rendering text |
||
|
|
|
|
|
TextRenderingHint |
|
Gets or sets the rendering mode for text associated with this |
||
|
|
Graphics object |
||
|
|
|
|
|
Transform |
|
Gets or sets the world transformation for this Graphics object |
||
|
|
|
|
|
VisibleClipBounds |
|
Gets or sets the bounding rectangle of the visible clipping region |
||
|
|
of this Graphics object |
||
|
|
|
|
|
|
|
Table 26-2: Graphics Class Methods |
||
|
|
|
|
|
Method |
|
|
|
Description |
|
|
|
|
|
AddMetafileComment |
|
|
|
Adds a comment to the current Metafile object |
|
|
|
|
|
BeginContainer |
|
|
|
Saves a Graphics container with the current state of this |
|
|
|
|
Graphics object and opens and uses a new graphics container |
|
|
|
|
|
Clear |
|
|
|
Clears the entire drawing surface and fills it with the |
|
|
|
|
specified background color |
|
|
|
|
|
DrawArc |
|
|
|
Draws an arc representing a portion of an ellipse specified by |
|
|
|
|
a pair of coordinates, a width, and a height |
|
|
|
|
|
DrawBezier |
|
|
|
Draws a Bézier spline defined by four Point structures |
|
|
|
|
|
DrawBeziers |
|
|
|
Draws a series of Bézier splines from an array of Point |
|
|
|
|
structures |
|
|
|
|
|
DrawClosedCurve |
|
|
|
Draws a closed cardinal spline defined by an array of Point |
|
|
|
|
structures |
|
|
|
|
|
DrawCurve |
|
|
|
Draws a cardinal spline through a specified array of Point |
|
|
|
|
structures |
|
|
|
|
|
DrawEllipse |
|
|
|
Draws an ellipse defined by a bounding rectangle specified |
|
|
|
|
by a pair of coordinates, a height, and a width |
|
|
|
|
|
DrawIcon |
|
|
|
Draws the image represented by the specified Icon object at |
|
|
|
|
the specified coordinates |
|
|
|
|
|
DrawIconUnstretched |
|
|
|
Draws the image represented by the specified Icon object |
|
|
|
|
without scaling the image |
|
|
|
|
|
DrawImage |
|
|
|
Draws the specified Image object at the specified location |
|
|
|
|
|
![](/html/2706/1080/html_9cKTTofkDS.dOaC/htmlconvd-XeoWSs408x1.jpg)
|
Table 26-2: Graphics Class Methods |
||
Method |
|
|
Description |
|
|
|
|
|
|
|
and with the original size |
|
|
|
|
DrawImageUnscaled |
|
|
Draws the specified Image object with its original size at the |
|
|
|
location specified by a coordinate pair |
|
|
|
|
DrawLine |
|
|
Draws a line connecting the two points specified by |
|
|
|
coordinate pairs |
|
|
|
|
DrawLines |
|
|
Draws a series of line segments that connect an array of Point |
|
|
|
structures |
|
|
|
|
DrawPath |
|
|
Draws a GraphicsPath object |
|
|
|
|
DrawPie |
|
|
Draws a pie shape defined by an ellipse specified by a |
|
|
|
coordinate pair, a width, and a height and two radial lines |
|
|
|
|
DrawPolygon |
|
|
Draws a polygon defined by an array of Point structures |
|
|
|
|
DrawRectangle |
|
|
Draws a rectangle specified by a coordinate pair, a width, |
|
|
|
and a height |
|
|
|
|
DrawRectangles |
|
|
Draws a series of rectangles specified by Rectangle |
|
|
|
structures |
|
|
|
|
DrawString |
|
|
Draws the specified text string at the specified location with |
|
|
|
the specified Brush and Font objects |
EndContainer
Closes the current graphics container and restores the state of this Graphics object to the state saved by a call to the BeginContainer method
EnumerateMetafile |
|
Sends the records in the specified Metafile object, one at a |
|
|
time, to a callback method for display at a specified point |
|
|
|
ExcludeClip |
|
Updates the clip region of this Graphics object to exclude the |
|
|
area specified by a Rectangle structure |
|
|
|
FillClosedCurve |
|
Fills the interior of a closed cardinal spline curve defined by |
|
|
an array of Point structures |
FillEllipse
Fills the interior of an ellipse defined by a bounding rectangle specified by a pair of coordinates, a width, and a height
FillPath |
|
Fills the interior of a GraphicsPath object |
|
|
|
FillPie |
|
Fills the interior of a pie section defined by an ellipse |
|
|
specified by a pair of coordinates, a width, and a height and |
|
|
two radial lines |
|
|
|
FillPolygon |
|
Fills the interior of a polygon defined by an array of points |
|
|
specified by Point structures |
|
|
|
FillRectangle |
|
Fills the interior of a rectangle specified by a pair of |
|
|
coordinates, a width, and a height |
|
|
|
FillRectangles |
|
Fills the interiors of a series of rectangles specified by |
|
|
Rectangle structures |
|
|
|
FillRegion |
|
Fills the interior of a Region object |
![](/html/2706/1080/html_9cKTTofkDS.dOaC/htmlconvd-XeoWSs409x1.jpg)
|
Table 26-2: Graphics Class Methods |
||
Method |
|
|
Description |
Flush
Forces execution of all pending graphics operations and returns immediately without waiting for the operations to finish
FromHdc |
|
Creates a new Graphics object from the specified handle to a |
|
|
device context |
|
|
|
FromHwnd |
|
Creates a new Graphics object from the specified handle to a |
|
|
window |
|
|
|
FromImage |
|
Creates a new Graphics object from the specified Image |
|
|
object |
|
|
|
GetHalftonePalette |
|
Gets a handle to the current Windows halftone palette |
|
|
|
GetHdc |
|
Gets the handle to the device context associated with this |
|
|
Graphics object |
|
|
|
GetNearestColor |
|
Gets the nearest color to the specified Color structure |
|
|
|
IntersectClip |
|
Updates the clip region of this Graphics object to the |
|
|
intersection of the current clip region and the specified |
|
|
Rectangle structure |
IsVisible
Indicates whether the point specified by a pair of coordinates is contained within the visible clip region of this Graphics object
MeasureCharacterRanges
MeasureString
MultiplyTransform
ReleaseHdc
ResetClip
ResetTransform
Restore
RotateTransform
Save
ScaleTransform
Gets an array of Region objects, each of which bounds a range of character positions within the specified string
Measures the specified string when drawn with the specified Font object
Multiplies the world transformation of this Graphics object and specified the Matrix object parameters
Releases a device context handle obtained by a previous call to the GetHdc method of this Graphics object
Resets the clip region of this Graphics object to an infinite region
Resets the world transformation matrix of this Graphics object to the identity matrix
Restores the state of this Graphics object to the state represented by a GraphicsState object
Applies the specified rotation to the transformation matrix of this Graphics object
Saves the current state of this Graphics object and identifies the saved state with a GraphicsState object
Applies the specified scaling operation to the transformation matrix of this Graphics object by prepending it to the object's transformation matrix
SetClip |
|
Sets the clipping region of this Graphics object to the Clip |
![](/html/2706/1080/html_9cKTTofkDS.dOaC/htmlconvd-XeoWSs410x1.jpg)
|
Table 26-2: Graphics Class Methods |
||
|
|
|
|
Method |
|
|
Description |
|
|
|
|
|
|
|
property of the specified Graphics object |
|
|
|
|
TransformPoints |
|
|
Transforms an array of points from one coordinate space to |
|
|
|
another using the current world and page transformations of |
|
|
|
this Graphics object |
|
|
|
|
TranslateClip |
|
|
Translates the clipping region of this Graphics object by |
|
|
|
specified amounts in the horizontal and vertical directions |
|
|
|
|
TranslateTransform |
|
|
Prepends the specified translation to the transformation |
|
|
|
matrix of this Graphics object |
|
|
|
|
As you can see, the Graphics class provides every possible method that you would ever want to use to work with any type of GUI element. Listing 26-1 uses several of the methods in the Graphics class to produce the output displayed in Figure 26-1.
Figure 26-1: Output from using members of the Graphics class
Note As there is no AutoRedraw property, you still need a way to redraw a form if it is resized. Using the SetStyles method and passing the ControlStyles. ResizeRedraw stylecorrectly calls the Paint method of a form. After the call the InitializeComponent; in your form, you should type SetStyle- (ControlStyles.ResizeRedraw, true) to guarantee that the Paint event will be called when your form is resized. Look up SetStyle in the
.NET Framework SDK to learn more about what you can do with the SetStyle method. Listing 26-1: Using Methods from the Graphics Class
private void drawLine()
{
/* create a Graphics object that can be resued * for each of the samples */
Graphics g;
g = this.CreateGraphics();
// Use the Pen object to create a line
Pen p;
p = new Pen(Color.Red, 50);
/* DrawLine is an overloaded method,
* pass the x1, y1, x2, y2 coordinates */
g.DrawLine(p, 100F, 100F, 500F, 100F);
// draw an icon from the file system
Icon i;
i = new Icon(@"C:\Desktop.ico");