如果我们的程序中有个CEikRichTextEditor或者是 CEikEdwin,而且不用控件本身的滚动条来控制文本的滚动的话,我们就需要了解下下面的内容。
CTextLayout的这个API-FindDocPos- 可以把控件中文本的位置信息转换为 控件的可视位置的坐标信息,就是以控件的top-left point为坐标的原点,所以如果文本的数目超过了控件的可视范围那么自动向上翻动的文本头转换为位置信息时Y点的坐标就是负的。
IMPORT_C TBool FindDocPos(const TTmDocPosSpec &aDocPos, TTmPosInfo2 &aPosInfo, TTmLineInfo *aLineInfo=0) const;
第一个参数 TTmDocPosSpec 要 转换的文本在控件中的信息,通常是开始和结尾,定义如下,
TTmDocPos startPos(0, EFalse); // start point
TTmDocPos endPos(aEditor->RichText()->DocumentLength(), EFalse); // end point
NOTE: 一般我们使用TTmDocPos来替 代 TTmDocPosSpec
第二个参数TTmPosInfo2 这 里用不着,具体用途参考SDK的description
第三个参数TTmLineInfo 返 回了比较多的信息比如:linenumber,innerrect,outerrect等等,这里我们使用iOuterRect
startPosY = lineInfo.iOuterRect.iTl.iY;
endPosY = lineInfo.iOuterRect.iTl.iY;
这里的lineInfo分别是传入startPos和endPos到FindDocPos 里 后获得的信息,endPosY -startPosY 就可以得到文本中Y坐标值,这个值是像素值 。
FindDocPos 的返回值表明text是否是经过format 的如果没有那么就返回EFalse,我们应该要检测这个值,如果当前的text没有format过可以通过下面的方式来进行。
aEditor->TextLayout()->SetAmountToFormat(CTextLayout::EFFormatAllText );
aEditor->TextView()->FormatTextL();
关于这两个API的细节请参考SDK,这里可见CTextLayout 和CTextView 是 很重要的处理 CEikEdwin中文字信息的类,还有个CRichText 也很重要!
NOTE: 对于FindDocPos 的 返回值,如果我们需要取得多个信息时,需要嵌套检测。因为 aEditor->TextLayout()->SetAmountToFormat()这个函数默认的格式化方式是格式化可见的部分,如果 不可见的部分没有格式化是获取不了信息的,为了防止这种情况的发生,我们一般是嵌套检测,而且一般是用 CTextLayout::EFFormatAllText 来格式化文本,当然这会造成aEditor->TextView()->FormatTextL()的time-consmuing,所以我 们call it if necessary,这一点SDK描述的很清楚。
我们可以通过这些API获得很多其他的信息,比如总行数,某个位置的行数,可视部分行数,某点的RECT等等,
获取总行数:
// two ways to get the total count of text, it should be same
TInt textLength = aEditor->TextLength();
TInt docLength = aEditor->RichText()->DocumentLength();
if (aEditor->TextLayout()->PosIsFormatted(docLength))
{
aEditor->TextLayout()->FindDocPos(pos,posInfo,&lineInfo);
lineNum = lineInfo.iLineNumber;
} else {
aEditor->TextView()->FormatTextL();
aEditor->TextView()->FinishBackgroundFormattingL();
if (aEditor->TextLayout()->PosIsFormatted(docLength))
{
aEditor->TextLayout()->FindDocPos(pos,posInfo,&lineInfo);
lineNum = lineInfo.iLineNumber;
} else {
lineNum = aEditor->TextLayout()->NumFormattedLines();
}
}
某个位置的行数:
aEditor->TextLayout()->GetLineNumber(aDocPos); // get the line number of aDocPos
某点的RECT:
aEditor->TextLayout()->GetLineRectL(pos,pos );
可视部分行数:
const TRect viewRect = aEditor->TextView()->ViewRect(); // visiable rect
TPoint posTl(rect.iTl);
TPoint posBr(rect.iBr);
aEditor->TextLayout()->FindXyPos(posTl,posInfo,&lineInfo)
TInt firstLineNumInBand = lineInfo.iLineNumber;
aEditor->TextLayout()->FindXyPos(posBr,posInfo,&lineInfo)
TInt lastLineNumInBand = lineInfo.iLineNumber;
lineNum = lastLineNumInBand - firstLineNumInBand;
这里的FindXyPos函数同样要做是否format的检测。
另外 如果控件中文本的行数超过了控件的显示范围,在控制文本滚动的时候就可 以利用以下的方法:
TInt firstLineInBand = aEditor->TextLayout()->FirstLineInBand (); 获得控件当前的可视范围中显示的第一个完全显示行的行数,行数以0开始计数的。
aEditor->TextView()->SetViewLineAtTopL (firstLineInBand); 垂直移动当前控件的显示区域,行数是相对于格式化文本来的,行数的计数是从1开始的。所以如果把上面的两行结合起来就是完成了一次向上滚动的动作。
附:S60 FP2 SDK
class TTmLineInfo
{
public:
// bit values for iFlags
enum
{
EParStart = 1,
EParEnd = 2,
EParRightToLeft = 4,
ELineEndsInForcedLineBreak = 8
};
inline TTmLineInfo();
/** Outer enclosing rectangle including margins */
TRect iOuterRect;
/** Inner enclosing rectangle: the text only */
TRect iInnerRect;
/** y coordinate of the baseline */
TInt iBaseline;
/** Start document position */
TInt iStart;
/** End document position */
TInt iEnd;
/** Line number */
TInt iLineNumber;
/** Paragraph number */
TInt iParNumber;
/** Line number in the paragraph */
TInt iLineInPar;
/** y coordinate of the top of the paragraph */
TInt iParTop;
/** Start of paragraph, end of paragraph, etc. */
TUint iFlags;
};
U CAN GET MORE INFORMATION!!