MFC简易文本编辑

程序中用到的一些函数

//创建插入符
void CreateSolidCaret(int nWidth, int nHeight);
nWidth 
	Specifies the width of the caret, in logical units. 
	If this parameter is zero, the width is set to the system-defined window-border width. 
nHeight 
	Specifies the height of the caret, in logical units. 
	If this parameter is zero, the height is set to the system-defined window-border height. 

//定义完成后要调用下面的函数才能使插入符显示出来
void ShowCaret();

//CDC类的GetTextMetrics函数可以得到DC中的当前字体的度量信息
BOOL GetTextMetrics( LPTEXTMETRIC lpMetrics ) const;
Return Value
	Nonzero if the function is successful; otherwise 0.

Parameters
	lpMetrics
		Points to the TEXTMETRIC structure that receives the metrics.
//参数是一个TEXTMETRIC结构体的指针,函数会将DC中的字体度量信息传给这个结构体,这个结构体的内部成员如下
typedef struct tagTEXTMETRIC {  /* tm */
    int  tmHeight;
    int  tmAscent;
    int  tmDescent;
    int  tmInternalLeading;
    int  tmExternalLeading;
    int  tmAveCharWidth;
    int  tmMaxCharWidth;
    int  tmWeight;
    BYTE tmItalic;
    BYTE tmUnderlined;
    BYTE tmStruckOut;
    BYTE tmFirstChar;
    BYTE tmLastChar;
    BYTE tmDefaultChar;
    BYTE tmBreakChar;
    BYTE tmPitchAndFamily;
    BYTE tmCharSet;
    int  tmOverhang;
    int  tmDigitizedAspectX;
    int  tmDigitizedAspectY;
} TEXTMETRIC;

//非常多,根据需要选择就可以,这里是为了设置插入符号的宽度和高度,所以只需要利用
//tmHeight和tmAveCharWidth两个变量就可以,一个是字符高度,一个是平均宽度,
CreateSolidCaret(tm.tmAveCharWidth/5,tm.tmHeight+6);
//大小可以自己调试下

//创建图形插入符
void CreateCaret( CBitmap* pBitmap );
//用一个位图指针作为参数,所以只需载入一个位图,并用该位图作为插入符的图像就可以了
//在程序中要将位图对象作为VIEW类的一个成员变量,不然在执行到OnCreate函数的最后时,
//该变量的生命期就会结束,那么在窗口上就不户显示该图像了

//OnDraw函数相当于WM_PAINT消息响应函数,希望在窗口发生重绘时,文字或图像依然在上面的就可以写在这个函数里

//载入字符串资源,可以在资源的string table中增加新的字符串资源,然后将其ID作为参数 就可以引入该资源了
BOOL LoadString(UINT nID); 

//获取一个字符串在屏幕上显示的宽度和高度
CSize GetTextExtent( const CString& str ) const;
//返回一个CSize结构,该结构有两个变量,一个是宽度,一个是高度

//利用路径层的特点可以实现一些特殊的效果
//在Beginpath()和Endpath()中间加入路径层的区域
//用SelectClipath(int nMode)函数可以指定路径层和DC中已有的裁减区域按一种特定的模式进行一个互操作
//nMode指定互操作模式

//设置插入符的位置
static void PASCAL SetCaretPos( POINT point );
Parameters
	point
		Specifies the new x  and y coordinates (in client coordinates) of the caret.

//设置文本颜色
virtual COLORREF SetTextColor( COLORREF crColor ); 
//函数会返回之前的文本颜色

CString Left(int nCount) const;
//返回从左边开始CString 的nCount个字符,从1开始算

//设置字体
BOOL CreatePointFont(int nPointSize,LPCTSTR lpszFaceName,CSC *pDC=NULL);
nPointSize
	Requested font height in tenths of a point. (For instance, pass 120 to request a 12-point font.)

lpszFaceName
	字体名字
pDC
	Pointer to the CDC object to be used to convert the height in nPointSize to logical units. 
	If NULL, a screen device context is used for the conversion.


//在指定矩形区域内输出字体
int DrawText( const CString& str, LPRECT lpRect, UINT nFormat );
//当输出字数超过矩形范围时,只显示能够显示的那部分文字

下面的程序实现了在插入符的位置进行输出文字并且可以响应回车和退格 实现字体平滑变色

下面是部分代码

CTextView::CTextView()
{
	// TODO: add construction code here
	m_strLine="";//保存当前输入的字符串
	m_ptOrigin=0;//保存鼠标当前位置
	m_nWidth=0;//宽度
}

void CTextView::OnDraw(CDC* pDC)
{
	CTextDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	// TODO: add draw code for native data here
	CString str="VC++ 深入详解";
	//与SDK的Textout函数的区别是不需要传递DC句柄作为参数,因为CDC类内部有个成员变量m_hDC保存了DC句柄
	pDC->TextOut(50,100,str);

	CSize sz=pDC->GetTextExtent(str);
	//加载字符串资源
	str.LoadString(IDS_STRINGVC);

	pDC->TextOut(0,200,str);

	//路径层,在beginpath和endpath之间绘制

	pDC->BeginPath();
	pDC->Rectangle(50,100,50+sz.cx,100+sz.cy);
	pDC->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);
	}
}

int CTextView::OnCreate(LPCREATESTRUCT lpCreateStruct) 
{
	if (CView::OnCreate(lpCreateStruct) == -1)
		return -1;
	
	// TODO: Add your specialized creation code here
	CClientDC dc(this);
	TEXTMETRIC tm;
	//获取DC中当前字体的度量信息
	dc.GetTextMetrics(&tm);
	CreateSolidCaret(tm.tmAveCharWidth/5,tm.tmHeight+6);

/*	//初始化的插入符是隐藏的
	bitmap.LoadBitmap(IDB_BITMAP1);
	//创建图形插入符
	CreateCaret(&bitmap);
*/
	ShowCaret();

	SetTimer(1,100,NULL);//定时器,100ms发生一次信息
	return 0;
}

void CTextView::OnLButtonDown(UINT nFlags, CPoint point) 
{
	// TODO: Add your message handler code here and/or call default
	
	//设置插入符的位置,放在这个详细处理函数里用来使它一直跟随鼠标单击时的位置
	SetCaretPos(point);
	
	//鼠标到了一个新地方时,要将之前m_strLine的内容清空,从这个开始重新输出
	m_strLine.Empty();
	
	//记录鼠标单击时的位置,便于输出时候定位
	m_ptOrigin=point;

	CView::OnLButtonDown(nFlags, point);
}

void CTextView::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags) 
{
	// TODO: Add your message handler code here and/or call default
	CClientDC dc(this);
	CFont font;
	font.CreatePointFont(120,"新宋体",NULL);
	CFont *fOldFont=dc.SelectObject(&font);
	TEXTMETRIC tm;
	dc.GetTextMetrics(&tm);
	//回车符的ASCII码值为0x0d,退格符号的ASCII码值为0x08
	if(nChar==0x0d)
	{
		//按下回车的时候,现存的字符要清空,然后光标位置下移,横坐标不变
		m_strLine.Empty();
		m_ptOrigin.y+=tm.tmHeight;
	}
	else if(nChar==0x08)
	{
		//SetTextColor函数会返回更改前的字体颜色
		COLORREF clr=dc.SetTextColor(dc.GetBkColor());
		dc.TextOut(m_ptOrigin.x,m_ptOrigin.y,m_strLine);
		m_strLine=m_strLine.Left(m_strLine.GetLength()-1);
		dc.SetTextColor(clr);
	}
	else
		m_strLine+=nChar;
	
	//使插入符跟随输出的字符串
	CSize cs=dc.GetTextExtent(m_strLine);
	CPoint pt;
	pt.x=m_ptOrigin.x+cs.cx;
	pt.y=m_ptOrigin.y;
	SetCaretPos(pt);

	dc.TextOut(m_ptOrigin.x,m_ptOrigin.y,m_strLine);
	dc.SelectObject(fOldFont);

	CView::OnChar(nChar, nRepCnt, nFlags);
}

void CTextView::OnTimer(UINT nIDEvent) 
{
	// TODO: Add your message handler code here and/or call default
	
	//通过定时器,每次使得DrawText的矩形宽度增加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,90));
	
	CString str;
	str.LoadString(IDS_STRINGVC);

	dc.DrawText(str,rect,DT_LEFT);


	CSize cs=dc.GetTextExtent(str);
	if(m_nWidth>cs.cx)//当宽度达到文字的总宽度时,将文字变为绿色 
	{
		m_nWidth=0;
		dc.SetTextColor(RGB(0,255,0));
		dc.TextOut(0,200,str);
	}
	

	CView::OnTimer(nIDEvent);
}


 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值