1、绘图编程
1、绘制线条
我们可以利用MFC提供的CClientDC类来实现这一功能,这个类跟CPaintDC一样,也派生于CDC类。CClientDC是窗口客户区的设备描述环境,它应用在WM_PAINT消息之外的消息处理函数中。我们只需要定义一个CClientDC对象,然后就可以利用该对象提供的函数进行绘图操作了。CClientDC对象构造时接收一个参数,即:要进行图像绘制的窗口指针对象。
CClientDC提供的划线函数:
-
绘制线条
的起始点:
MoveTo
(
CPoint
p)
p –
起始点
坐标
-
绘制
一条
到
指定点的线:
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提供的几个初始化函数如下表:
初始化一个由LOGFONT结构给出其特征的CFont对象 |
|
初始化用指定特性定义的CFont对象 |
|
用指定高度(用0.1点)和字体初始化一个CFont对象 |
|
与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。
*/
具体步骤如下:
- 在视类的OnCreate函数中设置定时器。
- 在视类中对定时器消息进行处理,因此需要给视类添加WM_TIMER消息的响应函数
- 需要使DrawText的函数的第二个参数,即显示文字的矩形范围不断增加,所以需要设置一个变量,让它旳值不断增加,实现矩形宽度的不断增加。
核心代码如下: