奥利给!!字体/颜色对话框这么豪横的解释,赶紧PICK一下吧!!

上一篇文章介绍了如何创建基于对话框的模态对话框和非模态对话框。这篇文章为大家介绍一下字体对话框和颜色对话框的创建与实现。
话不多说,我们先来看一下效果图。
在这里插入图片描述

主要功能介绍

此实例要实现的功能:

  • 生成一个对话框,对话框中放置一个“ 字体选择” 按钮和一个编辑框。点击“ 字体选择” 按钮将弹出字体对话框。编辑框用于显示所选字体名,并以选定的字体来显示字体名字符串,例如,如果选择了华文行楷,则在编辑框中以华文行楷显示字符串“ 华文行楷” 。
  • 生成一个对话框,对话框中放置一个“ 颜色选择” 按钮,四个静态文本框和四个编辑框。四个静态文本框分别显示 颜色值、R、G、B,每个静态文本框后面跟一个编辑框,分别用来显示颜色对话框中选择的颜色值和所选颜色值的R、G、B分量。
  • 将选择的字体属性和颜色属性赋值给一个静态文本框,此例是赋值给"奥利给"静态文本框。

字体文本框

MFC使用CFontDialog类封装了字体对话框的所有操作。字体对话框也是一种模态对话框。
CFontDialog类的构造函数:

CFontDialog(
LPLOGFONT lplfInitial = NULL,
DWORD dwFlags = CF_EFFECTS | CF_SCREENFONTS,
CDC* pdcPrinter = NULL,
CWnd* pParentWnd = NULL
);

参数说明:

参数 作用
lplfInitial 指向 LOGFONT 结构体数据的指针,可以通过它设置字体的一些特征
dwFlags 指定选择字体的一个或多个属性
pdcPrinter 指向一个打印设备上下文的指针
pParentWnd 指向字体对话框父窗口的指针
LOGFONT 指针 LOGFONT 结构体中包含了字体的大部分特征,包括字体高度、宽度、方向、名称等等
typedef struct tagLOGFONT {
LONG lfHeight;//指定高度(逻辑单位) 
LONG lfWidth;//指定字符的平均宽度(逻辑单位)。如果为0,则比例自适应
LONG lfEscapement;//字符串的书写角度,单位0.1度,默认为0
LONG lfOrientation;//每个字符的书写角度,单位0.1度,默认为0 
LONG lfWeight;//字符的笔画粗细,范围0~1000,0表示默认粗细,使用数字或下表中定义的宏均可。(见表一)
BYTE lfItalic;//指定字体是否是斜体
BYTE lfUnderline;//指定字体是否有下划线
BYTE lfStrikeOut;//指定字体是否有删除线
BYTE lfCharSet;//指定字符集
BYTE lfOutPrecision;//指定文字的输出精度(见表二)
BYTE lfClipPrecision;//指定文字的剪辑精度(见表三)
BYTE lfQuality;//指定文字的输出质量(见表四)
BYTE lfPitchAndFamily;//指定以常规方式描述字体的字体系列(见表五)
TCHAR lfFaceName[LF_FACESIZE];//字体名称,名称不得超过 31 个字符。如果是空字符串,系统将使用第一个满足其它属性的字体。 
} LOGFONT;

表一:

粗细值
FW_DONTCARE 0
FW_THIN 100
FW_EXTRALIGHT 200
FW_ULTRALIGHT 200
FW_LIGHT 300
FW_NORMAL 400
FW_REGULAR 400
FW_MEDIUM 500
FW_SEMIBOLD 600
FW_DEMIBOLD 600
FW_BOLD 700
FW_EXTRABOLD 800
FW_ULTRABOLD 800
FW_HEAVY 900
FW_BLACK 900

表二:
lfOutPrecision 指定文字的输出精度。输出精度定义输出与所请求的字体高度、宽度、字符方向、行距、间距和字体类型相匹配必须达到的匹配程度。可以是以下值:

含义
OUT_DEFAULT_PRECIS 指定默认的映射行为
OUT_DEVICE_PRECIS 当系统包含多个名称相同的字体时,指定设备字体
OUT_OUTLINE_PRECIS 指定字体映射选择 TrueType 和其它的 outline-based 字体
OUT_RASTER_PRECIS 当系统包含多个名称相同的字体时,指定光栅字体(即点阵字体)
OUT_STRING_PRECIS 这个值并不能用于指定字体映射,只是指定点阵字体枚举数据
OUT_STROKE_PRECIS 这个值并不能用于指定字体映射,只是指定 TrueType 和其他的 outline-based 字体,以及矢量字体的枚举数据
OUT_TT_ONLY_PRECIS 指定字体映射只选择 TrueType 字体。如果系统中没有安装 TrueType 字体,将选择默认操作
OUT_TT_PRECIS 当系统包含多个名称相同的字体时,指定 TrueType 字体

表三:
lfClipPrecision指定文字的剪辑精度。剪辑精度定义如何剪辑字符的一部分位于剪辑区域之外的字符。可以是以下值:

含义
CLIP_DEFAULT_PRECIS 指定默认的剪辑行为
CLIP_STROKE_PRECIS 这个值并不能用于指定字体映射,只是指定光栅(即点阵)、矢量或 TrueType 字体的枚举数据
CLIP_EMBEDDED 当使用内嵌的只读字体时,必须指定这个标志
CLIP_LH_ANGLES 如果指定了该值,所有字体的旋转都依赖于坐标系统的方向是逆时针或顺时针。如果没有指定该值,设备字体始终逆时针旋转,但是其它字体的旋转依赖于坐标系统的方向。该设置影响 lfOrientation 参数的效果。

表四:
lfQuality 指定文字的输出质量。输出质量定义图形设备界面 (GDI) 必须尝试将逻辑字体属性与实际物理字体的字体属性进行匹配的仔细程度。可以是以下值:

含义
ANTIALIASED_QUALITY 指定输出质量是抗锯齿的(如果字体支持)。
DEFAULT_QUALITY 指定输出质量不重要。
DRAFT_QUALITY 草稿质量。字体的显示质量是不重要的。对于光栅字体(即点阵字体),缩放是有效的,这就意味着可以使用更多的尺寸,但是显示质量并不高。如果需要,粗体、斜体、下划线和删除线字体会被合成。
NONANTIALIASED_QUALITY 指定输出质量不是抗锯齿的。
PROOF_QUALITY 正稿质量。指定字体质量比匹配字体属性更重要。对于光栅字体(即点阵字体),缩放是无效的,会选用其最接近的字体大小。虽然选中 PROOF_QUALITY 时字体大小不能精确地映射,但是输出质量很高,并且不会有畸变现象。如果需要,粗体、斜体、下划线和删除线字体会被合成。

表五:
lfPitchAndFamily 指定以常规方式描述字体的字体系列。字体系列描述大致的字体外观。字体系列用于在所需精确字体不可用时指定字体。
1~2 位指定字体间距,可以是以下值:

含义
DEFAULT_PITCH 指定默认间距
FIXED_PITCH 指定固定间距
VARIABLE_PITCH 指定可变间距

4~7 位指定字体系列,可以是以下值:

含义
FF_DECORATIVE 指定特殊字体。例如 Old English
FF_DONTCARE 指定字体系列不重要
FF_MODERN 指定具有或不具有衬线的等宽字体。例如,Pica、Elite 和 Courier New 都是等宽字体
FF_ROMAN 指定具有衬线的等比字体。例如 MS Serif
FF_SCRIPT 指定设计为类似手写体的字体。例如 Script 和 Cursive
FF_SWISS 指定不具有衬线的等比字体。例如 MS Sans Serif

我们在字体对话框中选择了字体后,如何获取选定的字体呢?我们可以通过 CFontDialog 类的成员变量m_cf间接获得选定字体的CFont对象。m_cf是
CHOOSEFONT 类型的变量,CHOOSEFONT结构体定义如下:

typedef struct {
DWORD lStructSize;
HWND hwndOwner;
HDC hDC;
LPLOGFONT lpLogFont;
INT iPointSize;
DWORD Flags;
COLORREF rgbColors;
LPARAM lCustData;
LPCFHOOKPROC lpfnHook;
LPCTSTR lpTemplateName;
HINSTANCE hInstance;
LPTSTR lpszStyle;
WORD nFontType;
INT nSizeMin;
INT nSizeMax;
} CHOOSEFONT, *LPCHOOSEFONT;

CHOOSEFON结构体中有个成员 lpLogFont,它是指向LOGFONT结构体变量的指针,就像上面所说,LOGFONT 中包含了字体特征,例如,我们可以通过LOGFONT的lfFaceName得知字体名。
我们最终要获得的是所选择字体的CFont对象,有了字体的LOGFONT怎样获得对应的CFont对象呢?使用CFont类的成员函数CreateFontIndirect可以达到此目的。函数原型如下:

BOOL CreateFontIndirect(const LOGFONT* lpLogFont );

参数是LOGFONT指针类型,我们可以传入CFontDialog类成员变量m_cf的 lpLogFont成员,就可以得到所选字体的CFont对象了。

创建实例步骤

  1. 创建一个基于对话框的MFC工程。
  2. 在自动生成的主对话框模板中,删除“TODO:Place dialog controls here.” 静态文本框,将确定按钮ID修改为IDC_FONT_BUTTON;,Caption 修改为“ 字体选择” ;再添加一个编辑框,ID设为IDC_FONT_EDIT;再添加一个静态文本框,ID默认IDC_STATIC,Caption 修改为“ 奥利给!!” 。
  3. 在FontDlg.h中为CFontDlg类添加private成员变量:CFont m_font;用来保存编辑框中选择的字体。
  4. 为按钮IDC_FONT_BUTTON添加点击消息的消息处理函数。
  5. 修改消息处理函数如下:
void CFontDlg::OnBnClickedFontButton()
{
	// TODO: 在此添加控件通知处理程序代码
	CString strFontName; // 字体名称
	LOGFONT lf; // LOGFONT 变量
	// 将 lf 所有字节清零
	memset(&lf, 0, sizeof(LOGFONT));
	// 将 lf 中的元素字体名设为“ 宋体”
	_tcscpy_s(lf.lfFaceName, LF_FACESIZE, _T("宋体"));
	// 构造字体对话框,初始选择字体名为“ 宋体”
	CFontDialog fontDlg(&lf);
	if (IDOK == fontDlg.DoModal()) // 显示字体对话框
	{
		// 如果 m_font 已经关联了一个字体资源对象,则释放它
		if (m_font.m_hObject)
		{
			m_font.DeleteObject();
		}
		// 使用选定字体的 LOGFONT 创建新的字体
		m_font.CreateFontIndirect(fontDlg.m_cf.lpLogFont);
		// 获取编辑框 IDC_FONT_EDIT 的 CWnd 指针,并设置其字体
		GetDlgItem(IDC_FONT_EDIT)->SetFont(&m_font);// 如果用户选择了字体对话框的 OK 按钮,则获取被选择字体的名称并显示到编辑框里
		strFontName = fontDlg.m_cf.lpLogFont->lfFaceName;
		SetDlgItemText(IDC_FONT_EDIT, strFontName);
		//字体属性赋值到静态文本
		GetDlgItem(IDC_STATIC)->SetFont(&m_font);
	}
}

颜色文本框

MFC中提供了CColorDialog 类封装了颜色对
话框的所有操作,我们可以通过它显示颜色对话框,并获取颜色对话框中选择的
颜色。颜色对话框跟字体对话框一样,也是一种模态对话框。

CColorDialog 类的构造函数:

CColorDialog(
COLORREF clrInit = 0,
DWORD dwFlags = 0,
CWnd* pParentWnd = NULL
);
参数 功能
clrInit 默认选择颜色的颜色值,类型为 COLORREF,实际上就是unsigned long 类型。如果没有设置它的值,则默认为 RGB(0,0,0),即黑色
dwFlags 自定义颜色对话框功能和外观的属性值
pParentWnd 颜色对话框的父窗口的指针

我们使用颜色对话框的最终目的还是要获得在颜色对话框中选择的颜色值。为此CColorDialog类的成员函数GetColor()能够很好的实现我们的要求。
GetColor()函数的原型为:

COLORREF GetColor( ) const;

它返回所选颜色的COLORREF值。
如果我们想获得R、G、B 各分量的值可以根据GetColor得到的COLORREF颜色值,通过使用GetRValue、GetGValue和GetBValue三个宏获得。
GetRValue 的语法形式为:

BYTE GetRValue(DWORD rgb);

参数rgb就是COLORREF颜色值,返回值即是R分量值。其他两个宏的形式与之类似。例如,GetColor()函数返回的COLORREF为10000,则R分量值就是 GetRValue(10000)。

创建实例步骤:

接上面的字体文本框继续创建:

  1. 添加一个按钮,ID设为IDC_COLOR_BUTTON,Caption设为“ 颜色选择” ;再添加四个静态文本框,ID分别为IDC_COLOR_STATICIDC_R_STATICIDC_G_STATICIDC_B_STATIC, Caption分别设为“颜色值:” 、“R:” 、“G:”、“B:” ,然后每个静态文本框后添加一个编辑框,四个编辑框的ID分别为IDC_COLOR_EDITIDC_R_EDITIDC_G_EDITIDC_B_EDIT
  2. 为按钮IDC_COLOR_BUTTON添加点击消息的消息处理函数。
  3. 为静态文本框添加OnCtlColor消息用于改变静态文本框颜色。
  4. 添加代码如下:

COLORREF color = RGB(0, 0, 0); // 颜色对话框的初始颜色为黑色
CColorDialog colorDlg(color); // 构造颜色对话框,传入初始颜色值

void CFontDlg::OnBnClickedColorButton()
{
	// TODO: 在此添加控件通知处理程序代码
	if(IDOK == colorDlg.DoModal()) // 显示颜色对话框,并判断是否点击了“ 确定”
	{
		color = colorDlg.GetColor(); // 获取颜色对话框中选择的颜色值
		SetDlgItemInt(IDC_COLOR_EDIT, color); // 在 Color 编辑框中显示所选颜色值
		SetDlgItemInt(IDC_R_EDIT, GetRValue(color)); // 在 R 编辑框中显示所选颜色的 R 分量值
		SetDlgItemInt(IDC_G_EDIT, GetGValue(color)); // 在 G 编辑框中显示所选颜色的 G 分量值
		SetDlgItemInt(IDC_B_EDIT, GetBValue(color)); // 在 B 编辑框中显示所选颜色的 B 分量值
	}
	Invalidate(TRUE);//最重要的一句代码,重绘窗口
}


HBRUSH CFontDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
	HBRUSH hbr = CDialogEx::OnCtlColor(pDC, pWnd, nCtlColor);
	// TODO:  在此更改 DC 的任何特性
	if (pWnd->GetDlgCtrlID() == IDC_STATIC)// IDC_STATIC1为所选文本框ID
	{
		pDC->SetTextColor(color);//设置字体颜色
	}
	// TODO:  如果默认的不是所需画笔,则返回另一个画笔
	return hbr;
}

注:以下两行代码必须放在void CFontDlg::OnBnClickedColorButton()函数外面。 这是因为OnCtlColor消息函数需要调用color的值给静态文本框显示的字符。

COLORREF color = RGB(0, 0, 0); // 颜色对话框的初始颜色为黑色
CColorDialog colorDlg(color); // 构造颜色对话框,传入初始颜色值

结果

到此我们的所有步骤就完成了,直接编译运行,就会看到如下结果:
在这里插入图片描述
我们进行字体选择、颜色选择后就会看到文章开头显示的结果。

今天的文章就分享到这了, 奥利给!! 喜欢的点个赞再走吧。
在这里插入图片描述

发布了30 篇原创文章 · 获赞 99 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/l59565455/article/details/104844175
今日推荐