Symbian中大段文本顯示控制項,使用系統捲軸,可自動換行

來源:互聯網
上載者:User

有些時候我們想顯示一個大段的常值內容,但是我們去找不到合適的控制項。或者覺得系統控制項太單調,無法滿足需求是,我們需要自訂控制項,來實現我們自己想要的效果。我這個自訂控制項實現了,文本的自動換行,添加了系統的捲軸和一些簡單的文本顯示,

 

廢話不多說了,直接貼出代碼吧!!

 

.h檔案

/*
============================================================================
 Name        : TextDisplay.h
 Author      : Barrett
 Version     :
 Copyright   : Your copyright notice
 Description : CTextDisplay declaration
============================================================================
*/

#ifndef TEXTDISPLAY_H
#define TEXTDISPLAY_H

// INCLUDES
#include <COECNTRL.H> //Link against:cone.lib
#include <fbs.h>//Link against:fbscli.lib
#include <gulicon.h>
#include <aknutils.h>
#include <avkon.hrh>
// CLASS DECLARATION

/**
*  CTextDisplay
*
*/
class CTextDisplay : public CCoeControl
{
public: // Constructors and destructor

 /**
        * Destructor.
        */
 ~CTextDisplay();

        /**
        * Two-phased constructor.
        */
 static CTextDisplay* NewL(const TRect &aRect,CCoeControl* aParent);

        /**
        * Two-phased constructor.
        */
 static CTextDisplay* NewLC(const TRect &aRect,CCoeControl* aParent);
 TKeyResponse OfferKeyEventL(const TKeyEvent &aKeyEvent, TEventCode aType);

private:

 /**
        * Constructor for performing 1st stage construction
        */
 CTextDisplay();

 void Draw( const TRect& aRect ) const;

 /**
        * EPOC default constructor for performing 2nd stage construction
        */
 void ConstructL(const TRect &aRect,CCoeControl* aParent);
private:
 // display content
 RPointerArray<HBufC> *iDisplayContent;
 // 起始位置為第幾行
 TInt iStartLine;
 //字型顏色
 TRgb iFontColour;
 //文字總行數
 TInt iTotalLine;
 //文字顯示地區
 TRect iRect;
 //文字字型
 CFont *iFont;
 //捲軸寬度
 TInt iScrollBarWidth;
 //控制項背景色
 TRgb iBackGround;
 //文字顯示開始位置
 TPoint iStartPoit;
 //每行文字間的間距
 TInt iLineToLineSpace;
 //一螢幕顯示的最大行數
 TInt iMaxDisplayLine;

 CCoeControl *iParent;

 //系統捲軸
 CEikScrollBarFrame* iSBFrame;
 TEikScrollBarModel iModel;

 //建立系統捲軸
 void CreateScrollBars(TInt aCunt);
public:
 //計算文字中行數
 void AccountTotalLine();
 //計算一螢幕顯示的最大行數
 TInt GetMaxDisplay();
 void SetScrollBarWidth(TInt aWidth);
 //設定背景顏色
 void SetBackground(TRgb aRgb);
 //設定顯示的文字
 void SetDisplayContent(const TDesC& aContent,TBool aUseFlag = EFalse);
 //設定文字顯示字型
 void SetFont(CFont *aFont);
 //設定文字顯示顏色
 void SetFontColour(TRgb aRgb);
 
};

#endif // TEXTDISPLAY_H

 

 

.cpp檔案

/*
============================================================================
 Name        : TextDisplay.cpp
 Author      : Barrett
 Version     :
 Copyright   : Your copyright notice
 Description : CTextDisplay implementation
============================================================================
*/

#include "TextDisplay.h"
//#include "AuditionContainer.h"

_LIT(KLineStart,"<Line>");
_LIT(KLineEnd,"</Line>");
#define MAXDISPLAYLINE 10
#define LINESPACE 3
#define LASTSPACE 25

CTextDisplay::CTextDisplay()
{
 // No implementation required
// iBackGroundBitmap = NULL;
 iStartLine = 0;
 iTotalLine = 0;
 iFontColour = KRgbBlack; // default
 iStartPoit = TPoint(3,5);
 iLineToLineSpace = LINESPACE;
 iScrollBarWidth = 10;
}

CTextDisplay::~CTextDisplay()
{

 if (iDisplayContent)
 {
  iDisplayContent->ResetAndDestroy();
  delete iDisplayContent;
  iDisplayContent = NULL;
 }
 if(iSBFrame)
 {
  delete iSBFrame;
  iSBFrame = NULL;
 }
}

CTextDisplay* CTextDisplay::NewLC(const TRect &aRect,CCoeControl* aParent)
{
 CTextDisplay* self = new (ELeave)CTextDisplay();
 CleanupStack::PushL(self);
 self->ConstructL(aRect,aParent);
 return self;
}

CTextDisplay* CTextDisplay::NewL(const TRect &aRect,CCoeControl* aParent)
{
 CTextDisplay* self=CTextDisplay::NewLC(aRect,aParent);
 CleanupStack::Pop(); // self;
 return self;
}

void CTextDisplay::ConstructL(const TRect &aRect,CCoeControl* aParent)
{
// SetRect(aRect);
 iRect = aRect;

 TFontSpec fontSpec = iEikonEnv->DenseFont()->FontSpecInTwips();
 fontSpec.iHeight *= 1;
 iCoeEnv->ScreenDevice()->GetNearestFontInTwips(iFont,fontSpec);
 iMaxDisplayLine = GetMaxDisplay();
 iParent = aParent;
 
}

TKeyResponse CTextDisplay::OfferKeyEventL(const TKeyEvent &aKeyEvent, TEventCode aType)
{
 if((aType == EEventKeyDown) && (aKeyEvent.iScanCode == EStdKeyDownArrow))
 {
  if(iTotalLine >= iStartLine+iMaxDisplayLine)
  {
   ++iStartLine;
  }
 }
 else if((aType == EEventKeyDown) && (aKeyEvent.iScanCode == EStdKeyUpArrow))
 {
  if(iStartLine > 0)
  {
   --iStartLine;
  }
 }
 iSBFrame->MoveVertThumbTo(iStartLine);//絕對座標
 iSBFrame->DrawScrollBarsNow();
 DrawNow();
 return EKeyWasConsumed;
}

void CTextDisplay::SetDisplayContent(const TDesC& aContent,TBool aUseFlag)
{
 if(aContent.Length() == 0)
 {
  return ;
 }
 if (iDisplayContent)
 {
  iDisplayContent->ResetAndDestroy();
  delete iDisplayContent;
  iDisplayContent = NULL;
 }

 iDisplayContent = new RPointerArray<HBufC>;

 HBufC *CopyText = aContent.Alloc();
 
 if(aUseFlag)
 {
  TBuf<6> bufBeginTag(KLineStart);
  TBuf<7> bufEndTag(KLineEnd);
  
  while(CopyText->Length())
  {
   TInt posBegin = CopyText->Find(bufBeginTag)+bufBeginTag.Length();
   TInt posEnd = CopyText->Find(bufEndTag);
   if(posBegin!=KErrNotFound&&posEnd!=KErrNotFound)
   {
    TPtrC ptrPerson = CopyText->Mid(posBegin,posEnd-posBegin);
    HBufC *HText = ptrPerson.Alloc();
    iDisplayContent->Append(HText);
    if(CopyText->Length() > posEnd+bufEndTag.Length()+1)
    {
     CopyText->Des().Copy(CopyText->Des().Right(CopyText->Length()-posEnd-bufEndTag.Length()));
    }
    else
    {
     break;
    }
   }
  }
  delete CopyText;
 }
 else
 {
  iDisplayContent->Append(CopyText);
 }
 //擷取一螢幕顯示的行數
 //計算文字顯示總行數
 AccountTotalLine();
 CreateScrollBars(iTotalLine-iMaxDisplayLine+2);
}

void CTextDisplay::Draw( const TRect& aRect ) const
{
 CWindowGc& gc = SystemGc();

 gc.SetBrushColor(iBackGround);
 gc.Clear(aRect);
 
 gc.UseFont(iFont);
 gc.SetPenColor(iFontColour);
 //起點
 TPoint point = iStartPoit;
 //記錄上一段的位置
 TPoint Mark = TPoint(0,-(iStartLine*iFont->HeightInPixels()+iLineToLineSpace));
 TPoint point2;
 if(iDisplayContent == NULL)
 {
  gc.DrawText(_L("No content!"),TPoint(aRect.Width()/3,aRect.Height()/3));
  return ;
 }
 for(TInt i=0;i<iDisplayContent->Count();i++)
 {
  TInt nStringMaxDisplayLine = iFont->TextWidthInPixels((*iDisplayContent)[i]->Des())/(iRect.Width() - iScrollBarWidth) + iMaxDisplayLine;

  TBidiText* bidi = TBidiText::NewL((*iDisplayContent)[i]->Des(), nStringMaxDisplayLine);
  bidi->WrapText(iRect.Width()-iScrollBarWidth, *iFont, NULL);
  TInt lines = bidi->NumberOfLinesInDisplayText();
  for(TInt i=0; i<lines; i++)
  {
   point2 = TPoint (point.iX,point.iY+Mark.iY + iFont->HeightInPixels()*(i+1)+iLineToLineSpace*i);
   TInt width = 0;
   TPtrC text = bidi->LineOfDisplayText(i, width);
   gc.DrawText(text, point2);
  }
  Mark = point2;
  delete bidi;
 }
 //畫個小三角
 if(Mark.iY > iRect.Height() - LASTSPACE || iStartLine > 0)
 {
  gc.SetBrushStyle(CGraphicsContext::ESolidBrush);
  gc.SetPenStyle(CGraphicsContext::ENullPen);
  gc.SetBrushColor(KRgbBlue);
  gc.DrawRect(TRect(TPoint(0,iRect.Height()-LASTSPACE),TSize(iRect.Width(),LASTSPACE)));
  gc.SetBrushColor(KRgbBlack);
  TInt nTrigonWidth = 12;         //預設三角寬12個像素
  TInt nTrigonHeight = 12;         //預設三角高12個像素
  //三角形第一的點的橫縱座標
  TInt PointX = aRect.Width()/2;
  TInt PointY = aRect.Height()  - LASTSPACE + (LASTSPACE- 2*nTrigonHeight - 1)/2;
  if(iTotalLine >= iStartLine + iMaxDisplayLine && iTotalLine > iMaxDisplayLine)
  {
   CArrayFixFlat<TPoint>* ArrPoint = new (ELeave) CArrayFixFlat<TPoint>(10);
   ArrPoint->AppendL(TPoint(PointX-nTrigonWidth/2,PointY + 1 + nTrigonHeight)); // +1表示 兩個三角的間距
   ArrPoint->AppendL(TPoint(PointX+nTrigonWidth/2,PointY + 1 + nTrigonHeight)); // +1表示 兩個三角的間距
   ArrPoint->AppendL(TPoint(PointX,PointY+2*nTrigonHeight));
   gc.DrawPolygon(ArrPoint);
   delete ArrPoint;
  }
  if(iStartLine > 0)
  {
   CArrayFixFlat<TPoint>* ArrPoint = new (ELeave) CArrayFixFlat<TPoint>(10);
   ArrPoint->AppendL(TPoint(PointX,PointY));
   ArrPoint->AppendL(TPoint(PointX-nTrigonWidth/2,PointY+nTrigonHeight));
   ArrPoint->AppendL(TPoint(PointX+nTrigonWidth/2,PointY+nTrigonHeight));
   gc.DrawPolygon(ArrPoint);
   delete ArrPoint;
  }
  gc.SetBrushStyle(CGraphicsContext::ENullBrush);
 }

}
void CTextDisplay::SetFontColour(TRgb aRgb)
{
 iFontColour = aRgb;
}

void CTextDisplay::SetFont(CFont *aFont)
{
 iFont = aFont;
 iMaxDisplayLine = GetMaxDisplay();
}

void CTextDisplay::SetBackground(TRgb aRgb)
{
 iBackGround = aRgb;
}

void CTextDisplay::AccountTotalLine()
{
 for(TInt i=0;i<iDisplayContent->Count();i++)
 {
  TInt nStringMaxDisplayLine = iFont->TextWidthInPixels((*iDisplayContent)[i]->Des())/(iRect.Width() - iScrollBarWidth) + iMaxDisplayLine;
  TBidiText* bidi = TBidiText::NewL((*iDisplayContent)[i]->Des(), nStringMaxDisplayLine);
  bidi->WrapText(iRect.Width()-iScrollBarWidth, *iFont, NULL);
  TInt lines = bidi->NumberOfLinesInDisplayText();
  iTotalLine += lines;
  delete bidi;
 }
}

TInt CTextDisplay::GetMaxDisplay()
{
 return (iRect.Height() - LASTSPACE - iStartPoit.iY)/(iFont->HeightInPixels() + iLineToLineSpace);
}

void CTextDisplay::SetScrollBarWidth(TInt aWidth)
{
 iScrollBarWidth = aWidth;
}

//建立系統捲軸
void CTextDisplay::CreateScrollBars(TInt aCunt)
{
 //構造
 iSBFrame=new(ELeave) CEikScrollBarFrame(iParent, NULL,ETrue);
 iSBFrame->CreateDoubleSpanScrollBarsL(ETrue, EFalse,ETrue,ETrue);
 iSBFrame->SetTypeOfVScrollBar(CEikScrollBarFrame::EDoubleSpan);
 iSBFrame->SetScrollBarVisibilityL(CEikScrollBarFrame::EOff,
  CEikScrollBarFrame::EAuto);
 

 iModel = TEikScrollBarModel(aCunt, 1, 0);
 //設定地區
 TRect aRect;
 aRect = TRect(TPoint(iRect.Width()-iScrollBarWidth,iRect.iTl.iY),TSize(iScrollBarWidth,iRect.Height()-LASTSPACE));
 iSBFrame->Tile(&iModel,aRect);
 //設定初始位置-絕對座標
 iSBFrame->MoveVertThumbTo(0);
 iSBFrame->DrawScrollBarsNow();
}
// End of File 

 

在container中的使用

第一步:在container中定義一個成員

 CTextDisplay *iTextDisplay;

第二步:在constructl中初始化

代碼如下: //這裡是為了方便直接從檔案中讀出一段文本

_LIT(KAbout,"C://about.ini");
 
 RFs fs = CEikonEnv::Static()->FsSession();
 RFile fp;
 TInt err = fp.Open(fs,KAbout,EFileRead);
 if(err == 0)
 {
  TInt nFileSize = 0;
  fp.Size(nFileSize);
  HBufC8* fileInfo = HBufC8::NewLC(nFileSize);
  TPtr8 file = fileInfo->Des();
  fp.Read(file, nFileSize);
  HBufC* fileInfo16 = HBufC::NewLC(file.Length());
  TPtr16 ptr = fileInfo16->Des();

  /*ptr.Copy(file);*/
  ConvGbk2Uni(file, ptr);
 
  iTextDisplay = CTextDisplay::NewL(aRect,this);
  iTextDisplay->SetDisplayContent(fileInfo16->Des());
  iTextDisplay->SetContainerWindowL(*this);
  iTextDisplay->SetExtent(TPoint(0,0), TSize(240, 320));
  CleanupStack::PopAndDestroy(2);
 }
 fp.Close();

 

在一段代碼寫在ActivateL函數之前,原因我就不說了。ConvGbk2Uni函數的代碼我也貼出來。如下:

 

void ConvGbk2Uni(TDesC8& original, TDes& res)       //這個函數不是我寫的,從網上搜的
{
 //RFs aFileServerSession = CEikonEnv::Static()->FsSession();
 RFs aFileServerSession;
 aFileServerSession.Connect();
 // CleanupStack::Pop();
 CCnvCharacterSetConverter* converter=CCnvCharacterSetConverter::NewLC();

 if(converter->PrepareToConvertToOrFromL(KCharacterSetIdentifierGbk,aFileServerSession)!=CCnvCharacterSetConverter::EAvailable)
  User::Leave(KErrNotSupported);

 TInt state=CCnvCharacterSetConverter::KStateDefault;

 TPtrC8 str( original );
 HBufC* iInfoText = HBufC::NewL( str.Length() );

 TPtr16 ptr = iInfoText->Des();

 if(CCnvCharacterSetConverter::EErrorIllFormedInput == converter->ConvertToUnicode(ptr, str, state))
  User::Leave(KErrArgument);

 res.Zero() ;
 res.Copy(ptr) ;
 aFileServerSession.Close();
 CleanupStack::PopAndDestroy();
 delete iInfoText;
}

 

第二步:CountComponentControls函數加1,ComponentControl函數返回控制項指標。

第三步:在OfferKeyEventL函數中添加。

    return iTextDisplay->OfferKeyEventL(aKeyEvent,aType);

第四步:在解構函式中寫好析構。

第五步:編譯運行。

 

 

實現過程和使用過程還是比較簡單的,使用過程和使用系統控制項類似。在我這個控制項中我提供了顯示文本的兩者方法。

第一種就是這裡的這種,還有一種就是使用_LIT(KLineStart,"<Line>");
_LIT(KLineEnd,"</Line>");這對標籤的。使用時把

iTextDisplay->SetDisplayContent(fileInfo16->Des());改成

iTextDisplay->SetDisplayContent(fileInfo16->Des(),ETrue);就可以了,這種顯示的內容是<Line>你好嗎</Line><Line>你好嗎</Line>這種文本的。

 

在最後需要注意一個問題,在使用系統捲軸時,它需要視窗,這個視窗可以是共用父類的,也可以是控制項自己定義的。如本文中的

//構造
 iSBFrame=new(ELeave) CEikScrollBarFrame(iParent, NULL,ETrue); iParent就是共用的父類視窗,如果這裡不使用這個而是直接使用this的話,在下一句iSBFrame->CreateDoubleSpanScrollBarsL(ETrue, EFalse,ETrue,ETrue);中會有KERN-EXEC 3的panic,這個是我自己的理解也不知道對不對。希望知道的大嬸,指點下~~

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.