其他语言

位置:IT落伍者 >> 其他语言 >> 浏览文章

Visual C++实现各种文字特殊效果


发布日期:2023年07月10日
 
Visual C++实现各种文字特殊效果

一般情况下程序开发人员都希望自己的程序美观大方为了达到这一个要求想尽办法美化自己的程序另一方面文字是程序界面上不可或缺的一种传递信息的途径如果在界面上适当的地方添加并显示各种特殊效果的文字将不失为一个好的选择可以达到事半功倍的效果本例针对Visual C++中编程实现文字的特殊显示效果这一问题通过编写一个简单的小程序介绍如何实现这一目标读者朋友可以稍加改动将该方法应用到自己的程序中去

)thisstylewidth=; twffan=done>图字符串的环绕显示 borderColorDark=#ffffff align=center bgColor=#ddddd borderColorLight=# border=>image onmousewheel=javascript:return big(this) src=http://imgeducitycn/img_///jpg onload=javascript:if(thiswidth>)thisstylewidth=; twffan=done>图D文字效果

实现方法

在讲述文字的各种处理效果之前我们首先来介绍Visual C++中的MFC提供的用来创建字体的CFont类对于Windows程序开发人员来说可以创建的字体有两种库存字体(该字体直接使用字体的索引选入设备上下文就可以了例如CDC::CreateStockObject(int nIndex ))和自定义字体

CFONT类从CgdiObject派生而来该类的对象可以通过Createfont()CreateFontIndirect()等函数创建自定义的字体两个函数原型分别如下

borderColorDark=#ffffff cellPadding= width= align=center borderColorLight=black border=>ee>

CFont::CreateFontIndirect(const LOGFONT* lpLogFont )

CFont::CreateFont( int nHeight int nWidth int nEscapement

int nOrientation int nWeight BYTE bItalic BYTE bUnderline

BYTE cStrikeOut BYTE nCharSet BYTE nOutPrecision BYTE nClipPrecision

BYTE nQuality BYTE nPitchAndFamily LPCTSTR lpszFacename )

其中第二个函数的参数和第一个函数中的LOGFONT类型的参数的的分量有一一对应的关系LOGFONT结构主要定义了字体的属性其定义可通过MSDN帮助查到

borderColorDark=#ffffff cellPadding= width= align=center borderColorLight=black border=>ee>

typedef struct tagLOGFONT {

LONG lfHeight; //字符字体高度

LONG lfWidth; //字符平均宽度

LONG lfEscapement; //文本行逆时针旋转角度

LONG lfOrientation; //字体角度

LONG lfWeight; //字体粗细程度

BYTE lfItalic; //倾斜

BYTE lfUnderline; //下划线

BYTE lfStrikeOut; //删除线

……

} LOGFONT;

在对LOGFONT结构进行设置时lfOutPrecisionlfClipPrecisionlfQuality 以及lfPitchAndFamily等几个成员变量一般可如下设置而无需改动

borderColorDark=#ffffff cellPadding= width= align=center borderColorLight=black border=>ee>

LOGFONT lf; //lf定义字体属性

lflfOutPrecision= OUT_STROKE_PRECIS;

lflfClipPrecision= CLIP_STROKE_PRECIS;

lflfQuality = DRAFT_QUALITY;

lflfPitchAndFamily= VARIABLE_

PITCH|FF_MODERN;

对于其他的成员变量则要根据实际需求进行具体的设定例如

对于没有下划线和删除线并且没有倾斜处理的粗体幼圆汉字可以采取如下设置

borderColorDark=#ffffff cellPadding= width= align=center borderColorLight=black border=>ee>

lflfHeight = ;

lflfWidth = ;

lflfEscapement = ;

lflfOrientation = ;

lflfWeight = FW_HEAVY;

lflfItalic = FALSE;

lflfUnderline = FALSE;

lflfStrikeOut = FALSE;

lflfCharSet = GB_CHARSET; strcpy(lflfFaceName幼圆);

(一)显示倾斜的文字

上文中的图一显示了通过显示一系列的倾斜字符串来实现环绕显示的效果下面来详细说明如何实现这个效果

实现上述的效果其实很容易只要使用CFONT类和LOGFONT结构来灵活的创建字体设置字体的属性就可以实现倾斜文字的效果LOGFONT结构中包含了所要创建的字体中的全部信息其中的ifEscapement 成员制定了所创建的字体与水平方向所倾斜的角度需要读者注意的是该成员变量角度的单位是十分之一度而不是度例如如果ifEscapement定义为它表示字体的倾斜角度为为了保证所有的字体按照一个方向旋转一定要设置ifEscapenent的CLIP_LH_ANGLES位否则字体有可能向反方向旋转

如同使用其它GDI(图形用户界面接口)对象一样在使用你定义的字体以前必须要将创建的字体选入DC中(设备上下文)

(二)实现D文字

计算机屏幕是平面二维的我们之所以能欣赏到真如实物般的三维图像是因为显示在计算机屏幕上时色彩灰度的不同而使人眼产生视觉上的错觉而将二维的计算机屏幕感知为三维图像基于色彩学的有关知识三维物体边缘的凸出部分一般显高亮度色而凹下去的部分由于受光线的遮挡而显暗色这一认识被广泛应用于网页或其他应用中对按钮D线条的绘制对于本文所要绘制的D文字同样也适用即在原始位置显示高亮度颜色而在左下或右上等位置用低亮度颜色勾勒出其轮廓这样在视觉上便会产生D文字的效果具体实现时可用完全一样的字体在不同的位置分别绘制两个不同颜色的D文字只要使两个文字的坐标合适就完全可以在视觉上产生出不同效果的D文字

具体实现的思想是通过CDCSetTextColor()分别设置文字的颜色为高亮(DHILIGHT)和阴影(DSHADOW)的状态下显示文字同时注意在两次显示文字时要错开几个像素这样才能达到预期的效果实现的效果上文的图二所示

(三)文字的渐变效果

为了实现文字的渐变效果需要设置一个定时器(使用SetTimer()函数)在定时器响应函数处理过程中通过调用CDCSetTextColor()函数不断改变设备上下文中文本的显示颜色从而实现文字的渐变效果文本的颜色是通过RGB(红绿兰)三种基本颜色的混合所形成的最终结果RGB三基色的变化范围都是(R=G=B时颜色的效果是灰色的所谓灰色就是在纯白和纯黑之间的一种过渡色当R=G=B=颜色为黑色当R=G=B=颜色为纯白色可以定义一个修正变量不断的对该三基色进行递增或递减从而实现文字的渐变显示这里仅仅给出实现的思路读者自己可以很容易的实现代码

(四)其它

另外还可以通过设置路径对象来对普通的文字进行轮廓勾勒使之具备特殊的效果路径是Win中新增的一个GDI对象下面先从概念上谈起

)路径的概念

在Windows /NT 这样的Win操作系统中除了已有的位图画笔画刷字体调色板和区域之外还增加了一个新的GDI对象路径路径是可以被填充画出轮廓或同时被画出轮廓并填充的一个或多个图形路径的引入大大地丰富了Windows的图形功能使得应用程序可以方便地建立复杂区域

绘制和填充不规则图形这里说的不规则图形是指由直线和贝塞尔曲线组成的图形(相对于矩形多边形椭圆等规则图形)

)路径的使用

与其它原有的GDI对象不同的是MFC类库没有专门用一个C++类来封装路径对象(或许在以后的版本中会得到支持)有关路径的定义和使用等各种操作都必须通过调用API函数(或CDC类中对应的成员函数)来实现路径的使用过程大致如下

()调用BeginPath()函数开始路径定义

()调用GDI绘图函数来定义路径在Win可以用于定义路径的GDI绘图函数包括AngleArc()Arc()ArcToChord()Ellipse()LineTo()TextOut()等函数

()调用EndPath()函数结束路径定义

完成路径定义后所定义的路径即被同时选进设备描述表设备描述表中原有的路径对象在调用BeginPath()函数开始路径定义时即被废弃

()使用路径对象

完成路径定义工作之后应用程序便可以利用有关GDI函数来使用路径这些函数包括绘制路径轮廓StrokePath()填充路径FillPath()绘制轮廓并填充StrokeAndFillPath()把路径转换成区域PathToRegion()把路径直线化FlattenPath()提取路径数据GetPath()加宽路径WidenPath()和设置裁剪路径SelectClipPath()等这些函数的具体使用方法可参阅有关的SDK文档

下面的代码演示了如何实现字体的空心效果

应用程序主窗口的重绘函数

borderColorDark=#ffffff cellPadding= width= align=center borderColorLight=black border=>ee>

void CMyWnd::OnPaint()

{

// 获得窗口的客户区设备上下文句柄

CPaintDC dc(this); // 更改当前字体

LOGFONT lf;

dcGetCurrentFont()>GetLogFont(&lf);

CFont font;

CFont *pOldFont; // 保存设备上下文最初使用的字体对象

lflfCharSet=;

lflfHeight=;

lflfHeight=;

lflfWidth=;

strcpy(lflfFaceName 隶书);

fontCreateFontIndirect(&lf);

pOldFont=dcSelectObject(&font);

dcSetBkMode(TRANSPARENT); // 更改当前画笔

CPen pen(PS_SOLID RGB( ));

CPen *pOldPen;

pOldPen=dcSelectObject(&pen); // 开始一个路径

dcBeginPath();

dcTextOut( 空心字);

dcEndPath(); // 绘制路径

dcStrokePath();

//可以用dcStrokeAndFillPath()函数来代替不过该函数会使用当前刷子填充路径的内部

dcSelectObject(pOldFont);

dcSelectObject(pOldPen);

}

编程步骤

启动Visual C++生成一个单文档视图结构的程序(对于旋转字体的程序项目名为ViewFont对于D效果的程序项目名为 DText)

重载应用程序的OnDraw(CDC* pDC)函数

添加代码编译运行程序

程序代码

旋转字体

borderColorDark=#ffffff cellPadding= width= align=center borderColorLight=black border=>ee>

void CViewFontView::OnDraw(CDC* pDC)

{

CViewFontDoc* pDoc = GetDocument();

ASSERT_VALID(pDoc);

// TODO: add draw code for native data here

CString str(_T(Visua C++编程实例));//定义要显示的字符串

CRect rect;

GetClientRect(&rect);

pDC>SetBkMode(TRANSPARENT);//设置背景为透明效果

pDC>SetTextColor(RGB());//设置显示的文本颜色

CFont font;

LOGFONT stFont;//定义字体结构

memset(&stFontsizeof(stFont));//设置字体结构的属性

stFontlfHeight=;

stFontlfWeight=FW_NORMAL;

stFontlfClipPrecision=CLIP_LH_ANGLES;

strcpy(stFontlfFaceNameArial);

//下面的代码以视图中心为圆点在半径的圆周上每隔度显示字符串

for(double i=;i<;i+=)

{

stFontlfEscapement=i;//设置字体的倾斜角度

fontCreateFontIndirect(&stFont);//根据字体结构创建字体对象

CFont *oldFont;

oldFont=pDC>SelectObject(&font);//将创建的字体选入设备上下文

if(i<)

pDC>TextOut(rectleft+rectWidth )/+*cos(i/*)

recttop+rectHeight ()/*sin(i/*)str);

if(i>=&&i<)

pDC>TextOut(rectleft+rectWidth ()/+*cos(i/*)

recttop+rectHeight ()/*sin(i/*)str);

if(i>=&&i<)

pDC>TextOut(rectleft+rectWidth ()/+*cos(i/*)

recttop+rectHeight ()/*sin(i/*)str);

if(i>=&&i<=)

pDC>TextOut(rectleft+rectWidth ()/+*cos(i/*)

recttop+rectHeight ()/*sin(i/*)str);

pDC>SelectObject(oldFont);//恢复设备上下文的字体

fontDeleteObject ();//删除创建的字体

}

}

显示D效果的程序

borderColorDark=#ffffff cellPadding= width= align=center borderColorLight=black border=>ee>

void CMyDTextView::OnDraw(CDC* pDC)

{

CMyDTextDoc* pDoc = GetDocument();

ASSERT_VALID(pDoc);

// TODO: add draw code for native data here

CString string;

string=Visual C++编程实例;

CFont m_fontLogo;

m_fontLogoCreateFont( FALSE FALSE Arial);

//创建字体

pDC>SetBkMode(TRANSPARENT);

CRect rectText;

GetClientRect(&rectText);

CFont * OldFont = pDC>SelectObject(&m_fontLogo);

COLORREF OldColor = pDC>SetTextColor( ::GetSysColor( COLOR_DSHADOW));

//阴影状态显示文字

pDC>DrawText( string rectText+CPoint()

DT_SINGLELINE | DT_LEFT |DT_VCENTER|DT_CENTER);

pDC>SetTextColor(::GetSysColor( COLOR_DHILIGHT) );

//高亮状态显示文字

pDC>DrawText( string rectText DT_SINGLELINE | DT_LEFT |DT_VCENTER|DT_CENTER);

pDC>SetTextColor( OldColor);

pDC>SelectObject(OldFont);

m_fontLogoDeleteObject();

}

小结

读者只要掌握了上面的内容灵活运用Cfont和LOGFONT结构创建不同的字体

再结合显示颜色位置时间的设置相信一定还可以实现更多的动态效果来

上一篇:为C++标准库容器写自己的内存分配程序

下一篇:Visual C++编译器常用选项设置