分类:
2008-10-14 14:52:51
一个简单字体察看器的实现
作者:
前言
以前喜欢没事做做网页,不怕各位见笑,都是很简单的那种静态的,有一个很头疼的问题就是字体的选择,
而且很多软件在做的时候看不到字体的例子,现在学了点VC++于是就像自己动手做一个。也算是我这个初学者的一个
小小的笔记,希望对像我一样的菜鸟有一些帮助。
介绍
通过本文,希望能学到一点有关windows各个组件的消息传递的知识。学习如何建立可用字体的列表,学会
如何指定使用的字体,如何动态改变字体。
用到的函数:EnumFontFamiliesEx。在MSDN中是这样写的:
int EnumFontFamiliesEx( HDC hdc, // handle to DC LPLOGFONT lpLogfont, // font information FONTENUMPROC lpEnumFontFamExProc, // callback function LPARAM lParam, // additional data DWORD dwFlags // not used; must be 0 );在Windows操作系统中的每一个枚举函数都需要传递一个回调函数的地址作为自变量,所以这个函数也不例外。
对象 | 属性 | 设置 |
Static Text | Caption | 输入文字 |
Edit Box | ID | IDC_EENTERED |
Static Text | Caption | 字体列表 |
List Box | ID | IDC_LFONTS |
Group Box | Caption | 示例 |
Static Text | ID Caption |
IDC_DISPLAY NULL |
Command Button |
ID Caption |
IDC_BEXIT 退出 |
注意在 Group Box 内部有一个 Static Text 和 Group Box 内部一样大,用来显示文字。
为控件添加变量:
对象 | 名称 | 类别 | 类型 |
IDC_DISPLAY | m_ctlDisplay m_strDiaplay |
Control Value |
Cstatic CString |
IDC_LFONTS | m_ctlFontList m_strFontName |
Control Value |
ClistBox CString |
IDC_EENTERED | m_strSampText | Value | CString |
为 IDC_EEXIT 添加事件代码:(注:斜体部分为输入内容):
void CFontsViewDlg::OnBnClickedBexit() { // TODO: 在此添加控件通知处理程序代码 OnOK(); }好了,到此为止,基本的框架已经建好了,下一步需要建立字体列表。首先要添加回调函数来获得每个字体列表:
// FontsViewDlg.h : 头文件 // #pragma once #include "afxwin.h" int CALLBACK MyEnumFontProc(ENUMLOGFONTEX* lpelf,NEWTEXTMETRICEX* lpntm,DWORD nFontType,long lParam);然后再向FontsViewDlg.cpp中添加回调函数的定义:
int CALLBACK MyEnumFontProc(ENUMLOGFONTEX* lpelf,NEWTEXTMETRICEX* lpntm,DWORD nFontType,long lParam) { CFontsViewDlg* pWnd=(CFontsViewDlg*) lParam; if(pWnd) { pWnd->m_ctlFontList.AddString(lpelf->elfLogFont.lfFaceName); return 1; } return 0; }我们还要构建一个函数来获取操作系统中的字体列表:选择Class View面板,选择CfontsViewDlg类,添加函数,函数名设为FillFontList,访问类型Private。
void CFontsViewDlg::FillFontList(void) { int iCurCount; CString strCurFont; CString strPrevFont=""; LOGFONT lf; lf.lfCharSet=DEFAULT_CHARSET; lf.lfFaceName[0]=NULL; lf.lfPitchAndFamily=0; m_ctlFontList.ResetContent(); CClientDC dc(this); ::EnumFontFamiliesEx((HDC) dc,&lf,(FONTENUMPROC) MyEnumFontProc,(LPARAM) this,0); for (iCurCount=m_ctlFontList.GetCount();iCurCount > 0;iCurCount--) { m_ctlFontList.GetText((iCurCount-1),strCurFont); if (strCurFont==strPrevFont) { m_ctlFontList.DeleteString((iCurCount-1)); } else { strPrevFont=strCurFont; } } }编辑 OnInitDialog 函数来调用 FillFontList 函数:
BOOL CFontsViewDlg::OnInitDialog() { CDialog::OnInitDialog(); // 将\“关于...\”菜单项添加到系统菜单中。 (略) SetIcon(m_hIcon, TRUE); // 设置大图标 SetIcon(m_hIcon, FALSE); // 设置小图标 // TODO: 在此添加额外的初始化代码 FillFontList(); return TRUE; // 除非设置了控件的焦点,否则返回 TRUE }好了,现在可以编译一下,看看有什么结果发生了:)
BOOL CFontsViewDlg::OnInitDialog() { CDialog::OnInitDialog(); ... // 将\“关于...\”菜单项添加到系统菜单中。 ... SetIcon(m_hIcon, TRUE); // 设置大图标 SetIcon(m_hIcon, FALSE); // 设置小图标 // TODO: 在此添加额外的初始化代码 FillFontList(); m_strEntered="大家好"; m_strDisplay=m_strEntered; UpdateData(FALSE); return TRUE; // 除非设置了控件的焦点,否则返回 TRUE }为IDC_EENTERED添加EN_CHANGE事件消息函数:
void CFontsViewDlg::OnEnChangeEentered() { // TODO: 如果该控件是 RICHEDIT 控件,则它将不会 // 发送该通知,除非重写 CDialog::OnInitDialog() // 函数并调用 CRichEditCtrl().SetEventMask(), // 同时将 ENM_CHANGE 标志“或”运算到掩码中。 ? // TODO: 在此添加控件通知处理程序代码 UpdateData(TRUE); m_strDisplay=m_strEntered; UpdateData(FALSE); }OK,再编译一下看看:)
void CFontsViewDlg::SetMyFont(void) { CRect rRect; if(m_strFontName.GetLength()>0) { m_ctlDisplay.GetWindowRect(&rRect); m_fSetFont.Detach(); m_fSetFont.CreateFont((rRect.Height()-5), 0,0,0,FW_NORMAL, 0, 0, 0, DEFAULT_CHARSET, OUT_CHARACTER_PRECIS, CLIP_CHARACTER_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH|FF_DONTCARE, m_strFontName); m_ctlDisplay.SetFont(&m_fSetFont); } }最后给 IDC_LFONTS 添加一个 LBN_SELCHANGE 事件消息函数就大功告成了:
void CFontsViewDlg::OnLbnSelchangeLfonts() { // TODO: 在此添加控件通知处理程序代码 UpdateData(TRUE); SetMyFont(); }