四. 文本编程--Windows编程课程学习笔记
Posted ling_xiao007
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了四. 文本编程--Windows编程课程学习笔记相关的知识,希望对你有一定的参考价值。
4.1 插入符
4.1.1 创建文本插入符
在视类创建响应WM_CREATE消息的消息函数。为根据字体信息来调整大小,调用CreateSolidCaret函数,基线(base line)h以上最高的为升序高度,g最低的为降序高度,之差为字体高度(tmHeight),字体没有一个具体宽度值,只有一个平均宽度(tmAveCharWidth),以及最大宽度(tmMaxCharWidth)。
CClientC dc(this);
TEXTMETRIC tm;
dc.GetTextMetrics(&tm);
CreateSolidCaret(tm.tmAveCharWidth/8,tm.tmHeight);
ShowCaret();
4.1.2 创建图形插入符
同创建文本插入符一样,在视类创建响应WM_CREATE消息的消息函数。调用CreateCaret()函数创建图形插入符。因为bmp为局部变量,当OnCreate执行完后,bmp被析构,故插入符不能够显示。可以将bmp声明为视类的私有变量或者Detach分离bmp与位图资源实现。
CBitmap bmp;
bmp.LoadBitmap(IDB_BITMAP2);
CreateCaret(&bmp);
bmp.Detach();
ShowCaret();
4.2 窗口重绘
4.2.1 OnDraw函数
MFC中专门为视类提供了响应WM_PAINT消息的响应函数OnDraw(CDC* pDC)。如果要防止窗口重绘时显示的文字或图形被刷新,文字输出和图形绘制的操作都应该在OnDraw函数里完成。
接下来,要实现一个文字输出功能,可以用TextOut函数实现。MFC提供CString类,该类没有基类。CString提供多种构造函数。
Cstring();
CString(constCstring & stringSrc);
CString(TCHARch, int nRepeat = 1);
CString(LPCTSTRlpch, int nLength);
CString (constunsigned char * psz);
CString(LPCWSTRlpsz);
CString(LPCSTRlpsz);
所以可以在视类添加以下代码。
CString str("第四讲 文本编程");
pDC->TextOut(100, 100, str);
4.2.2 创建字符串资源
CString类提供一个LoadString,可以装载一个字符串资源。在资源的String Table中添加字符串资源,在视类添加以下代码。
CString str2;
str2.LoadStringA(IDS_STRING312);
pDC->TextOutA(100, 200, str2);
4.3 路径
设备描述表有路径层,MFC中创建路径层利用了CDC类提供的BeginPath和EndPath实现,前者在设备描述表打开一个路径层,然后利用图形设备接口(GDI)提供的绘图功能绘图,后者关闭。
CDC类提供一个过的字符串宽度和高度的函数GetTextExtent。返回一个CSize类,该结构体有x,y两个私有变量。(区分GetTextMetrics)。实现一个给特定字符串加框。
CStringstr("第四讲文本编程");
pDC->TextOut(100, 100, str);
CSize sz = pDC->GetTextExtent(str);
str.LoadStringA(IDS_STRING312);
pDC->TextOutA(100, 200, str);
pDC->BeginPath();
pDC->Rectangle(100, 100, 100 + sz.cx, 100 + sz.cy);
pDC->EndPath();
运行程序没有变化,但是注释BeginPath和EndPath,一个白色矩形覆盖文本。添加以下代码绘制网格线。
for (int i = 0; i < 300; i+=10)
pDC->MoveTo(0,i);
pDC->LineTo(300,i);
pDC->MoveTo(i,0);
pDC->LineTo(i,300);
接下来介绍裁剪区域。EndPath后添加以下代码。RGN_DIFF参数时,可以看到线条到路径层断开了。它使新的裁剪区域包含了当前的裁剪区域,但把当前路径层的范围排除在外。可以在试一下RGN_AND,只有路径层显示。所以,如果希望整个图形中有局部不同则可踹放置在一个路径层中,利用SelectClipPath函数设置一种模式。
pDC->SelectClipPath(RGN_DIFF); pDC->SelectClipPath(RGN_AND);
4.4 字符输入
设计思路是,把每次输入的字符都存储在一个字符串中,在程序中,每当按下新的字符时,都在当前窗口插入符位置重新输入一遍字符串。
1)让视类捕捉WM_CHAR消息,定义一个m_strLine,并在视类构造函数初始化为空。
2)确定当前插入符位置。为此捕获WM_LBUTTONDOWN消息,在消息响应函数中,把插入符位置移动到点击位置。可以利用SetCaretPos函数实现。
SetCaretPos(point);
3)字符串成员变量取值变化问题。左键按下,字符串清空。
m_strLine.Empty();
4)字符串应该显示在插入符位置。为此,视类添加私有变量m_lMouseP,保存左键单击时的坐标,构造函数为0。
m_lMouseP = point;
5)回车字符(0x0d)处理。回车换行,清空字符串,通过GEtTExtMetrics函数计算下一行位置。
6)退格键(0x08)处理。用背景颜色重绘最后一个字符,字符串删除最后一个字符。CDC类提供GetBkColor函数获得背景色。Cstring类Left函数可以删除。
7)插入符调整。利用SetCaretPos以及GetTextExtend函数获得字符串宽度。
void CMyMFCAppView::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)
//TODO: 在此添加消息处理程序代码和/或调用默认值
CClientDC dc(this);
// 回车键处理
if (0x0d == nChar)
TEXTMETRIC tm;
dc.GetTextMetrics(&tm);
m_strLine.Empty();
m_lMouseP.y += tm.tmHeight;
// 退格键处理
else if (0x08 == nChar)
COLORREF clr= dc.SetTextColor(dc.GetBkColor());
dc.TextOut(m_lMouseP.x,m_lMouseP.y, m_strLine);
m_strLine =m_strLine.Left(m_strLine.GetLength() - 1);
dc.SetTextColor(clr);
else
m_strLine += (unsigned char) nChar;
dc.TextOut(m_lMouseP.x, m_lMouseP.y, m_strLine);
CView::OnChar(nChar, nRepCnt, nFlags);
4.4.1 设置字体
MFC提供一个CFont类设置字体,该类派生于CGdiObject类,封装了一个Windows图形设备接口(GDI)的字体。初始化函数有: CreateFont、CreateFontIndirect、CreatePointFont、CreatePontFontIndirect。作用主要是将其C++对象和字体资源关联起来。同其他GDI对象一样,创建初始化之后,需要将它选入设备描述表,用完再恢复。
BOOLCreatePointFont(int nPointSize, LPCTSTR lpszFaceName, CDC * pDC = NULL) // nPointSize为字体高度。lpszFaceName字体名称。<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);"> </span>
// 4.4.1 设置字体
CFont font;
font.CreatePointFont(200, "华文琥珀");
CFont* pOldFont = dc.SelectObject(&font);
…
dc.SelectObject(pOldFont);
4.4.2字幕变色功能
为实现该功能使用DrawText来实现。Int DrawText(const CString &str, LPRSRCT lpRect, UINT nFormat); str为输出字符串,lpRect为输出矩形区域,nFormat为输出格式。当字符串超过矩形区域自动截断。为使其不断变化、自动进行,要不断调用,同时增加矩形宽度,需要用到定时器。UINT SetTimer(UINT nIDEvent, UINT nElapse, void (CALLBACK EXPORT *lpfnTimer)(HWND, UINT, UINT, DWORD));调用成功,返回新定时器的标识。nIDEvent标识,nElapse多长时间发送一个WM_TIMER,单位是毫秒。lpfnTimer函数指针,NULL则将WM_TIMER放置到应用程序的消息队列中。
为了使举行范围不断增加,在视类添加私有变量m_nWidth,构造函数初始化为0。视类响应WM_TIMER消息,m_nWidth按3个像素点增加,也就是DrawText矩形区域按3像素增加。添加字符串资源IDS_MYSTRING。第三个参数设置为DT_LEFT左对齐。
void CMyMFCAppView::OnTimer(UINT_PTR nIDEvent)
//TODO: 在此添加消息处理程序代码和/或调用默认值
//4.4.2 字幕变色功能OnTimer
m_nWidth += 3;
CClientDC dc(this);
TEXTMETRIC tm;
dc.GetTextMetrics(&tm);
CRect rect;
rect.left = 0;
rect.top = 150;
rect.right = rect.left + m_nWidth;
rect.bottom = rect.top + tm.tmHeight;
dc.SetTextColor(RGB(255,0, 0));
CString str;
str.LoadString(IDS_MYSTRING);
dc.DrawText(str, rect, DT_LEFT);
CView::OnTimer(nIDEvent);
另外,字幕随时间平滑变色,在OnDraw添加一下源颜色显示代码。OnTimer添加超过字符串尺寸,矩形宽度置0函数。
void CMyMFCAppView::OnDraw(CDC* pDC)
…
COLORREF clr = pDC->SetTextColor(RGB(0,0, 255));
str.LoadStringA(IDS_MYSTRING);
pDC->TextOutA(0, 150, str);
pDC->SetTextColor(clr);
…
void CMyMFCAppView::OnDraw(CDC* pDC)
…
// 平滑变色
CSize sz = dc.GetTextExtent(str);
if (m_nWidth > sz.cx)
m_nWidth = 0;
dc.SetTextColor(RGB(0,0, 255));
dc.TextOut(rect.left,rect.top, str);
CView::OnTimer(nIDEvent);
以上是关于四. 文本编程--Windows编程课程学习笔记的主要内容,如果未能解决你的问题,请参考以下文章
《从零开始学Swift》学习笔记(Day 69)——Swift与Objective-C混合编程之语言