Here are some basic steps for drawing either hatched or gradient text using GDI+.
- Add an event handler for the control's Paint event
You should do your drawing in this method (or a method
called from this method) so that your control is repainted properly.
- Obtain a Graphics object
For those of you familiar with drawing on device contexts, the Graphics
object is the .NET encapsulation of a drawing surface. When drawing on a control - such as a PictureBox -
you could call the PictureBox::CreateGraphics method as it returns a Graphics
object for you to draw on. In fact, I've seen this technique on various demo/sample application
on the Web. However, the problem with that is that the Graphics object is not persistent. Therefore,
the control doesn't paint itself propertly when the user switches to another application and then back again.
As a result, you should use the Graphics object of the PaintEventArgs object that is passed
to the control's Paint method.
private: System::Void picText_Paint(System::Object * sender, System::Windows::Forms::PaintEventArgs * e)
{
...
Graphics* g = e->Graphics;
- Instantiate a Font object
There are currently 13 different Font constructors,
but the most basic one requires that you supply the font type face name and the font size. Here's an example
where I'm creating a 20 point, regular (as opposed to bold, italic, etc.) font using the "Times New Roman"
type face.
using namespace System::Drawing;
...
Font* font = new Font(S"Times new Roman", 20, FontStyle::Regular);
- Measure the text to be rendered
In order to render text, you'll need to measure the text. As illustrated in my article
Managed Extensions - Measuring Strings, the
Graphics::MeasureString is used to accomplish this task. This method takes
the text to be measured and the font being used and returns a SizeF structure,
which simply defines the dimensions needed to draw the text.
SizeF textSize = g->MeasureString(S"My Sample Text", font);
- Instantiate a Brush object
There are various types of Brush objects you can use to draw with. These include
HatchBrush, LinearGradientBrush, PathGradientBrush,
SolidBrush and TextureBrush. As the parameters to instantiate the various
Brush objects are only slightly different, I won't attempt to cover each and every
one. Instead, I'll present examples of the two types of Brush objects (HatchBrush
and LinearGradientBrush) that are used in this article's demo application where I
allow the user to select the Brush type that is used in drawing their specified text.
// HatchBrush example
Brush* brush = new HatchBrush(HatchStyle::Cross,
Color::Black, Color::Blue);
// LinearGradientBrush example
RectangleF* rect = __nogc new RectangleF(PointF(0, 0), textSize);
brush = new LinearGradientBrush(*rect,
Color::Black,
Color::Blue,
LinearGradientMode::ForwardDiagonal);
- [Optional] Fill the background
Typically you'll need to initialize the background before you draw on it. There are two standard
ways of doing this: The easiest way is to simply call the Graphics::Clear method and specify
the desired colour that will be used to fill the entire drawing surface. However, there might be times
when you a finer level of control. In those cases, you can use the Graphics::FillRectange
method.
The Graphics::FillRectange method enables you to specify a Brush object of your choosing as well as the exact
rectangular coordiates to use. Regarding the Brush object, you can either instantiate a custom Brush
or use the SystemBrushes object that defines property members that are each a SolidBrush
representation of a Windows display element. These are the elements that are defined via the Windows
Display Properties and include ActiveBorder, ActiveCaption and so on.
// Use the Windows-defined colour for controls
// and explicitly state the rectangle coordinates
g->FillRectangle(SystemBrushes::Control,
picText->Left,
picText->Top,
picText->Right - picText->Left,
picText->Bottom - picText->Top);
// Colour the entire drawing surface using White
g->Clear(Color::White);
- Render (Draw) the Text
Once you have all the GDI+ objects instantiated, you need only call the Graphics::DrawString
method. Here's an example call to that method where I'm specifying the text to render,
the Font and Brush objects to use and exactly where on the drawing surface
I want the text displayed.
// Center the text on the drawing surface
g->DrawString(txtToDisplay->Text,
font,
brush,
(picText->Width - textSize.Width) / 2,
(picText->Height - textSize.Height) / 2);