关于在文档输入时准确的将插入符设置在两个文字中间
1、通过m_ptWriteCaret的坐标判断是否输入了文字
if(m_ptWriteCaret.x==0&&m_ptWriteCaret.y==0)
pt=CPoint(0,0);
若未输入文字,直接将插入符设置在(0,0)处;
2、判断鼠标点击的纵坐标位置是否超过了文字输入的位置
else
{
//光标位置超过了输入字符的情况
if(point.y>(m_ptWriteCaret.y+tm.tmHeight))
pt=m_ptWriteCaret;//将字符创放在输入文字的末尾;
3、获取字体的信息
CDC *dc;
dc=GetDC();
TEXTMETRIC tm;
dc->GetTextMetrics(&tm);//获取字体信息
4、利用字体的信息利用point.y除以字体高得到应处于哪一行,point.x除以自体的平均宽度判断处于那一列,从而得到插入符的大约位置;(注意这里只是个大约的位置,只是判断在哪个字之间插入,并不是要确定具体的坐标)
//光标位置超过了输入字符的情况
if(point.y>(m_ptWriteCaret.y+tm.tmHeight))
pt=m_ptWriteCaret;//将字符创放在输入文字的末尾;
//插入符纵坐标在输入纵坐标之内
else
{
iHeight=point.y/tm.tmHeight;//判断插入符在第几行;
strLine=m_strAarray.GetAt(iHeight);//从集合类中获取改行字符串;
CSize sz=dc->GetTextExtent(strLine);//获取改行字符串的长度
iNum=point.x/tm.tmAveCharWidth; //获取改行字符串的第几个位置插入
//在每行已输入字里
if(point.x<sz.cx)
{
//点击首行的情况
if(iHeight==0)
{
//首行首列(第一个字母)
if(iNum==0)
ptPoint.x=0;
//首行其他列时
else
ptPoint.x=(dc->GetTextExtent(strLine.Left(iNum))).cx;//插入符的横坐标;
ptPoint.y=0;
pt=ptPoint;
}
//非首行时
else
{
//首列的情况
if(iNum==0)
ptPoint.x=0;
else
{
ptPoint.x=(dc->GetTextExtent(strLine.Left(iNum))).cx;//插入符的横坐标;
}
ptPoint.y=iHeight*tm.tmHeight;
pt=ptPoint;
}
}
//在每行横坐标已输入文字外
else
{
ptPoint.y=iHeight*tm.tmHeight;
ptPoint.x=sz.cx;
pt=ptPoint;
}
4、因为自体的高度是tmHeight的位置是一定的,因此得到的结果能准确的判定插入符在第几行,但由于用于判断横坐标是用的是自体的平均宽度(tmAveWidth)因此若以其作为横坐标就会出现插入符在原有自体上显示的问题。因此,我们利用就近的原则,得到它在哪两个字之间,再获取左右两边的字符串的距离(GetTextExtent)获取准确的插入符横坐标位置。
CString strLeft;//光标左边的字符
strLeft=strLine.Left(iNum);
dc->TextOutA(0,pt.y,strLeft);//输出光标左边的字符
CString strRight;
strRight=strLine.Right(strLine.GetLength()-iNum);//获取光标右边的字符;
dc->TextOut(dc->GetTextExtent(strLine.Left(iNum)).cx,pt.y,strRight);
}
//保存插入符的实时位置
m_ptCaret=pt;
SetCaretPos(pt);
上述的方式避免了,将插入符显示在字符上的问题。