Looks interesting right! Well this is done using plain window’s GDI functions, here is a function which does this!
// Thanks to Charles Petzold!
void CCanvas::DrawOutlineText( CDC& dc, const CString& Text )
{
const int RestorePoint = dc.SaveDC();
// Create new font
CFont NewFont;
NewFont.CreatePointFont( 700, TEXT( "Verdana" ), &dc );
// Use this font
dc.SelectObject( &NewFont );
// Brush for pen
LOGBRUSH lBrushForPen = { 0 };
lBrushForPen.lbColor = RGB( 200, 150, 100 );
lBrushForPen.lbHatch = HS_CROSS;
lBrushForPen.lbStyle = BS_SOLID;
// New pen for drawing outline text
CPen OutlinePen;
OutlinePen.CreatePen( PS_GEOMETRIC | PS_SOLID, 2, &lBrushForPen, 0, 0 );
// Use this pen
dc.SelectObject( &OutlinePen );
dc.SetBkMode( TRANSPARENT );
dc.BeginPath();
// This text is not drawn on screen, but instead each action is being
// recorded and stored internally as a path, since we called BeginPath
dc.TextOut( 20, 20, Text );
// Stop path
dc.EndPath();
// Now draw outline text
dc.StrokePath();
dc.RestoreDC( RestorePoint );
}
Using ExtCreatePen and PS_USERSTYLE you can create funky styled pens instead of the old PS_DOT, PS_DASHDOT, PS_DASHDOTDOT style pens. When using PS_USERSTYLE for creating pens you’ve got specify an array of DWORD which holds dash and space length while drawing a user styled pen!
I’ve created a sample application which demostrates marching ants demo, if you’ve worked in photoshop then you’ve already seen it after selecting a portion of an image…
// Add this to "OnPaint" function to have some fun :smiley:
void CDialogTestDlg::DrawMarchingStuff()
{
CPaintDC dc(this);
const int SavePoint = dc.SaveDC();
// Just for demo, make this a member or whatever but not static !!!
static CFont fnt;
if( !fnt.GetSafeHandle() )
{
fnt.CreatePointFont( 700, _T( "verdana" ), &dc );
}
dc.SelectObject( fnt );
// Create new ext pen
CBrush Brush;
Brush.CreateSolidBrush( RGB( 255, 00, 178 ));
LOGBRUSH lBrush = { 0 };
Brush.GetLogBrush( &lBrush );
dc.SelectStockObject( NULL_BRUSH );
int DashLen = 1;
int SpaceLen = 2;
// Well this is the array that I was talking about, every value at "odd index" denotes dash length and every
// every value at "even index" denotes space length
CPen NewPen;
DWORD Style1[] = { DashLen, SpaceLen };
DWORD Style2[] = { DashLen, SpaceLen + 1 }; // Secret to animation
static int Decider = 0;
int StyleLength = 0;
DWORD* pStyle = NULL;
if( !Decider )
{
StyleLength = sizeof(Style1)/sizeof(Style1[0]);
pStyle = Style1;
Decider = 1;
}
else
{
StyleLength = sizeof(Style2)/sizeof(Style2[0]);
pStyle = Style2;
Decider = 0;
}
NewPen.CreatePen( PS_GEOMETRIC | PS_USERSTYLE, 1, &lBrush, StyleLength, pStyle );
// Hey Mr DC use MY pen
dc.SelectObject( &NewPen );
dc.SetBkMode(TRANSPARENT);
dc.BeginPath();
// This text is not drawn on screen, but instead each action is being
// recorded and stored internally as a path, since we called BeginPath
dc.TextOut( 20, 20, _T( "Hello Nibu" ));
// Stop path
dc.EndPath();
// Draw outlined text
dc.StrokePath();
// Draw a marching rectangle wrapping above text
dc.Rectangle( 20, 30, 500, 130 );
// Restore previous stuff
dc.RestoreDC( SavePoint );
}
Simple way to rotate a piece of text is to use a font object… Here is a sample which does this…
void CSomeDlg::OnPaint()
{
CPaintDC dc(this);
// Get existing dlg font
CFont NewFont;
LOGFONT lgFnt = { 0 };
GetFont()->GetLogFont(&lgFnt);
// Modify this existing font //
// Face name is important, some font's like MS Sans Serif doesn't work
strcpy( lgFnt.lfFaceName, "Arial" );
// Give rotation as multiples of 10, so rotation will be 90 degrees
lgFnt.lfOrientation = 900;
lgFnt.lfEscapement = 900;
// Create a font from this log font
VERIFY( NewFont.CreateFontIndirect( &lgFnt ));
// Save this DC
const int DcRestorePoint = dc.SaveDC();
dc.SetBkMode( TRANSPARENT );
// Set this font to DC
dc.SelectObject( &NewFont );
dc.TextOut( 100,100, _T( "Nibu babu thomas loves Jesus Christ" ));
// Restore dc to previous state
dc.RestoreDC( DcRestorePoint );
}// End OnPaint