在背景上输出文字,并且可以不留痕迹的擦除。
微软提供的 CDC 函数, TextOut 和 DrawText 不支持界面像素的异或运算操作,所以无法从背景中擦除输出的文字。要达到这种目的,只好使用支持像素的异或运算的图形函数了。
有两种方式可以选择:
1. 输出轮廓路径,然后指定画刷填充封闭的路径区域。
2. 得到文字的点阵图,使用向屏幕花点的方式输出文字。
下面给出第二种方式的实现代码。
调用两次下面的函数可以擦除输出的文字, 还可以显示按任意角度旋转的文字。
注意:传入的设备上下文变量 pDC ,其中的 ROP2 属性应该指定为 R2_XORPEN 或 R2_NOTXORPEN
void CDicfexView :: DrawVectorText ( CDC * pDC , CString & strText , CPoint pntPosition , int nAngle )
{
if ( strText . IsEmpty ())
return ;
CClientDC dc ( this );
// 确认要按文本输出的坐标映射模式
if ( pDC -> GetMapMode () != MM_TEXT )
{
// 转换到原坐标映射
dc . SetROP2 ( pDC -> GetROP2 () );
pDC -> LPtoDP ( & pntPosition );
pDC = & dc ;
}
DWORD dwSize ;
MAT2 stM2 ;
GLYPHMETRICS stGM ;
TEXTMETRIC stTM ;
// 创建字体
CFont font ;
LOGFONT stFont ;
memset (& stFont ,0, sizeof ( stFont ));
// 设置字体结构的属性;
stFont . lfHeight =12;
stFont . lfWeight = FW_NORMAL ;
stFont . lfClipPrecision = CLIP_LH_ANGLES ;
strcpy (( char *) stFont . lfFaceName , "Courier New" );
stFont . lfEscapement = nAngle * 10;
stFont . lfOrientation = nAngle * 10;
font . CreateFontIndirect ( & stFont );
CFont * pOldFont = pDC -> SelectObject (& font );
pDC -> SelectObject (& font );
pDC -> GetTextMetrics (& stTM );
// 坐标变换矩阵 , 但这种转换时 , 由于精度舍入的原因 , 取得的字体点阵的质量很差 ,
// 给 stFont.lfEscapement 变量赋值 , 似乎微软做过优化 , 取得字体点阵勉强能说的过去 ,
/*double nEscapement = nAngle * 3.1415926 / 180.0;
stM2.eM11 = FloatToFixed(cos(nEscapement));
stM2.eM12 = FloatToFixed(sin(nEscapement));
stM2.eM21 = FloatToFixed(-sin(nEscapement));
stM2.eM22 = FloatToFixed(cos(nEscapement));*/
stM2 . eM11 = FloatToFixed (1.0);
stM2 . eM12 = FloatToFixed (0.0);
stM2 . eM21 = FloatToFixed (0.0);
stM2 . eM22 = FloatToFixed (1.0);
int nChar = 0;
int nSx = pntPosition . x ;
int nSy = pntPosition . y ;
int nFontSpace = 0;
int nCx = 0;
int nCy = 0;
for ( int i = 0; i < strText . GetLength (); i ++)
{
if ( strText . GetAt ( i ) >= 0)
nChar = strText . GetAt ( i );
else
{
// 宽字节
int th = strText . GetAt ( i );
int tl = strText . GetAt ( i + 1);
nChar = (( th & 0x00ff)<<8) + ( tl & 0x00ff);
i ++;
}
// 得到字体轮廓信息的尺寸
dwSize = pDC -> GetGlyphOutline ( nChar , GGO_BITMAP ,& stGM , 0L , NULL ,& stM2 );
// 定义缓冲区
BYTE * pBuffer = new BYTE [ dwSize ];
memset ( pBuffer , 0, dwSize );
// 取得字体轮廓
pDC -> GetGlyphOutline ( nChar , GGO_BITMAP , & stGM , dwSize , pBuffer , & stM2 );
int nStride = dwSize / stGM . gmBlackBoxY ;
// 轮廓数据
OUTLINETEXTMETRIC stOtm ;
memset ( & stOtm , 0, sizeof ( stOtm ) );
stOtm . otmSize = sizeof ( stOtm );
pDC -> GetOutlineTextMetrics ( sizeof ( stOtm ), & stOtm );
//x 的偏移量
int nXOffset = stGM . gmptGlyphOrigin . x ;
//y 的偏移量 字的顶部 - y 方向原点 都是相对于 baseline
int nYOffset = stOtm . otmAscent - stGM . gmptGlyphOrigin . y ;
for ( int y =0; y < stGM . gmBlackBoxY ; ++ y )
{
for ( int x =0; x < nStride ; ++ x )
{
for ( int k =0; k < 8; ++ k )
{
if ( ( pBuffer [ y * nStride + x ] >> (7- k ) ) & 1 )
{
int nX = nCx + 8 * x + k + nXOffset ;
int nY = nCy + y + nYOffset ;
pDC -> SetPixel ( nSx + nX , nSy + nY , RGB (255,200,200) );
}
}
}
}
// 设置下一个字符的位置
nCx += stGM . gmCellIncX ;
nCx += nFontSpace ;
nCy += stGM . gmCellIncY ;
delete [] pBuffer ;
}
pDC -> SelectObject ( pOldFont );
}