關於在文檔輸入時準確的將插入符設置在兩個文字中間
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);
上述的方式避免了,將插入符顯示在字符上的問題。