📄 gdiplus3dtext.htm
字号:
<h1 align="center">Managed Extensions - Using GDI+ to Draw 3D Text</h1>
<p>
In a previous article - <a href="" target="_blank">Managed Extensions - Using GDI+
Brushes to Draw Text</a> - I presented step-by-step instructions as well as a demo application
illustrating how to draw 2D text using GDI+ objects. This week, I'll take that a
step a further and show you how to render 3D text in order to accomlish the following effects:
<ul>
<li>Shadowed Text</li>
<li>Blocked Text</li>
<li>Embossed Text</li>
<li>Engraved Text</li>
</ul>
The shadowed, blocked, embossed or engraved text-effects are typically realized by
drawing the text multiple times starting with the text furthest in the background (i.e., the shadow) and
proceeding until the top-most, or foreground, text is drawn last. In other words, drawing 3D text
is basically just drawing 2D text multiple times. Therefore, I won't describe each step of
setting up the various GDI+ objects as I've already done that in the article
, <a href="" target="_blank">Managed Extensions - Using GDI+ Brushes to Draw Text</a>. Instead,
I'll focus on the code necessary to accomplish each of the aforementioned 3D effects.
<p>
<blockquote><b>Note:</b> In order to test these code snippets, first simply drag
a <b>PictureBox</b> from the Toolbox onto a <b>Form</b> in a Managed Extensions Windows
Forms application and name the <b>PictureBox</b> variable <b>picText</b>. Then,
copy and paste the desired snippet into your application to have the text rendered
onto the <b>PictureBox</b></blockquote>
</p>
<h3>Steps to Rendering Shadowed Text</h3>
To achieve a shadowed appearance, you simply draw the shadowed text twice: first
at the desired depth first and then the foreground text. For example, the following code
will draw a sample text on a window (represented by the <b>Graphics</b> object, <b>g</b>)
where the text has a shadow version of itself drawn 5 pixels in the background.
<p>
<img src="GDIPlus3DText1.jpg">
<pre>
<font color="green">// Assumes a PictureBox on the form named picText</font>
<font color="green">// with this code being the picText object's </font>
<font color="green">// Paint method</font>
private:
System::Void picText_Paint(
System::Object * sender,
System::Windows::Forms::PaintEventArgs * e)
{
<font color="green">// Test string</font>
String* textToDisplay = S"Test string";
<font color="green">// Obtain Graphics object</font>
Graphics* g = e->Graphics;
<font color="green">// Create a Font object, Times New Roman, 25pt</font>
System::Drawing::Font* font =
new System::Drawing::Font("Times New Roman",
Convert::ToSingle(25),
FontStyle::Regular);
<font color="green">// Obtain the size of the text to be rendered</font>
SizeF textSize = g->MeasureString(textToDisplay, font);
<font color="green">// Text will be centered on PictureBox control</font>
Single x = (picText->Width - textSize.Width) / 2;
Single y = (picText->Height - textSize.Height) / 2;
<font color="green">// Clear background</font>
g->Clear(Color::White);
<b>
<font color="green">// Draw the shadow text</font>
g->DrawString(textToDisplay,
font,
SystemBrushes::ControlLight,
x + 5, y + 5);
<font color="green">// Draw the foreground text</font>
g->DrawString(textToDisplay, font, SystemBrushes::ControlText, x, y);
}
</b>
</pre>
<h3>Steps to Rendering Blocked Text</h3>
To get the blocked-text effect, the text is be repeatedly drawn
starting at the desired depth and moving one pixel at a time
up to where the foreground text is drawn. Obviously, you have
to decide in which direction this repeated drawing occurs. I
personally draw blocked text with the light
source from the upper-right. This means using a <b>for</b>
loop and subtracting the offset depth from the X dimension. To
move the light-source to the upper-left, simply increment the offset.
<p>
<img src="GDIPlus3DText2.jpg">
<pre>
<font color="green">// Assumes a PictureBox on the form named picText</font>
<font color="green">// with this code being the picText object's </font>
<font color="green">// Paint method</font>
private:
System::Void picText_Paint(
System::Object * sender,
System::Windows::Forms::PaintEventArgs * e)
{
<font color="green">// Test string</font>
String* textToDisplay = S"Test string";
<font color="green">// Get drawing surface for PictureBox and clear background</font>
Graphics* g = e->Graphics;
<font color="green">// Create a Font object</font>
System::Drawing::Font* font = new System::Drawing::Font("Times New Roman", Convert::ToSingle(25), FontStyle::Regular);
<font color="green">// Obtain the size of the text to be rendered</font>
SizeF textSize = g->MeasureString(textToDisplay, font);
<font color="green">// Text will be centered on Picture Box control</font>
Single x = (picText->Width - textSize.Width) / 2;
Single y = (picText->Height - textSize.Height) / 2;
<font color="green">// Clear background</font>
g->Clear(Color::White);
<b>
<font color="green">// Print the background text multiple times starting </font>
<font color="green">// at the furthest point in the background up to</font>
<font color="green">// the foreground text</font>
for (int i = Convert::ToInt32(5); i >= 0; i--)
{
g->DrawString(textToDisplay,
font,
SystemBrushes::ControlLight,
x - i, y + i);
}
<font color="green">// Draw the foreground text</font>
g->DrawString(textToDisplay, font, SystemBrushes::ControlText, x, y);
</b>
}
</pre>
<h3>Steps to Rendering Embossed and Engraved Text</h3>
I'll explain both of these in the same section because engraved-text is simply the inverse
of embossed text. The emossed-text effect is usually accomplished by simply using the
shaddow-text technique with the depth set 1 pixel and the foreground text colour set to the same
colour as the backround on which the text is being rendered. The shadow text is then some darker
colour - such as grey or black. The engraved effect is done in reverse where the offset for
the shadow colour is one pixel up and left from the foreground text.
<p>
<img src="GDIPlus3DText3.jpg"> <img src="GDIPlus3DText4.jpg">
</p>
<pre>
<font color="green">// Assumes a PictureBox on the form named picText</font>
<font color="green">// with this code being the picText object's </font>
<font color="green">// Paint method</font>
private:
System::Void picText_Paint(
System::Object * sender,
System::Windows::Forms::PaintEventArgs * e)
{
<font color="green">// Test string</font>
String* textToDisplay = S"Test string";
<font color="green">// Get drawing surface for PictureBox and clear background</font>
Graphics* g = e->Graphics;
<font color="green">// Create a Font object</font>
System::Drawing::Font* font = new System::Drawing::Font("Times New Roman", Convert::ToSingle(25), FontStyle::Regular);
<font color="green">// Obtain the size of the text to be rendered</font>
SizeF textSize = g->MeasureString(textToDisplay, font);
<font color="green">// Text will be centered on Picture Box control</font>
Single x = (picText->Width - textSize.Width) / 2;
Single y = (picText->Height - textSize.Height) / 2;
<font color="green">// Clear background</font>
g->Clear(Color::White);
<b>
<font color="green">// Change the isEmossed value to switch</font>
<font color="green">// between embossed and engraved</font>
bool isEmbossed = false;
g->DrawString(textToDisplay,
font,
SystemBrushes::ControlText,
x + Convert::ToSingle( (isEmbossed? 1 : -1)),
y + Convert::ToSingle( (isEmbossed ? 1 : -1)));
<font color="green">// Draw the foreground text</font>
g->DrawString(textToDisplay, font, new SolidBrush(Color::White), x, y);
</b>
}
</pre>
<h3>Sample Application</h3>
<p>
I've attached a demo application with this article that will allow you to play around with the various
effects you can accomplish with GDI+ and 3D text. The following image is a screen capture of that demo
application
<p><img src="GDIPlus3DText.jpg"></p>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -