The GDI+ coordinate system is shown on the picture below
AliceBlue AntiqueWhite Aqua Aquamarine Azure Beige Bisque Black BlanchedAlmond Blue BlueViolet Brown BurlyWood CadetBlue Chartreuse Chocolate Coral CornflowerBlue Cornsilk Crimson Cyan DarkBlue DarkCyan DarkGoldenrod DarkGray DarkGreen DarkKhaki DarkMagenta DarkOliveGreen |
DarkOrange DarkOrchid DarkRed DarkSalmon DarkSeaGreen DarkSlateBlue DarkSlateGray DarkTurquoise DarkViolet DeepPink DeepSkyBlue DimGray DodgerBlue Firebrick FloralWhite ForestGreen Fuchsia Gainsboro GhostWhite Gold Goldenrod Gray Green GreenYellow Honeydew HotPink IndianRed Indigo Ivory |
Khaki Lavender LavenderBlush LawnGreen LemonChiffon LightBlue LightCoral LightCyan LightGoldenrodYellow LightGray LightGreen LightPink LightSalmon LightSeaGreen LightSkyBlue LightSlateGray LightSteelBlue LightYellow Lime LimeGreen Linen Magenta Maroon MediumAquamarine MediumBlue MediumOrchid MediumPurple MediumSeaGreen MediumSlateBlue |
MediumSpringGreen MediumTurquoise MediumVioletRed MidnightBlue MintCream MistyRose Moccasin NavajoWhite Navy OldLace Olive OliveDrab Orange OrangeRed Orchid PaleGoldenrod PaleGreen PaleTurquoise PaleVioletRed PapayaWhip PeachPuff Peru Pink Plum PowderBlue Purple Red RosyBrown RoyalBlue |
SaddleBrown Salmon SandyBrown SeaGreen SeaShell Sienna Silver SkyBlue SlateBlue SlateGray Snow SpringGreen SteelBlue Tan Teal Thistle Tomato Transparent Turquoise Violet Wheat White WhiteSmoke Yellow YellowGreen |
| Method | Description | Example |
|---|---|---|
| FromArgb | Creates a color based on red, green and blue components expressed as integers from 0 to 255. Overloaded version allows to specify alhpa, red, green, and blue values. |
my_color = Color::FromArgb(100, 0, 255, 0); |
| FromName | Creates a color from a name, passed as a pointer to a String | my_color = Color::FromName(S"White"); |
| FromKnownColor | Creates a Color structure from the specified pre-defined color. | my_color = Color::FromKnownColor(Color::Khaki); |
We can easily change colors of the form from inside the program, for example, in the constructor of the Form object. To illustrate this, let's get back to our first project and add the lines
this->ForeColor = Color::FromArgb(100, 0, 0, 255); this->BackColor = Color::FromName( S"White" );to the constructor Form1(void) to make it look like
Form1(void)
{
this->ForeColor = Color::FromArgb(100, 0, 0, 255);
this->BackColor = Color::FromName( S"White" );
InitializeComponent();
}
Graphics *gObj = e->Graphics;After this line variable gObj is available to draw shapes on the from.
If we want to create a event-driven graphics, then we need to associate the drawing with events like button clicks, or timer ticks, which do not have their own graphics context. In order to draw, we need to create an instance of the Graphics class by invoking the CreateGraphics() method. For example, inside a button click function it can be done like
Graphics *gObj = this->CreateGraphics();where this refers to the Form object.
Once we created an object of the Graphics type we can start using its methods to draw simple pictures. Some of the methods are
| Method | Description |
|---|---|
Clears the entire drawing surface and fills it with the specified background color.
gObj->Clear( this->BackColor ); |
|
Draws a line from (x1, y1) to (x2, y2). The pen parameter determines the color, style, and
width of the line.
Pen *p = new Pen( Color::Blue );Overloaded |
|
Draws a rectangle of the specified width w and height h. The top-left corner of the rectangle
is located at the point (x, y). The pen parameter determines the color, style, and width of the rectangle.
gObj->DrawRectangle(p, 0, 0, 200, 100);Overloaded. |
|
Draws an ellipse inside the rectangle specified by the top-left corner (x, y), the width w,
and the height h. The pen argument determines the color, style, and width of the ellipse.
gObj->DrawEllipse(p, 0, 0, 200, 100);Overloaded |
|
Draws an arc representing a portion of an ellipse specified by a pair of coordinates, a width, and a height.
The arc starts at the angle start (angle in degrees measured clockwise from the x-axis to the starting point of the arc)
and the size of the arc is sweep (angle in degrees measured clockwise from the startAngle parameter to ending point of the arc).
gObj->DrawArc(p, 0, 0, 100, 100, 90, 30);Overloaded |
|
Draws a pie shape defined by an ellipse specified by a coordinate pair, a width, and a height and two radial lines.
gObj->DrawPie(p, 0, 0, 100, 100, 90, 30);Overloaded |
|
Draws a polygon. The coordinates of each point are specified in an array of Point objects.
This method draws a closed polygon, even if the last point is different from the first one.
Pen *pen = new Pen( Color::DarkBlue, 7); Point points[] = new Point[4]; points[0].X = 50; points[0].Y = 0; points[1].X = 100; points[1].Y = 50; points[2].X = 50; points[2].Y = 100; points[3].X = 0; points[3].Y = 50; gObj->DrawPolygon(pen, points);Overloaded |
|
Draws a solid rectangle of the given width and height. The top-left corner of the rectangle
is located at the point (x, y). The brush attribute defines the fill pattern inside the rectangle.
Brush *brush = new Brush( Color::FromArgb(128, 128, 128, 128) );Overloaded |
|
Draws a filled ellipse inside the given rectangle. Thebrush argument determines the fill pattern
inside the ellipse.
gObj->FillEllipse(brush, 10, 10, 150, 40);Overloaded |
|
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.
gObj->FillPie(brush, 0, 0, 200, 200, 0, -90);Overloaded |
|
Draws a closed solid polygon. The coordinates of each point are specified in an array of Points.
Thebrush argument determines the fill pattern inside the polygon.
Brush *brush = new SolidBrush( Color::Blue ); Point points[] = new Point[4]; points[0].X = 50; points[0].Y = 0; points[1].X = 100; points[1].Y = 50; points[2].X = 50; points[2].Y = 100; points[3].X = 0; points[3].Y = 50; gObj->FillPolygon(brush, points);Overloaded |
The Pen class defines an object used to draw lines and curves. A Pen object draws a line of specified width and style. Use the DashStyle property to draw several varieties of dashed lines. The line drawn by a Pen object can be filled in a variety of fill styles, including solid colors and textures. The fill style depends on brush or texture that is used as the fill object.
The list of some of the public attributes of the Pen class is
| Attribute | Description |
|---|---|
| Alignment | Gets or sets the alignment for this Pen object. |
| Brush | Gets or sets the Brush object that determines attributes of this Pen object. |
| Color | Gets or sets the color of this Pen object. |
| CustomEndCap | Gets or sets a custom cap to use at the end of lines drawn with this Pen object. |
| CustomStartCap | Gets or sets a custom cap to use at the beginning of lines drawn with this Pen object. |
| DashCap | Gets or sets the cap style used at the end of the dashes that make up dashed lines drawn with this Pen object |
| DashOffset | Gets or sets the distance from the start of a line to the beginning of a dash pattern |
| DashPattern | Gets or sets an array of custom dashes and spaces. |
| DashStyle | Gets or sets the style used for dashed lines drawn with this Pen object |
| EndCap | Gets or sets the cap style used at the end of lines drawn with this Pen object |
| PenType | Gets the style of lines drawn with this Pen object. |
| StartCap | Gets or sets the cap style used at the beginning of lines drawn with this Pen object |
| Width | Gets or sets the width of this Pen object. |
Pen *pen = new Pen( Color::FromArgb(100, 0, 0, 100) );Another constructor allows the programmer to assign both the color and the width of the new pen:
Pen *pen = new Pen( Color::Blue, 3 );And finally two more constructors allow us to use a Brush object to create a Pen. One of them takes a pointer to a Brush object only, and the other takes a pointer to a Brush and a width argument:
Pen *pen = new Pen( brush, 12);The Brush property determines how the Pen object draws lines. Lines are drawn as if they are filled rectangles, with the characteristics of the specified Brush object.
Thus, we can specify in the constructor the color and the thickness of the lines we will draw using a pen. To control the style of the lines, we need to use property DashStyle. A DashStyle is an enumeration that represents the style used for dashed lines drawn with this Pen object. Possible values are
| Value | Description |
|---|---|
| Dash | Specifies a line consisting of dashes |
| DashDot | Specifies a line consisting of a repeating pattern of dash-dot |
| DashDotDot | Specifies a line consisting of a repeating pattern of dash-dot-dot |
| Dot | Specifies a line consisting of dots |
| Solid | Specifies a solid line (the default value). |
| Custom | Specifies a user-defined custom dash style. This value specifies that a custom pattern of dashes and spaces, defined by the DashPattern property, make up lines drawn with this Pen object. If the value of this property is DashStyle::Custom and the value of the DashPattern property is a null reference, the pen draws solid lines. |
Pen *dot_pen = new Pen( Color::DarkBlue, 4); dot_pen->DashStyle = DashStyle::Dot; gObj->DrawRectangle(dot_pen, 10, 10, 200, 200);
The Brush class an abstract base class and cannot be instantiated. To create a brush object, we need to use classes derived from Brush, such as
Here are several examples that illustrate how we can use the different types of brushes to fill regions:
Brush *brush = new SolidBrush( Color::LightGreen ); gObj->FillPolygon(brush, points);
Brush *hbrush = new HatchBrush( HatchStyle::ZigZag, Color::Navy, Color::Cyan ); gObj->FillPolygon(hbrush, points);
Bitmap *texture = new Bitmap(10, 10); // create a bitmap for future texture Graphics *temp_gObj = Graphics::FromImage( texture ); // create a graphics object to fill the bitmap SolidBrush *brush = new SolidBrush( Color::LightGreen ); temp_gObj->FillRectangle(brush, 0, 0, 10, 10); brush->Color = Color::Blue; temp_gObj->FillRectangle(brush, 2, 2, 7, 6); brush->Color = Color::Navy; temp_gObj->FillRectangle(brush, 1, 1, 4, 2); Brush *tbrush = new TextureBrush(texture); // create a texture brush gObj->FillPolygon(tbrush, points);
Brush *lgbrush = new LinearGradientBrush(Point(0, 50), Point(100, 50),
Color::DarkBlue, Color::LightGreen );
gObj->FillPolygon(lgbrush, points);
| Property | Description |
|---|---|
| FontFamily | Gets the FontFamily object associated with this Font object. |
| Bold | Gets a value that indicates whether this Font object is bold. |
| Italic | Gets a value that indicates whether this Font object is italic. |
| Strikeout | Gets a value that indicates whether this Font object specifies a horizontal line through the font. |
| Underline | Gets a value that indicates whether this Font object is underlined. |
| Style | Gets style information for this Font object. |
| Height | Gets the line spacing of this font. |
| Size | Gets the em-size of this Font object measured in the unit of this Font object. |
| SizeInPoints | Gets the em-size, in points, of this Font object. |
| Unit | Gets the unit of measure for this Font object. |
| Constructor | Description | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Initializes a new Font object using the specified family and size. The family parameter
is a pointer to an object of the FontFamily class.
An element of the FontFamily class can be created with specifying either a name of the font you would like
to use
FontFamily *family = new FontFamily(S"Arial");or by specifying one of the generic font families (these generic families can be retrieved by static public methods of the FontFamily class: GenericMonospace(), GenericSansSerif(), and GenericSerif()): Drawing::Font *fnt = new Drawing::Font(FontFamily::GenericSansSerif, 32); |
|||||||||||||||||
Similar to the previous one. We specify the family and the size, but in this case we use the name instead of a
FontFamily object. The name of the family is to be contained in a String object. For example,
Drawing::Font *fnt = new Drawing::Font(S"Times New Roman", 32); |
|||||||||||||||||
Similar to the first constructor, but allows to assign a style of the font. The argument style is a parameter
of the FontStyle enumeration type. The possible values of FontStyle are:
Drawing::Font *fnt = new Drawing::Font(FontFamily::GenericSansSerif, 32,
FontStyle::Italic);
we an also combine the styles
Drawing::Font *fnt;
fnt = new Drawing::Font(FontFamily::GenericSansSerif, 32,
static_cast<FontStyle>(FontStyle::Bold + FontStyle::Underline));
|
|||||||||||||||||
This constructor is similar to the previous one, but the family of the font is specified by a string, not an object.
Drawing::Font *fnt = new Drawing::Font(S"Courier", 32, FontStyle::Italic); |
|||||||||||||||||
This constructor allows to specify the units we are measuring the size of the font in. The unit parameter has
the GraphicsUnit enumeration type. The possible values are
Drawing::Font *fnt = new Drawing::Font(FontFamily::GenericSansSerif, 2,
FontStyle::Italic, GraphicsUnit::Inch); |
|||||||||||||||||
style, unit); |
We can also specify the measuring units when we assign the font family by name. |
Now, when we know how to create a new Font object, we are ready to draw strings. To print a string in a graphics context, we should use method DrawString() of the Graphics object. This method is overloaded and has many flavors. Here we describe only some of them. The complete information can be found in the Visual Studio documentation.
Drawing::Font *fnt = new Drawing::Font(S"Times New Roman", 14, FontStyle::Italic);
Drawing::Font *fnt = new Drawing::Font(S"Times New Roman", 0.5, FontStyle::Bold,
GraphicsUnit::Inch);
gObj->DrawRectangle(pen, 10, 10, 50, 200);
gObj->DrawString(S"Hello", fnt, brush, RectangleF(10, 10, 50, 200));
The Image class is a basic class that provides functionality for Bitmap and Metafile descended classes. We will not discuss this class in details, just mention a couple of static method of the class. The first method, we would like to discuss is FromFile(). This method takes a String containing an image file name as a parameter and creates a new object of the Image class. For example, the cimplest code that displays an image stored in a file robot.gif will look like
Graphics *gObj = this->CreateGraphics(); Image *img = Image::FromFile( S"robot.gif" ); gObj->DrawImage(img, 5, 5);The Image object also has several properties and methods we would like to mention:
| Property/ Method | Description | ||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Height | Gets the height of this Image object. | ||||||||||||||||||||||||||||||||
| Width | Gets the width of this Image object. | ||||||||||||||||||||||||||||||||
| Size | Gets the width and height, in pixels, of this image. | ||||||||||||||||||||||||||||||||
| HorizontalResolution | Gets the horizontal resolution, in pixels-per-inch, for this Image object. | ||||||||||||||||||||||||||||||||
| VerticalResolution | Gets the vertical resolution, in pixels-per-inch, for this Image object. | ||||||||||||||||||||||||||||||||
| RotateFlip(type) |
This method either rotates, flips, or rotates and flips the Image object.
It takes only one argument - a RotateFlipType enumeration member that specifies the type of rotation and
flip to apply to the image. The possible values of this type are:
|
||||||||||||||||||||||||||||||||
| Save( filename ) |
Saves the image to the file assigned by the string argument filename. The second parameter specifies the format of the image file. For more information on the file format see the official documentation. |
In the example above we have seen the simplest form of the DrawImage() method of the Graphics class. The easiest form of the method takes only three arguments - the image object to draw ant the coordinates of the top-left corner of the rectangle where the image should appear. Another version of the DrawImage() method takes the image to draw, the coordinates of the top-left corner, and the size of the rectangle to fit the image into:
DrawImage( Image *image, int x, int y, int width, int height);For example, we can display the image in half of its original size:
gObj->DrawImage(img, 10, 5, img->Width/2, img->Height/2);There is an interesting version of the method that allows us to fit the image not into a rectangle, but into a parallelogram. The syntax of the method is
DrawImage( Image *image, Point dest[] );where the dest parameter specifies three points of a parallelogram. The three Point structures represent the upper-left, upper-right, and lower-left corners of the parallelogram. The fourth point is extrapolated from the first three to form a parallelogram. For example, to draw an image into a diamond we can do this:
Graphics *gObj = this->CreateGraphics();
Image *img = Image::FromFile( S"img/bluedrag.gif" );
Point dest[] = { Point(40, 0), Point(80, 40), Point(0, 40) };
gObj->DrawImage(img, dest);
Second, add the following lines to the private section of the Form object definition:
Graphics *gObj;
SolidBrush *brush; // brush to display the ball
SolidBrush *erasor; // brush to erase the ball
int x, y, // the current position of the ball
dx, dy; // the direction the ball is heading
Random *rnd_gen; // we will generate all random numbers using this instance of the Random class
Now, click twice to the Start button to get into the button1_Click() method of the form. Here we need to create all the graphical objects and initialize the current position of the ball and its direction:
gObj = GraphPanel->CreateGraphics(); brush = new SolidBrush( Color::Red ); erasor = new SolidBrush( GraphPanel->BackColor ); rnd_gen = new Random( DateTime::Now.Ticks ); gObj->Clear( GraphPanel->BackColor ); x = rnd_gen->Next() % (GraphPanel->Width - 10); // 10 - is the size of the ball y = rnd_gen->Next() % (GraphPanel->Height - 10); dx = 1 + rnd_gen->Next()%4; dy = 1 + rnd_gen->Next()%2;
When the program starts, it will initialize all the needed variables and then it will repeat the same steps:
NextStepTimer->Enabled = true;to the button1_Click() method to start the timer.
Click twice on the timer and add the following code to the timer1_Tick() method:
// erase the ball
gObj->FillEllipse(erasor, x, y, 10, 10);
// change the X coordinates
x += dx;
if( x>GraphPanel->Width-10 || x<0 ){
dx = -dx;
x += 2*dx;
// make the ball more transparent
int alpha = brush->Color.A;
brush->Color = Color::FromArgb(alpha>5?alpha-5:0, brush->Color);
}
// change the Y coordinates
y += dy;
if( y>GraphPanel->Height-10 || y<0 ){
dy = -dy;
y += 2*dy;
// make the ball more transparent
int alpha = brush->Color.A;
brush->Color = Color::FromArgb(alpha>5?alpha-5:0, brush->Color);
}
// draw the ball in the new position
gObj->FillEllipse(brush, x, y, 10, 10);
Enjoy.