07 MFC的绘图及文本编程

版权声明:原创不易,如引用,请附原文链接 https://blog.csdn.net/Chiang2018/article/details/88757141

1、绘图编程

1、绘制线条

我们可以利用MFC提供的CClientDC类来实现这一功能,这个类跟CPaintDC一样,也派生于CDC类。CClientDC是窗口客户区的设备描述环境,它应用在WM_PAINT消息之外的消息处理函数中。我们只需要定义一个CClientDC对象,然后就可以利用该对象提供的函数进行绘图操作了。CClientDC对象构造时接收一个参数,即:要进行图像绘制的窗口指针对象。

CClientDC提供的划线函数:

  1. 绘制线条的起始点:MoveToCPoint p) p – 起始点坐标
  2. 绘制一条指定点的线:LineTo(CPoint p) p – 终点坐标

2、绘制彩色线条

我们实现的画线功能,绘制的都是黑色的线条。这是因为设备描述表中有一个默认的黑色画笔。如果想要绘制其他颜色的线条,首先需要创建一个特定颜色的画笔,然后将此画笔选入设备描述表中,接下俩绘制的线条的颜色就由这个新画笔决定了。

我们可以通过MFC提供的类CPen来创建画笔对象。

CPen(int nPenStyle,int nWidth,COLORREF crColor);

第一个参数:指定笔的线型(实线、点线、虚线等)

第二个参数:线的宽度

第三个参数:颜色,是一个RGB宏

COLORREF RGB(BYTE bRed,BYTE bGreen,BYTE bBlue)

当构建一个GDI(图形设备接口)对象后该对象并不会马上生效,必须选入设备描述表,它才会在以后的操作中生效。可以使用SelectObject函数把GDI对象选入设备描述表中,并且该函数会返回指向先前备选对象的指针。

 

2、文本编程

1、创建插入符

在我们使用文本编辑器的时候,在这些文本处理程序的编辑窗口中都有一条闪烁的竖线,将之称为插入符。插入符可以用于提示用户:你输入的文字信息将在这个插入符所在的位置显示出来。

程序中想要创建插入符,可以利用CWnd类的CreateSolidCaret()函数该函数原型:

void CreateSolidCaret(int nWidth,int nHeight);

函数的两个参数分别代表插入符的宽度和高度。

如何让插入符适合于当前字体的大小呢?首先我们需要得到设备描述表中当前字体的信息,然后根据字体信息来调整插入符的大小。可以通过调用CDC类的GetTextMetrics成员函数得到设备描述表中当前字体的度量信息。函数原型如下:

BOOL GetTextMetrics(LPTEXTMETRIC lpMetrics)const

我们使用CreateSolidCaret函数创建插入符之后,插入符初始状态是隐藏的,必须调用ShowCaret()函数来显示插入符

在前边我们已经讲过,视类窗口始终位于框架窗口之上,对窗口客户区的鼠标和键盘操作实际上都是在视类窗口上进行的,因此应该在视类窗口上创建插入符。

插入符的创建应该在窗口创建之后进行,可以在WM_CREATE消息的响应函数OnCreate中添加创建插入符的代码。

2、字符输入

想要实现字符的输入功能,也就是当我们按下键盘上某个键之后,要把该字符输出到程序窗口上,这就需要捕获键盘按下(WM_CHAR)这一消息。我们需要利用TextOut函数在窗口输出字符串,TextOut函数原型:

BOOL TextOut(int x ,int y ,const CString& str);

根据函数我们可以知道输出字符时我们需要提供字符的x,y坐标,但是这是有难度的,因为每个字符在屏幕所占的宽度都不一样,所以我们获取下一个输入点的坐标就不太容易实现。所以我们可以采用一种简单的方式,把每次输入的字符都保存到一个字符串中,当每次输入新的字符时,我们就在窗口当前插入符的位置重新把字符串输出一次。

需要注意的到的几个问题:

1、程序在当前插入的符的位置输出字符。也就是说程序运行时,如果鼠标左键单击窗口中的某个位置,那么插入符就移动到这个地方,随后输入的字符都应该在此位置往后输出。把插入符移动到鼠标左键的单击处,可以利用CWnd类的SetCaretPos函数来实现,函数声明如下:

static void PASCAL SetCaretPos( POINT point );

参数: point 指定了插字符的新的x和y坐标(客户坐标)。  

2、用来存储输入字符的字符串取值变化问题。

当鼠标左键单击窗口中一个新的地方时,插入符就会移动到这个位置,那么以后输入的字符都应该从这个位置开始输出,以前输入的字符不应该再从此位置输出,依次需要把存储字符的字符串清空。

3、每次输入的字符串都应该在当前插入符的位置,也就是鼠标单击的位置开始显示。这样就需要把鼠标左键单击的坐标保存起来,以便在On_Char函数中使用。

4、在输出字符时,还需要考虑到回车字符的处理,按下回车后,插入符应切换到下一行,随后的输入也应该新的一行开始输出,前面介绍过GetTextMetrics函数,可以获得当前设备描述表中字体高度信息。

5、在输出字符时,还需要另外一个字符处理,退格键。按下退格键需要删除屏幕上位于插入符前面的那个字符。我们可以采取最简单的实现方式,先将文本颜色设置为背景色,在窗口中将字符串输出一次,然后将字符串中最后一个字符删掉,再把文本颜色设置为原来是颜色,将字符串再输出一次。屏幕上就看到了正确的删除效果。获取背景颜色可以使用CDC类的GetBKColor函数。而设置文本颜色我们可以使用CDC类提供的另一个成员函数SetTextColor函数,这个函数将会返回文本之前的颜色。如果想要实现从字符串中删除一个字符,可以使用CString类的Left函数。函数原型: CString Left(int nCount) const;返回一个CString对象,即返回指定字符串左边指定数目(nCount参数指定)的字符。

完成上述代码之后,执行程序,可以在窗口中插入字符了,但是插入符的位置没有改变,一般情况我们需要插入随着字符的输入而移动,我们知道可以利用SetCaretPos函数来设置插入符的位置,但是移动的位置如何确定呢?实际上对于同一行输入来说,插入符横向移动的距离就是输入字符的宽度,纵坐标是没有改变的。可以利用函数GetTextExtent得到字符串的宽度。

核心代码如下:

3、设置字体

MFC中提供了CFront类专门来设置字体。这个类派生于CGdiObject类,封装了一个Windows图形设备接口的字体。在编程时,在构造了一个CFont对象后,还必须利用该类提供的几个初始化函数之一对该对象进行初始化,然后才能使用这个对象。

CFont提供的几个初始化函数如下表:

CreateFontIndirect 

初始化一个由LOGFONT结构给出其特征的CFont对象

CreateFont 

初始化用指定特性定义的CFont对象

CreatePointFont 

用指定高度(用0.1点)和字体初始化一个CFont对象

CreatePointFontIndirect 

与CreateFontIndirect相似,但字体高度用0.1点定义而不用逻辑单位定义

这些初始化函数的主要作用就是讲CFront这个C++对象与字体资源关联起来。

在程序中与其他GDI对象一样,当创建了一个字体对象并初始化后,还必须将他选入设备描述表,之后这个新字体才能发挥作用。这个可以利用CDC类的SelectObject函数来实现,同样函数会返回先前的字体,我们可以保存这个字体,在使用完新字体之后,再把设备描述表中的字体恢复为先前的字体。

4、字体变色

为了达到平滑的变色效果我们需要利用CDC类提供的另一个文字输出的函数DrawText来实现,该函数声明如下:

int DrawText(const CString& str, LPRECT lpRect, UNIT nFormat);

该函数实际上是把文字输出局限在一个矩形范围内。当初始输出文本是先把矩形的宽度设置为一个较小的值,然后不断加大矩形的宽度,这样就可以不断的增加显示文字的内容,从而实现文字平滑变色的效果。

文字变色是一个不断变化、自行进行的过程,这意味着我们需要不断的调用DrawText函数,同时增大包含文本的矩形宽度。要实现这个功能,我们需要用到定时器,通过定时器自动控制文字颜色的进程。

利用CWnd类的SetTimer成员函数可以设置定时器。函数原型如下:

UINT SetTimer(UINT nIDEvent, UINT nElapse, void (CALLBACK EXPORT*lpfnTimer) (HWND, UINT, UINT, DWORD) );
/*
nIDEvent 指定了不为零的定时器标识符。  
nElapse 指定了定时值;以毫秒为单位。  
lpfnTimer 指定了应用程序提供的TimerProc回调函数的地址,该函数被用于处理WM_TIMER消息。如果这个参数为NULL,则WM_TIMER消息被放入应用程序的消息队列并由CWnd对象来处理。

如果函数成功,则返回新定时器的标识符。应用程序可以将这个值传递给KillTimer成员函数以销毁定时器。如果成功,则返回非零值;否则返回0。

*/

具体步骤如下:

  1. 在视类的OnCreate函数中设置定时器。
  2. 在视类中对定时器消息进行处理,因此需要给视类添加WM_TIMER消息的响应函数
  3. 需要使DrawText的函数的第二个参数,即显示文字的矩形范围不断增加,所以需要设置一个变量,让它旳值不断增加,实现矩形宽度的不断增加。

核心代码如下:

 

猜你喜欢

转载自blog.csdn.net/Chiang2018/article/details/88757141
07