写点什么

MFC|自绘 Static 控件

  • 2022 年 7 月 11 日
  • 本文字数:2382 字

    阅读完需:约 8 分钟

MFC|自绘Static控件

最近一段时间系统的整理了下关于 MFC 框架的知识点,想给大家分享下关于 MFC 框架下控件的自绘知识。也是我刚刚参加工作实现的一整套控件自绘,这里,我会逐一进行讲解的

首先,我们来拿 MFC 下最简单的静态文本控件来讲解吧!

很多时候,我们在使用静态控件只是用于显示文本,但是也有显示图片的时候。

当前自绘的静态文本控件可以实现哪些功能:


1:文本字体颜色值设置

2:背景色以及背景图片设置

3:是否填充背景色

4:文本的对齐方式


根据以上上述功能,我来具体讲解该控件的自绘功能吧!

一般情况下,自绘控件的父类都是基于框架原始类实现的。

class UIStatic:public CStatic{}
复制代码

这种方式我们才使用控件时,直接将 CStatic 类替换成 UIStatic 就可以啦!

在 MFC 框架下自绘的方式也会有所不同,例如当前所有的控件,需要在 OnPaint 消息中进行重新绘制。

OnPaint 自绘

既然是要自绘,那么系统控件 CStatic 类风格显示的内容都会被覆盖的,我们需要在 OnPaint 中重新定义字体显示风格、文本风格以及背景风格

设置字体风格

CFont *font = GetFont();CFont *oldFont = dc.SelectObject(font);//OnPaint最后,一定要写的哦~dc.SelectObject(oldFont);
复制代码

这里很多人都会疑问,为什么不直接在 OnPaint 中随时设置字体的风格呢?

首先,我们不确定使用该控件的程序员是否会设置字体风格,采用 GetFont 的方式如果不进行设置自定义的字体风格时,可以默认使用系统的风格。

设置字体颜色值

这里的字体颜色是需要用户设置的,所以在这里设置的颜色值不是能写成固定值的哦~

dc.SetTextColor(m_crText);dc.SetBkMode(TRANSPARENT);
复制代码

那么,如何设置字体的颜色值呢?有两种方式,大家可以拿小本本记录下来哟~

方法 1:DWORD 方式传入

RGB(GetBValue(color),GetGValue(color),GetRValue(color));
复制代码

方法 2:COLORREF 方式传入

void SetTextColor(COLORREF color){   m_crText = color;}
复制代码

设置背景色以及背景图片

处于简单实现,这里加载图片的方式采用了 CImage,但是这个类有一个弊端,就是图片偏大或者偏小时,会失真,必须按照图片的大小进行设置。

如果存在了背景图片,那么就将该控件的背景显示成图片信息;

if (! m_ImgBackground.IsNull()){	m_ImgBackground.Draw((*pDC).GetSafeHdc(),rect);}
复制代码

如果不存在图片信息,就是用设定的背景颜色值。当前的背景颜色值设置也可以用上面文本颜色值的设置方法哦~

else{    pDC->FillSolidRect(rect , m_crBackground);}
复制代码

设置文本对齐方式

文本的对齐方式有:左、右、靠上、靠下、水平居中、垂直居中,那么来看看是如何显示的吧!

定义一个 UINT 类型的成员变量,用来接收用户传入的字体显示风格

UINT m_uFormat;
复制代码

我们会根据实际的风格来设置文本的显示位置

当用户设置了垂直风格时?

if(m_uFormat & DT_VCENTER){	int   nTextHeight = csText.cy ;	if (csText.cx > rectItem.Width())//多行	{		int  row_num = csText.cx / rect.Width() +1 ;	//计算有多少行		nTextHeight = csText.cy * row_num ; //计算总共的行高	}	rectItem.top   = rect.top+(rect.Height()-nTextHeight)/2;}
复制代码

我们不知道传入的文本具体长度是多少,想要在控件的垂直居中位置显示文本时,需要知道应该显示几行文本,以及传入的字符串的总体像素单位长度是多少。

这里,会用到一个叫做 GetTextExtent 函数,获取传入文本的大小,也就是长度和宽度。

CSize   csText = pDC->GetTextExtent(strText);
复制代码

需要注意的是:该函数只有在 OnPaint 绘制操作时有效,或者是你可以 GetDC 时也会生效,其他地方获取得 CSize 是不准确的哦~

当字符串的显示长度超过控件本身宽度时,肯定是需要显示多行信息,也就意味着上述代码的多行显示了。

那么,剩下的无论是靠左风格、靠右风格以及水平居中风格,直接设置就可以。

dc.DrawText(strText , rectItem , DT_LEFT|DT_WORDBREAK); //靠左设置
复制代码



字体设置

接下来,这也算是贯穿整个自绘控件中的通用设置了,无论是哪个控件都是可以适用的~小本本准备好了吗?

定义一个叫做 SetTextFont()的函数用于设置控件的字体风格

完整的函数声明,如下:

void SetTextFont(int ftSize , CStringW ftType , int fontmode= PointFont_Mode, DWORD  nStyle = FontStyle_Normal);
复制代码

参数 1:字体的大小

参数 2:字体的风格,例如:微软雅黑,宋体、黑体

参数 3:创建字体模式,默认是模式 1,这里有两种字体创建模式

参数 4:设置字体风格

默认是 FontStyle_Normal,没有任何风格

FontStyle_Bold = 2 , //粗体

FontStyle_Italics = 4, //斜体

FontStyle_Underline = 8 , //下划线

当前的风格值是根据系统的参数值进行依依对应的。

注意:

当我们在设置字体风格时,一定要先销毁上一次使用的字体风格,再重新设置!

m_font.DeleteObject();
复制代码

方法 1 设置:

当前方法采用了 CreatePointFont 方式。

对于这种方式来说,设置很简单

m_font.CreatePointFont( ftSize*10 , ftType);
复制代码

为什么要*10 设置呢?那是因为使用该方法设置字体时,设置的字体很小,一般做乘 10 处理。

方法 2 设置:

当前方法采用了 CreateFontIndirect 方式。

使用该方法需要设置的参数比较多

GetObject(GetStockObject(SYSTEM_FONT),sizeof(LOGFONT),&logFont);  	logFont.lfHeight=ftSize;//字体高度为16PX  //根据 用户 设定风格 判定,是否需要设置?if (nStyle & FontStyle_Underline){	logFont.lfUnderline = TRUE;			//文字底部加下划线}else	logFont.lfUnderline = FALSE;if (nStyle & FontStyle_Bold){	logFont.lfWeight = 650    ;			//文字加粗}else	logFont.lfWeight = 0;if (nStyle & FontStyle_Italics){	logFont.lfItalic = TRUE;		//斜体文本}else	logFont.lfItalic = FALSE;logFont.lfWidth = 0;//字体宽度为20PX  logFont.lfCharSet=GB2312_CHARSET;//国标2312  wsprintf(logFont.lfFaceName,TEXT("%s"),strFtType);  
复制代码

该控件的讲解到这里就结束了,如果有疑问,欢迎探讨哦!

我是中国好公民 st,一名 C++开发程序媛~

发布于: 刚刚阅读数: 6
用户头像

书山有路勤为径,学海无涯苦作舟 2022.07.01 加入

擅长语言:C++ 涉及语言:Python

评论

发布
暂无评论
MFC|自绘Static控件_c++_中国好公民st_InfoQ写作社区