文本处理程序都有插入符,在MFC中使用CreateSolidCaret实现创建插入符,创建完成后使用ShowCaret显示插入符。
int CCH_5_TEXTView::OnCreate(LPCREATESTRUCT lpCreateStruct) { if (CView::OnCreate(lpCreateStruct) == -1) return -1; // TODO: Add your specialized creation code here CreateSolidCaret(20,100); ShowCaret(); return 0; }
CClientDC dc(this); TEXTMETRIC tm; dc.GetTextMetrics(&tm); CreateSolidCaret(tm.tmAveCharWidth/8,tm.tmHeight); ShowCaret();
m_bitmap.LoadBitmap(IDB_BITMAP1); CreateCaret(&m_bitmap);我们前面的画图程序,有一个明显的问题,就是如果我们改变了窗口的大小或者最小化以后再重新打开,之前画过的东西就会消失了,这是很正常的,因为上述操作会引起窗口的重绘,重绘会引起WM_PAINT消息,如果你对这个消息没有响应,那么自然显示出来的就是一个崭新的窗口了。如果你想在窗口重绘后来能保留原来的结果,那么必须要在这个消息的响应函数中重新写出之前的内容。
CString str("啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊"); pDC->TextOut(50,50,str);CString 对象还可以通过LoadString装载字符串资源,字符串资源也在资源视图中。
str.LoadString(IDS_STRINGTEXT); pDC->TextOut(50,50,str);
CSize sz = pDC->GetTextExtent(str); pDC->BeginPath(); pDC->Rectangle(50,50,50+sz.cx,50+sz.cy); pDC->EndPath();如果将BeginPath和EndPath注释起来,就会出现一个矩形框挡住文字的情况。
// pDC->SelectClipPath(RGN_DIFF); for(int i = 0; i < 300; i+= 10) { pDC->MoveTo(0,i); pDC->LineTo(300,i); pDC->MoveTo(i,0); pDC->LineTo(i,300); }我们画了一个网格。程序运行时,文字和网格混合在一起,但是如果打开注释,网格就在有文字的区域断开了。
CCH_5_TEXTView::CCH_5_TEXTView() { // TODO: add construction code here m_strLine = ""; }在响应WM_LBUTTONDOWN消息中使用SetCaretPos函数来设置插入光标的位置,并且清空字符串:
void CCH_5_TEXTView::OnLButtonDown(UINT nFlags, CPoint point) { // TODO: Add your message handler code here and/or call default SetCaretPos(point); m_strLine.Empty(); CView::OnLButtonDown(nFlags, point); }写到这里,我们突然发现似乎需要保存鼠标单击的位置,这个位置在以后的输出文字中用的上,所以我们有添加了一个CPoint类型的成员变量。
m_ptorigin = (0,0);而在OnLButtonDown函数中用它保存当前点击的位置:
m_ptorigin = point;有了它之后我们就可以开始写对WM_CHAR消息的响应函数了:
void CCH_5_TEXTView::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags) { // TODO: Add your message handler code here and/or call default CClientDC dc(this); //获得系统字体 TEXTMETRIC tm; dc.GetTextMetrics(&tm); //如果是回车 if(0x0d == nChar) { //清空字符串 m_strLine.Empty(); //换行 m_ptorigin.y += tm.tmHeight; } //如果是退格 else if(0x08 == nChar) { //将颜色变为背景色,并将原来的的颜色保存在clr中 COLORREF clr = dc.SetTextColor(dc.GetBkColor()); //用背景色输出文字 dc.TextOut(m_ptorigin.x,m_ptorigin.y,m_strLine); //删除最后那个字符:取源字符串的前m_strLine.GetLength() - 1个字符 m_strLine = m_strLine.Left(m_strLine.GetLength() - 1); //将颜色改回来 dc.SetTextColor(clr); } else { m_strLine += nChar; } //调整插入符位置 CSize sz = dc.GetTextExtent(m_strLine); CPoint pt; pt.x = m_ptorigin.x + sz.cx; pt.y = m_ptorigin.y ; SetCaretPos(pt); //输出内容 dc.TextOut(m_ptorigin.x,m_ptorigin.y,m_strLine); CView::OnChar(nChar, nRepCnt, nFlags); }当然,我们只是“模拟”文本编程,所以很多问题都是没有考虑的。假如想建立更好的文档处理程序,可以从CEditView或者CRichEditView派生出来。
CFont font; font.CreatePointFont(123,"华文行楷",NULL); CFont *pOldFont = dc.SelectObject(&font);使用完成后,把字体再改回来:
dc.SelectObject(pOldFont);2.让文字字逐渐的显示出来
SetTimer(1,100,NULL);添加一个int型成员变量:m_nWidth,并在构造函数中初始化为0。
void CCH_5_TEXTView::OnTimer(UINT nIDEvent) { // TODO: Add your message handler code here and/or call default //始终到来时宽度增加5 m_nWidth += 5; CClientDC dc(this); TEXTMETRIC tm; dc.GetTextMetrics(&tm); //设置矩形框的大小 CRect rect; rect.left = 0; rect.top = 200; rect.right = m_nWidth; rect.bottom = rect.top + tm.tmHeight; dc.SetTextColor(RGB(255,0,0)); CString str = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; dc.DrawText(str,rect,DT_LEFT ); CView::OnTimer(nIDEvent); }rawText还可以选择从右边开始输出,可以将模式设为DT_RIGHT。但是这会出一个问题,就是字母全部输出以后,会输出一些垃圾值,我们可以设定:如果矩形的长度大于字符串长度,把宽度设为0,把把字符串重新输出为背景色,再重新从开始的位置输出字符串。
CSize sz = dc.GetTextExtent(str); if(m_nWidth >= sz.cx) { m_nWidth = 0; dc.SetTextColor(dc.GetBkColor()); dc.TextOut(0,200,str); }