友情提示:如果本网页打开太慢或显示不完整,请尝试鼠标右键“刷新”本网页!
C语言实例教程(PDF格式)-第47部分
快捷操作: 按键盘上方向键 ← 或 → 可快速上下翻页 按键盘上的 Enter 键可回到本书目录页 按键盘上方向键 ↑ 可回到本页顶部! 如果本书没有阅读完,想下次继续接着阅读,可使用上方 "收藏到我的浏览器" 功能 和 "加入书签" 功能!
dc。SelectObject(pOldFont);
}
图9。 6 示例程序BrushDemo的运行结果
以前几节讲述的方法编译并链接上面的应用程序,运行结果如图9。6
所示。
第四节 字体对象
MFC类CFont封装了Windows图形设备接口中的字体对象。字体对象决
定的设备上下文中进行文本输出的字符样式。在使用字体对象的时
候,我们一般先创建一个CFont对象,然后调用CreateFont、
CreateFontIndirect、CreatePointFont及CreatePointFontIndirect
之一的成员函数来对该字体对象进行初始化。
9。4。1 创建字体对象
创建字体对象的最方便的方法是使用CreatePointFont函数,
CreatePointFont函数仅需三个参数,其原型如下:
BOOL CreatePointFont( int nPointSize; LPCTSTR lpszFaceName; CDC* pDC = NULL );
第一个参数nPointSize以十分之一磅为单位设置字体的大小,磅是印
刷行业中的常用度是单位,1磅=1/72英寸≈0。03528厘米。磅这个单
位在涉及图形和文本输出的Windows应用程序中被大量的使用,因此
我们应该熟知它和其它常用度量单位之间的换算关系。在后面的部分
中我们还会讨论到在Windows编程中还会使用到的其它度量单位以及
…………………………………………………………Page 550……………………………………………………………
它们之间的换算关系。
参数lpszFaceName指定了创建字体对象所使用的字体名,pDC指向一
个设备上下文对象,函数CreatePointFont将以磅表示的字体大小转
换为pDC所指向的设备上下文中相应的逻辑单位。如果指针pDC为空,
函数CreatePointFont将字体大小以设备单位表示。
9。4。2 LOGFONT结构
在Windows内部,字体是以一个名为LOGFONT的结构来表示的。结构
LOGFONT的定义如下:
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;
各成员的含义如下:
lfHeight: 以逻辑单位指定字体字符元
(character cell)或字符的高
…………………………………………………………Page 551……………………………………………………………
度。字符高度值为字符元高度值
减去内部行距 (internal
leading)值。当lfHeight大于0
时,字体映射程序将该值转换为
设备单位,并将它与可用字体的
字符元高度进行匹配;当该参数
为0时,字体映射程度将使用一个
匹配的默认高度值;如果参数的
值小于0,则将其转换为设备单
位,并将其绝对值与可用字体的
字符高度进行匹配。
对于任何一种情况,字体映射程
度最终得到的字体高度值不会超
过所指定的值。以MM_TEXT映射模
式下,字体高度值和磅值有如下
的换算公式:
lfHeight=…MulDiv(PointSize;
GetDeviceCaps(hDC; LOGPIXELSY); 72);
lfWidth: 以逻辑单位指定字体字符的平均
宽度。如果lfWidth的值为0,则
根据设备的纵横比从可用字体的
数字转换纵横中选取最接近的匹
配值,该值通过比较两者之间的
差异的绝对值得出。
lfEscapement: 以十分之一度为单位指定每一行
文本输出时相对于页面底端的角
度。
ifOrientation: 以十分之一度为单位指定字符基
线相对于页面底端的角度。
lfWeight: 指定字体重量。在Windows中,字
体重量这个术语用来指代字体的
粗细程度。lfWeight的范围为0到
1000,正常情况下的字体重量为
400,粗体为700。如果lfWeight
为0,则使用默认的字体重量。
…………………………………………………………Page 552……………………………………………………………
lfItalic: 当lfItalic为TRUE时使用斜体
lfUnderline: 当lfUnderline为TRUE时给字体添
加下划线
lfStrikeOut: 当lfStrikeOut为TRUE时给字体添
加删除线
lfCharSet: 指定字符集。可以使用下面的预
定义值:
ANSI_CHARSET
OEM_CHARSET
SYMBOL_CHARSET
UNICODE_CHARSET
其中OEM字符集是与操作系统相关
的。
lfOutPrecision: 指定输出精度。输出精度定义了
输出与所要求的字体高度、宽
度、字符方向等的接近程度。它
可以为下面的值之一:
OUT_CHARACTER_PRECIS
OUT_DEFAULT_PRECIS
OUT_STRING_PRECIS
OUT_STROKE_PRECIS
lfClipPrecision: 指定剪辑精度。剪辑精度定义了
当字符的一部分超过剪辑区域时
对字符的剪辑方式,它可以为下
列值之一:
CLIP_CHARACTER_PRECIS
CLIP_DEFAULT_PRECIS
…………………………………………………………Page 553……………………………………………………………
CLIP_STROKE_PRECIS
lfQuality: 定义输出质量。输出质量定义了
图形设备接口在匹配逻辑字体属
性到实际的物理字体的所使用的
方式,它可以为下列值之一:
DEFAULT_QUALITY (默认质量)
DRAFT_QUALITY (草稿质量)
PROOF_QUALITY (正稿质量)
lfPitchAndFamily: 指定字体的字符间距和族。最低
两位指定字体的字符间距为以下
值之一:
DEFAULT_PITCH
FIXED_PITCH
VARIABLE_PITCH
第4到7位指定字体族为以下值之
一:
FF_DECORATIVE
FF_DONTCARE
FF_MODERN
FF_ROMAN
FF_SCRIPT
FF_SWISS
这些值的具体含义可以参考
Visual C++中关于结构LOGFONT的
文档。
字符间距和字体族可以使用逻辑
…………………………………………………………Page 554……………………………………………………………
或(OR)运算符来进行组合。
lfFaceName: 一个指定以NULL结尾的字符串的
指针,它指定的所用的字体名。
该字符串的长度不得超过32个字
符,如果lfFaceName为NULL,图
形设备接口将使用默认的字体
名。
9。4。3 使用字体对象和枚举系统中的所有字体
示例程序FontDemo演示了LOGFONT结构和CFont对象的使用。此外,在
该示例程序中,我们还演示了如何获得当前系统中已安装的所有可用
字体,这些信息是通过API函数EnumFontFamilies和自定义的字体枚
举回调函数EnumFontFamProc来得到,并放入程序主窗口内的列表框
中的。
#include
#include
#include
#define DegToRnd(x) (x/180。*3。14159)
int WINAPI EnumFontFamProc(const LOGFONTA *lplf;
const TEXTMETRICA *lptm; unsigned long FontType; LPARAM lParam);
// 派生应用程序类
class CMyApp : public CWinApp
{
public:
virtual BOOL InitInstance();
};
// 派生窗口类
class CMyWnd : public CFrameWnd
{
…………………………………………………………Page 555……………………………………………………………
public:
CListBox lst;
protected:
// 声明消息处理函数
afx_msg void OnPaint();
afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
DECLARE_MESSAGE_MAP();
};
// 初始化应用程序实例
BOOL CMyApp::InitInstance()
{
// 创建应用程序的主窗口
CMyWnd *pWnd=new CMyWnd;
pWnd…》Create(NULL; 〃字体示例〃);
// 显示应用程序主窗口并刷新其客户区
pWnd…》ShowWindow(SW_SHOW);
pWnd…》UpdateWindow();
// 在主窗口关闭时终止应用程序的执行线程
m_pMainWnd=pWnd;
return TRUE;
}
// 声明唯一的应用程序对象
CMyApp MyApp;
// 应用程序主窗口的消息映射
BEGIN_MESSAGE_MAP(CMyWnd; CWnd)
ON_WM_CREATE()
…………………………………………………………Page 556……………………………………………………………
ON_WM_PAINT()
END_MESSAGE_MAP()
// 应用程序主窗口的重绘函数
void CMyWnd::OnPaint()
{
// 获得窗口的客户区设备上下文句柄
CPaintDC dc(this);
// 设置字体输出背景为透明
dc。SetBkMode(TRANSPARENT);
// 获得设备上下文所使用的当前字体
LOGFONT lf;
dc。GetCurrentFont()…》GetLogFont(&lf);
CFont font1; font2;
CFont *pOldFont; // 保存设备上下文最初使用的字体对象
// 创建 font1 为 12 象素宋体
lf。lfCharSet=134;
lf。lfHeight=…12;
lf。lfWidth=0;
strcpy(lf。lfFaceName; 〃宋体〃);
font1。CreateFontIndirect(&lf);
// 更改当前字体为 20 象素的 Times New Roman,并且向上倾斜 40 度
lf。lfCharSet=0;
strcpy(lf。lfFaceName; 〃Times New Roman〃);
lf。lfEscapement=400;
lf。lfHeight=…20;
font2。CreateFontIndirect(&lf);
…………………………………………………………Page 557……………………………………………………………
pOldFont=dc。SelectObject(&font2);
// 获得字符串 〃lfEscapement= 400〃 在输出时的宽度和高度
CSize sz=dc。GetTextExtent(〃lfEscapement= 400〃);
// 计算字符串合适的输出位置
dc。TextOut(10; 10+int(sz。cx*sin(DegToRnd(40))); 〃lfEscapement= 400〃);
// 将字体输出方向更改为向下倾斜 40 度
lf。lfEscapement=…400;
dc。SelectObject(pOldFont);
font2。DeleteObject();
font2。CreateFontIndirect(&lf);
dc。SelectObject(&font2);
// 计算字符串合适的输出位置
dc。TextOut(290…int(sz。cx*cos(DegToRnd(40))); 10; 〃lfEscapement=…400〃);
// 将字体输出方向更改为水平方向
lf。lfEscapement=0;
dc。SelectObject(pOldFont);
font2。DeleteObject();
font2。CreateFontIndirect(&lf);
dc。SelectObject(&font2);
// 对称于直线 x=150 输出字符串 〃lfEscapement=0〃
sz=dc。GetTextExtent(〃lfEscapement=0〃);
dc。TextOut(150…sz。cx/2; 110; 〃lfEscapement=0〃);
// 更改当前字体为最细的 50 象素大小的宋体
lf。lfCharSet=134;
strcpy(lf。lfFaceName; 〃宋体〃);
lf。lfEscapement=0;
…………………………………………………………Page 558……………………………………………………………
lf。lfWeight=0;
lf。lfHeight=…50;
dc。SelectObject(pOldFont);
font2。DeleteObject();
font2。CreateFontIndirect(&lf);
dc。SelectObject(&font2);
// 输出一个 〃细〃 字
dc。TextOut(330; 10; 〃细〃);
// 在旁边使用 12 象素大小的宋体字给出当前字体的重量
dc。SelectObject(&font1);
dc。TextOut(395; 29; 〃lfWeight=0〃);
// 更改当前字体为最粗的 50 象素大小的字体
lf。lfWeight=1000;
dc。SelectObject(pOldFont);
font2。DeleteObject();
font2。CreateFontIndirect(&lf);
dc。SelectObject(&font2);
// 输出一个 〃粗〃 字
dc。TextOut(330; 80; 〃粗〃);
dc。SelectObject(&font1);
// 在旁边使用 12 象素大小的宋体字给出当前字体和重量
dc。TextOut(395; 99; 〃lfWeight=1000〃);
// 恢复设备上下文原有的 GDI 绘图对象
dc。SelectObject(pOldFont);
}
// 主窗口的 WM_CREATE 消息的处理函数
…………………………………………………………Page 559……………………………………………………………
int CMyWnd::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
// 调用基类的默认消息处理函数
int iResult=CWnd::OnCreate(lpCreateStruct);
// 创建一个列表框,该列表框中给出了当前系统中安装的所有可用字体
lst。Create(LBS_STANDARD | LBS_USETABSTOPS | WS_CHILD | WS_VISIBLE;
CRect(10; 150; 480; 350); this; 1001);
// 更改列表框所用的字体为 9 磅 (12 象素) 大小的宋体
static CFont font;
font。CreatePointFont(90; 〃宋体〃);
lst。SetFont(&font);
// 设置列表框的制表符位置为 200 个对话框单位
lst。SetTabStops(200);
// 枚举当前系统的所有可用字体,将指向列表框的 CListBox 对象的指针作为应用程序提供
的
// 参数传递给枚举字体回调函数 EnumFontFamProc
EnumFontFamilies(::GetDC(GetSafeHwnd()); NULL; EnumFontFamProc; (LPARAM)(&lst));
return iResult;
}
// 枚举字体时的回调函数,该函数将系统的所有可用字体及其字符集添加到列表框中,
// 由应用程序提供的参数 lParam 提供了指向该列表框的 CListBox 对象的指针
int WINAPI EnumFontFamProc(const LOGFONTA * lplf;
const TEXTMETRICA *lptm; unsigned long FontType; LPARAM lParam)
{
CListBox *pList=(CListBox*)lParam;
CString str;
// 将当前字体的字体名 (FaceName) 和字符集 (CharSet) 添加到列表框中
…………………………………………………………Page 560……………………………………………………………
str。Format(〃FACENAME: %s tCHARSET: %d〃; lplf…》lfFaceName; lplf…》lfCharSet);
pList…》AddString(str);
return TRUE; // 返回 TRUE 以继续字体枚举的过程,返回 FALSE 将终止字体枚举的过程
}
我们先来看重绘消息处理函数OnPaint,一开始时,我们调用了CDC类
的成员函数GetCurrentFont,该成员函数返回当前设备上下文所使用
的字体,其返回值是一个指向CFont对象的指针,然后,我们通过该
指针调用CFont类的成员函数GetLogFont,该成员函数将字体的信息
填入到一个LOGFONT结构中。在下面的步骤中,我们通过修改该结构
的成员来创建新的字体对象。首先,我们创建一个CFont对象font1,
font1使用了12个象素大小的宋体字,在程序中它主要用来输出一些
标识文本。这里,我们先在LOGFONT结构对象lf在相关成员中填入新
的值,再以该结构对象为参数来调用CFont类的成员函数
CreateFontIndirect创建相应的GDI字体对象。这里我们将lfCharSet
成员修改为134 ,这个值可以通过本程序的运行结果得出,lfWidth
成员修改为0,这样将使用默认的字符纵横比得到字符的宽度。
在下面过程中,我们按照类似的方法创建一大小为20个象素的Times
New Roman字体,与刚才不同的是,我们将结构对象lf的
lfEscapement成员的值设置为400,这样,文本将以向上倾斜40度
(lfEscapement的值的单位为1/10度)的角度进行输出。接着,我们将
该字体对象通过CDC的成员函数SelectObject选入设备上下文中作为
设备上下文的当前字体。CDC类的成员函数GetTextExtent可以在输出
一个字符串之前得到该输出字符串的大小,以便于我们可以恰当的安
排字符串的输出位置。需要注意的是,通过该成员函数得到的度量值
不会受到我们在lfEscapement中设置的值的影响。在程序示例中,我
们通过成员函数GetTextExtent得到字符串〃lfEscapement= 400〃在输
出时的长度和宽度,然后根据所得的结果计算得出以40度角输出文本
串的合适的起始位置,最后调用CDC类的成员函数TextOut以当前字体
输出字符串〃lfEscapement= 400〃。
l 注意:
l 不管当前的lfEscapement值如何,函数TextOut总是以输出字符串
的第一个字符的起始位置的坐标作为其前两个参数。
l 在Windows 95中,lfEscapement和lfOrientation总是具有相同的
值,而在Windows NT中,两者在某些情况下可以不相同。
…………………………………………………………Page 561……………………………………………………………
l 设置lfFaceName时应该使用库函数strcpy,不要犯这样的错误:
l lfFaceName=〃宋体〃;
此外,如果为lfFaceName设置了新�
快捷操作: 按键盘上方向键 ← 或 → 可快速上下翻页 按键盘上的 Enter 键可回到本书目录页 按键盘上方向键 ↑ 可回到本页顶部!
温馨提示: 温看小说的同时发表评论,说出自己的看法和其它小伙伴们分享也不错哦!发表书评还可以获得积分和经验奖励,认真写原创书评 被采纳为精评可以获得大量金币、积分和经验奖励哦!