My function
SSTextOut
has similar functionality to
ExtTextOut
.
You need to specify the
pointer to the device
context, the pointer to
bounding rectangle, the
string
itself, and the
justification mode.
The
string
should contain special
formatting codes -
^
for superscript and
_
for subscript. The next
symbol after
^
or
_
will be shown as subscript
or superscript. If you need
to show
^
or
_
themselves - just type them
twice -
^^
or
__
.
Justification can be
DT_CENTER
,
DT_LEFT
,
or
DT_RIGHT
.
It affects only horizontal
justification. Vertically,
the text will be centered in
the bounding rectangle
automatically. The text
outside the rectangle is
clipped. The function uses
the current font of the
specified device context.
So, to
draw the
meaningless text in the
image above, you need to
call:
Collapse
Copy Code
SSTextOut(pDC,"ms^2/Hz+H_2O-mc^^2__4",&rect,DT_CENTER);
Source Code
The
source code of
SSTextOut
is shown below:
Collapse
Copy Code
void SSTextOut(CDC* pDC, CString data , CRect* drawRect, int justification)
{
pDC->SaveDC();
CSize sz;
CRect outRect(0,0,0,0);
CFont* pFont = pDC->GetCurrentFont();
CFont* oldFont;
pDC->SetTextAlign(TA_BOTTOM|TA_LEFT);
LOGFONT lf;
pFont->GetLogFont(&lf);
CPoint sub,sup,subofs,supofs;
sub.x=lf.lfWidth/2;
sup.x=lf.lfWidth/2;
sub.y=lf.lfHeight/3*2;
sup.y=lf.lfHeight/3*2;
subofs.x=lf.lfWidth/2;
supofs.x=lf.lfWidth/2;
subofs.y=lf.lfHeight/6;
supofs.y=lf.lfHeight/3;
lf.lfWidth=sub.x;
lf.lfHeight=sub.y;
CFont SubFont;
SubFont.CreateFontIndirect(&lf);
lf.lfWidth=sup.x;
lf.lfHeight=sup.y;
CFont SupFont;
SupFont.CreateFontIndirect(&lf);
CString temp = data;
TCHAR c;
do
{
int x=0;
CString s = "";
c=' ';
bool bFind=true;
while (bFind)
{
x=data.FindOneOf("^_");
if (x==-1)
{
bFind=false;
x=data.GetLength();
}
else if (x==data.GetLength()-1) bFind=false;
else if (data[x]!=data[x+1])
{
bFind=false;
c=data[x];
}
else x++;
s=s+data.Left(x);
data.Delete(0,min(x+1,data.GetLength()));
}
sz = pDC->GetTextExtent(s);
outRect.right+=sz.cx;
if (outRect.Height()<sz.cy) outRect.top=outRect.bottom-sz.cy;
switch (c)
{
case '^':
oldFont = pDC->SelectObject(&SupFont);
sz = pDC->GetTextExtent(data[0]);
outRect.right+=sz.cx+supofs.x;
data.Delete(0);
pDC->SelectObject(oldFont);
break;
case '_':
oldFont = pDC->SelectObject(&SubFont);
sz = pDC->GetTextExtent(data[0]);
outRect.right+=sz.cx+subofs.x;
data.Delete(0);
pDC->SelectObject(oldFont);
break;
}
}
while (c!=' ');
outRect.bottom+=2*subofs.y;
outRect.top-=2*subofs.x;
CPoint Origin;
Origin.y = drawRect->Height()/2+outRect.Height()/2+drawRect->top;
switch (justification)
{
case DT_CENTER:
Origin.x = drawRect->Width()/2-outRect.Width()/2+drawRect->left;
break;
case DT_LEFT:
Origin.x = drawRect->left;
break;
case DT_RIGHT:
Origin.x = drawRect->right-outRect.Width();
}
CPoint pnt = Origin;
data = temp;
do
{
int x=0;
CString s = "";
c=' ';
bool bFind=true;
while (bFind)
{
x=data.FindOneOf("^_");
if (x==-1)
{
bFind=false;
x=data.GetLength();
}
else if (x==data.GetLength()-1) bFind=false;
else if (data[x]!=data[x+1])
{
bFind=false;
c=data[x];
}
else x++;
s=s+data.Left(x);
data.Delete(0,min(x+1,data.GetLength()));
}
pDC->ExtTextOut(pnt.x,pnt.y,ETO_CLIPPED,drawRect,s,NULL);
sz = pDC->GetTextExtent(s);
pnt.x+=sz.cx;
switch (c)
{
case '^':
oldFont = pDC->SelectObject(&SupFont);
pDC->ExtTextOut(pnt.x+supofs.x,pnt.y-supofs.y,ETO_CLIPPED,drawRect,data[0],NULL);
sz = pDC->GetTextExtent(data[0]);
pnt.x+=sz.cx+supofs.x;
data.Delete(0);
pDC->SelectObject(oldFont);
break;
case '_':
oldFont = pDC->SelectObject(&SubFont);
pDC->ExtTextOut(pnt.x+subofs.x,pnt.y+subofs.y,ETO_CLIPPED,drawRect,data[0],NULL);
sz = pDC->GetTextExtent(data[0]);
pnt.x+=sz.cx+supofs.x;
data.Delete(0);
pDC->SelectObject(oldFont);
break;
}
}
while (c!=' ');
pDC->RestoreDC(-1);
}