中国人自古就有自右至左、从上到下书写汉字的习惯。而当我们在自己所编写的应用程序中使用输出函数输出的总是自左至右的横排文字。有没有可能在我们的应用程序中实现竖写汉字的效果呢?笔者偶然发现了一种利用VC实现竖写汉字效果的方法,现在就把它介绍给大家。

Windows系统内置了许多名称以“@”开头的字集,这些字集有一个共同的特点,即其所包含的文字全都是平躺着的(字头朝左,字底朝右)。如果我们能将这些字逆时针旋转270度后再显示出来,就可以达到实现竖写汉字效果的目的了。

  要使文字发生旋转,我们只需创建一个逻辑字体并设定该逻辑字体的显示角度,再设定其字体名称为一个以“@”开头的字集的名称即可。我们可以采用两种方式创建逻辑字体。

  其一,用CFont类的成员函数CreateFont直接创建逻辑字体。CreateFont的参数定义如下:

BOOL   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       //字体名称

);

  其中nEscapement单位为0.1角度,方向为逆时针,所以为了使平躺的字立起来应设定其值为2700,lpszFacename则赋以“@”开头的字集的名称,如“@system”。

  其二,利用LOGFONT结构,将该结构作为参数调用CFont类的成员函数CreateFontIndirect创建逻辑字体。LOGFONT结构通常被用来描述一种逻辑字体,结构内的各变量分别代表逻辑字体的各个属性,这些变量与函数CreateFont的参数相同。其结构如下:

typedef   struct   tagLOGFONT   {   //   lf

LONG   lfHeight;                   //字体的高度

LONG   lfWidth;                     //字体的宽度

LONG   lfEscapement;           //字体显示的角度

LONG   lfOrientation;         //字体的角度

LONG   lfWeight;                   //字体的磅数

BYTE   lfItalic;                   //斜体字体

BYTE   lfUnderline;             //带下划线的字体

BYTE   lfStrikeOut;             //带删除线的字体

BYTE   lfCharSet;                 //所需的字符集

BYTE   lfOutPrecision;       //输出的精度

BYTE   lfClipPrecision;     //裁减的精度

BYTE   lfQuality;                 //逻辑字体与输出设备的

//实际字体之间的精度

BYTE   lfPitchAndFamily;   //字体间距和字体集

TCHAR   lfFaceName[LF_FACESIZE];   //字体名称

}   LOGFONT;

  下面我们就以一个示例来说明竖写汉字的实现方法:

1.建立一个MFC   AppWizard(exe)应用工程CHNfont。在MFC   AppWizard向导的第一步中选择Single   Document,再点击按键Finish->OK完成工程的建立。

2.在CMainFrame::OnCreate函数中添加如下代码,使窗体最大化。AfxGetMainWnd()->ShowWindow(SW_SHOWMAXIMIZED);

3.添加如下代码实现竖写功能。

void   CChildView::OnPaint()

{

CPaintDC   dc(this);//   device   context   for   painting

///////   利用CFont::CreateFont(...)函数实现竖写汉字////////

CFont   myFont;           //创建字体对象

//创建逻辑字体

myFont.CreateFont(

56,                 //字体高度(旋转后的字体宽度)=56

20,                 //字体宽度(旋转后的字体高度)=20

2700,                 //字体显示角度=270°

0,                                     //nOrientation=0

10,                                   //字体磅数=10

FALSE,                             //非斜体

FALSE,                             //无下划线

FALSE,               //无删除线

DEFAULT_CHARSET,         //使用缺省字符集

OUT_DEFAULT_PRECIS,   //缺省输出精度

CLIP_DEFAULT_PRECIS,//缺省裁减精度

DEFAULT_QUALITY,         //nQuality=缺省值

DEFAULT_PITCH,             //nPitchAndFamily=缺省值

"@system");                   //字体名=@system

CFont   *pOldFont=dc.SelectObject(&myFont);//选入设备描述表

CRect   rtClient;

GetClientRect(rtClient);       //获取客户区尺寸、位置信息

//在客户区适当位置输出文字

dc.TextOut(rtClient.Width()/2+30,rtClient.Height()/8,

"无边落木萧萧下");

dc.SelectObject(pOldFont);   //将myFont从设备环境中分离

myFont.DeleteObject();           //删除myFont对象

///////////   利用LOGFONT结构实现竖写汉字//////////////

LOGFONT   lf;                                           //定义字体结构

lf.lfWeight=10;                                   //字体磅数=10

lf.lfHeight=56;               //字体高度(旋转后的字体宽度)=56

lf.lfWidth=20;                                     //字体宽度(旋转后的字体高度)=20

lf.lfUnderline=FALSE;                       //无下划线

lf.lfStrikeOut=FALSE;                       //无删除线

lf.lfItalic=FALSE;                             //非斜体

lf.lfEscapement=2700;                       //字体显示角度=270°

lf.lfCharSet=DEFAULT_CHARSET;       //使用缺省字符集

strcpy(lf.lfFaceName,"@system");   //字体名=@system

CFont   myLogFont;                                       //定义字体对象

myLogFont.CreateFontIndirect(&lf);   //创建逻辑字体

pOldFont=dc.SelectObject(&myLogFont);//选入设备描述表

//在客户区适当位置输出文字

dc.TextOut(rtClient.Width()/2-30,rtClient.Height()/8,

"不尽长江滚滚来");

dc.SelectObject(pOldFont);   //将myFont从设备环境中分离

myLogFont.DeleteObject();     //删除myLogFont对象

}

4.编译连接,运行。

或者

CString   m_text;

CSize   sz   =   pdc->GetTextExtent("效");

CRect   rtCal;   //要输出字符串的矩形区域。其宽度稍大于字符宽度。

rtCal.Width   =   sz.cx   +   2;

int   midhei=pDC->DrawText(m_text,&rtCal,flag   |   DT_CALCRECT   | DT_WORDBREAK| DT_NOCLIP);

或者只是简单的用:

for   (i=0;i<m_text.GetLength();i++){

pDC->TextOut(10,y,m_Text.GetAt(i));

y+=   sz.cy;

}

----------------------------------------------------------------------------------

HFONT CreateFont(
int nHeight, // logical height of font height
int nWidth, // logical average character width
int nEscapement, // angle of escapement
int nOrientation, // base-line orientation angle
int fnWeight, // font weight
DWORD fdwItalic, // italic attribute flag
DWORD fdwUnderline, // underline attribute flag
DWORD fdwStrikeOut, // strikeout attribute flag
DWORD fdwCharSet, // character set identifier
DWORD fdwOutputPrecision, // output precision
DWORD fdwClipPrecision, // clipping precision
DWORD fdwQuality, // output quality
DWORD fdwPitchAndFamily, // pitch and family
LPCTSTR lpszFace // pointer to typeface name string
);

CreateFont 参数说明:

1、nHeight:指定字体的字符单元或字符的逻辑单位高度,字符的高度值(也被称为em高度)是指字符单元高度值减去内部标头值。字体映射器以如下方式解释nHeight指定的值,各值含义为:
>0:字体映射器转换这个值以设备单位,并和已有字体的单元高度相匹配。
0:字体映射器转换在选择匹配时用一个缺省的高度值。
<0:字体映射器转换这个值到设备单位,并将它的绝对值和已有字体的字符高度相匹配。
比较所有的高度,字体映射器选择不超过要求大小的最大字体。
此映射当字体第一次被使用时发生。
对于MM_TEXT映射方式,可以用下面的公式为一种指定了点大小的字体确定高度:
nHeight=-MulDiv(PointSize, GetDeviceCaps(hDC, LOGPIXELSY),72)
2、nWidth:指定所要求字体的字符的逻辑单位的平均宽度。如果此值为0,字体映射器选择一个closest match值,closest match值是由比较当前设备的特征系数与可使用字体的数字化特征系数之差的绝对值而确定的。
3、nEscapement:指定移位向量和设备X轴之间的一个角度,以十分之一度为单位。移位向量平行于正文行的基线。
Windows NT:当图形设备设置为GM_ADVANCED时,可以不依赖字符串的字符的定位角而指定字符串的移位角。
当图形模式被设置为GM_COMPATIBLE时,nEscapement同时指定移位角和定位角,可以设置nEscapement和nOrientation为相同的值。
Windows 95:nEscapement同时指定移位角和定位角,可设置nEscapement和nOrientation为相同的值。
4、nOrientation:指定每个字符的基线和设备X轴之间的角度。
5、FnWeight:在0到1000之间指定字体的权值,如400表示标准体,700表示黑(粗)体,如果此值为0,则使用缺省的权值。
FW_DONTCARE:0;FW_THIN;100;FW_EXTRALIGHT;200;FW_ULTRALIGHT;200;FW_LIGHT;300;
FW_NORMAL:400;FW_MEDIUM;500;FW_SEMIBOLD;600;FW_DEMIBOLD;600;FW_BOLD:700;FW_EXTRABOLD;800;FW_BLACK;900。
6、fdwItalic:如果设置为TRUE,则字体设置为斜体。
7、fdwUnderline:如果设置为TRUE,则字体增加下划线。
8、fdwStrikeOut:如果设置为TRUE,则字体增加删除线。
9、fdwCharSet:指定字符集,下列值是预定义的:
ANSI_CHARSET; BALTIC_CHARSET; CHINESEBIG5_CHARSET; DEFAULT_CHARSET;
EASTEUROPE_CHARSET; GB2312_CHARSET; GREEK_CHARSET; HANGUL_CHARSET; MAC_CHARSET; OEM_CHARSET; RUSSIAN_CHARSET; SHIFTJIS_CHARSET;
SYMBOL_CHARSET; TURKISH_CHARSET。
韩国Windows:JOHAB_CHARSET;
中东地区Windows:HEBREW_CHARSSET; ARABIC_CHARSET
泰国Windows:THAI_CHARSET
OEM_CHARSET指定的字符集与操作系统有关。
可以使用DEFAULT_CHARSET值来允许字体的名字和大小来充分描述逻辑字体。如果指定的字体名不存在,任何字符集的字体都可以替代指定的字体,所以应该小心地用DEFAULT_CHARSET来避免不期望的结果出现。

函数原型

int DrawText(
HDC hDC, // 设备描述表句柄
LPCTSTR lpString, // 将要绘制的字符串
int nCount, // 字符串的长度
LPRECT lpRect, // 指向矩形结构RECT的指针
UINT uFormat // 正文的绘制选项
);

参数

hdc:
[输入]设备环境句柄。
lpString:
[输入]指向将被写入的字符串的指针,如果参数nCount是-1,则字符串必须是以\0结束的。 如果uFormat包含DT_MODIFYSTRING,则函数可为此字符串增加4个字符,存放字符串的缓冲区必须足够大,能容纳附加的字符。
nCount:
[输入]指向字符串中的字符数。如果nCount为-1,则lpString指向的字符串被认为是以\0结束的,DrawText会自动计算字符数。
lpRect:
[输入/输出]指向结构RECT的指针,其中包含文本将被置于其中的矩形的信息(按逻辑坐标)。
uFormat:
[输入]指定格式化文本的方法。它可以下列值的任意组合,各值描述如下:

DT_BOTTOM 将正文调整到矩形底部。此值必须和DT_SINGLELINE组合。
DT_CALCRECT 决定矩形的宽和高。
如果正文有多行,DrawText使用lpRect定义的矩形的宽度,并扩展矩形的底部以容纳正文的最后一行。
如果正文只有一行,则DrawText改变矩形的右边界,以容纳下正文行的最后一个字符。
出现上述任何一种情况,DrawText返回格式化正文的高度,而不是绘制正文。
DT_CENTER 使正文在矩形中水平居中。
DT_EDITCONTROL 复制多行编辑控制的正文显示特性。
特殊地,为编辑控制的平均字符宽度是以同样的方法计算的,此函数不显示只是部分可见的最后一行。
DT_END_ELLIPSIS 对于显示的文本,如果结束的字符串的范围不在矩形内,它会被截断并以省略号标识。
如果一个字母不是在字符串的末尾处超出了矩形范围,它不会被截断并以省略号标识。
字符串不会被修改,除非指定了DT_MODIFYSTRING标志。
DT_EXPANDTABS 扩展制表符,每个制表符的缺省字符数是8。
DT_WORD_ELLIPSIS, DT_PATH_ELLIPSIS和DT_END_ELLIPSIS不能和此参数一起使用
DT_EXTERNALLEADING 在行的高度里包含字体的外部标头,通常,外部标头不被包含在正文行的高度里。
DT_HIDEPREFIX 忽略正文中的前缀字符(&),并且前缀字符后面的字母不会出现下划线。其它前缀字符的调用方式不受影响。
输入的字符串: "A&bc&&d"
正常: "Abc&d"
DT_HIDEPREFIX: "Abc&d"
DT_INTERNAL 用系统字体来计算正文度量。
DT_LEFT 正文左对齐。
DT_MODIFYSTRING 修改给定的字符串来匹配显示的正文。
此标志必须和DT_END_ELLIPSIS 或 DT_PATH_ELLIPSIS同时使用。
DT_NOCLIP 无裁剪绘制。当DT_NOCLIP使用时DrawText的使用会有所加快。
DT_NOFULLWIDTHCHARBREAK 在宽字符的字符串中防止行断开,因此折行规则相当于单字符的字符串。
例如,我们可以用在棒子版的windows中,为图标标签提供更好的可读性。
除非指定DT_WORDBREAK,否则此值没有作用。
DT_NOPREFIX 关闭前缀字符的处理。
通常DrawText解释助记前缀字符,&为给其后的字符加下划线,解释&&为显示单个&。指定DT_NOPREFIX,这种处理被关闭。
DT_PATH_ELLIPSIS 对于显示的正文,替换字符串在椭圆中的字符,以确保结果能在合适的矩形内。
如果该字符串包含反斜杠(\)字符,DT_PATH_ELLIPSIS尽可能的保留最后一个反斜杠之后的正文。
字符串不会被修改,除非指定了DT_MODIFYSTRING标志。
DT_PREFIXONLY 仅仅在(&)前缀字符的位置下绘制一个下划线。不绘制字符串中的任何其他字符。
输入的字符串: "A&bc&&d"
正常: "Abc&d"
DT_PREFIXONLY:" _ "
DT_RIGHT 正文右对齐。
DT_RTLREADING 当选择进设备环境的字体是希伯来文或阿拉伯文字体时,为双向正文安排从右到左的阅读顺序都是从左到右的。
DT_SINGLELINE 显示正文的同一行,回车和换行符都不能折行。
DT_TABSTOP 设置制表,参数uFormat的15"C8位(低位字中的高位字节)指定每个制表符的字符数,每个制表符的缺省字符数是8。
注意:DT_CALCRECT, DT_EXTERNALLEADING, DT_INTERNAL,
DT_NOCLIP, DT_NOPREFIX值不能和DT_TABSTOP值一起使用。
DT_TOP 正文顶端对齐。
DT_VCENTER 使正文在矩形中垂直居中。
(DreamSmart注:此值必须和DT_SINGLELINE连用,否则GDI无法计算目的矩形)
DT_WORDBREAK 断开字。当一行中的字符将会延伸到由lpRect指定的矩形的边框时,此行自动地在字之间断开。一个回车一换行也能使行折断。
DT_WORD_ELLIPSIS 截短不符合矩形的正文,并增加省略号。

 
CSize GetTextExtent(LPCTSTR lpszString, int nCount) const;//获得字符串的宽高
 
参考文章:http://www.cnblogs.com/wangyang-sust/archive/2012/08/18/2645918.html

参考文章:http://baike.baidu.com/link?url=2fdO6RtuvbmsKEghtK036hqN4sE9JIs6AdNHYRBYAMWNm8lxyxDoYRLG2foEaeo4u8KnILAacYOiT32x1h6EGa

原文地址:http://www.cnblogs.com/gxceo/archive/2011/03/11/1980466.html

【转】MFC CreateFont 用法的更多相关文章

  1. MFC——ComBox用法大全

    Combo Box (组合框)控件很简单,可以节省空间.从用户角度来看,这个控件是由一个文本输入控件和一个下拉菜单组成的.用户可以从一个预先定义的列表里选择一个选项,同时也可以直接在文本框里面输入文本 ...

  2. MFC CFileDialog用法例子。

     Set it to TRUE to construct a File Open dialog box. Set it to FALSE to construct a File Save As dia ...

  3. MFC ListControl用法

    http://blog.csdn.net/lovton/article/details/6527208 1.建立一个对象m_LogList 步骤:在对话listcontrol控件右键点击添加变量-&g ...

  4. MFC——AfxParseURL用法

    1.功能: 该函数解析URL字符串并返回服务的类型及组件,包含在 afxinet.h 头文件中. 2.定义 BOOL AFXAPI AfxParseURL(LPCTSTRpstrURL,DWORD&a ...

  5. MFC ListControl用法合集

    以下未经说明,listctrl 默认view 风格为report ------------------------------------------------------------------- ...

  6. visual_c++外挂教程(详细)

    课程分四个大章节 初级篇,中级篇,进阶篇,高级篇 初级篇内容:编写一个完整的,简单的外挂 C++的数据类型:Byte,Word,DWORD,int,float API函数的调mouse_event,G ...

  7. mfc中Button、Edit Control和MFC EditBrowse Control的用法

    [前(fei)言(hua)] 写LL(1)分析器被CString转string卡了一个多小时也是醉了. 趁着还算清醒写下这次用到的控件的使用方法好了. 这次实验的mfc用到了四个控件:Edit Con ...

  8. MFC多线程各种线程用法 .

    http://blog.csdn.net/qq61394323/article/details/9328301 一.问题的提出 编写一个耗时的单线程程序: 新建一个基于对话框的应用程序SingleTh ...

  9. MFC中CString.Format的详细用法

          本文转载自:http://blog.csdn.net/wangkaishou/article/details/5846152,感谢网友 Technorati 标签: CString For ...

随机推荐

  1. Android事件分发机制源代码分析

    小小感慨一下,做android有一段时间了,一直以来都是习惯整理笔记存到有道笔记上,没有写博客的习惯. 以后逐步分类整理出来,也算"复习"一遍了 - _ - . android的事 ...

  2. eclipse3.7之后,在引入的jquery的js文件打红叉

    使用Eclipse 3.7时,工程中加入jquery.xx.js文件,发现该文件出现错误提示(红×),但使用Eclipse 3.7以前的版本就不会出现这种提示.是因为Eclipse 3.7在.proj ...

  3. 解决svchost占用内存过高问题

    摘抄自:https://jingyan.baidu.com/article/d169e1867cea7e436611d801.html svchost占用内存过高,会导致内存100%电脑卡住,CPU温 ...

  4. django1.8forms读书笔记

    一.HttpRequest对象的一些属性或方法 request.path,The full path, not including the domain but including the leadi ...

  5. cocos2dx 3.x ccDrawLine一个坑

    ccDrawLine,如果传进去的坐标是INFINITY,画不出来.

  6. jQuery.ajax() 如何设置 Headers 中的 Accept 内容

    其实很简单,首先如果是常见类型,则请直接设置 dataType 属性 $.ajax({ dataType: "json", type: "get", succe ...

  7. QThread 实用技巧、误区----但文档中没有提到

    本文主要内容: 在任务一中,用 四 种方式实现:点击界面按钮,开线程运行一段程序,结果显示在一个Label上.1. 用不正确的方式得到看似正确的结果2. 用Qt Manual 和 例子中使用的方法3. ...

  8. paip.提升性能--多核编程中的java .net php c++最佳实践 v2.0 cah

    paip.提升性能--多核编程中的java .net php c++最佳实践  v2.0 cah 作者Attilax  艾龙,  EMAIL:1466519819@qq.com  来源:attilax ...

  9. Xilinx之RAM使用指南

    一. RAM 分类XILINX 的 RAM 可分为三种,分别是:单口 RAM,简化双口 RAM 和真双口 RAM.如下 图所示: 图1 单口 RAM 图2 简化双口 RAM A 口写入数据,B 口读数 ...

  10. 改善C#程序的建议9:使用Task代替ThreadPool和Thread

    一:Task的优势 ThreadPool相比Thread来说具备了很多优势,但是ThreadPool却又存在一些使用上的不方便.比如: 1: ThreadPool不支持线程的取消.完成.失败通知等交互 ...