Join Now
Quality Rating:
  • Currently 1.0 / 5
(1.0 / 5 - 1 vote cast)
Expertise Level:
  • Currently 1.0 / 5
(1.0 / 5 - 1 vote cast)

This page was last modified 12:05, 8 December 2007.

How to insert an image into a skin aware CEikRichTextEditor

From Forum Nokia Wiki

Nokia published in 2006 an example code (S60 Platform: Rich Text Editor Example v2.0) demonstrating how to insert an image into CEikRichTextEditor. However, the published solution is not skin aware: if the CEikRichTextEditor control is made skin aware the inserted pictures are drawn on white background.

The following code demonstrates how pictures can be made skin aware.


How does the solution work?

Images are inserted into the rich text control contents as CRTxPicture objects:

void
CRTx::InsertPictureL(
    MRTxBackgroundDrawer & aControl,
    TInt                   aPos,
    CFbsBitmap           & aBitmap,
    CFbsBitmap           & aBitmapMask)
{
    CRTxPicture* picture;
    
    picture = new(ELeave) CRTxPicture(
        iTextBox->GetSystemGc(), aControl, aBitmap, aBitmapMask);
    
    CleanupStack::PushL(picture);
    TPictureHeader header;
    header.iPicture = TSwizzle<CPicture>(picture);
    
    iTextBox->RichText()->InsertL(aPos, header);
    
    CleanupStack::Pop(); 
}

CRTxPicture is derived from CPicture and implementes Draw method in a way first the skin background is drawn, second the picture itself is drawn:

void
CRTxPicture::Draw(
    CGraphicsContext   & aGc,
    const TPoint       & aTopLeft,
    const TRect        & aClipRect,
    MGraphicsDeviceMap * aMap) const
{
    CBitmapContext& gc = static_cast<CBitmapContext &>(aGc);
    TRect bmpPieceRect(TPoint(0,0),iBitmap->SizeInPixels());
    
    // here is the skin background drawn
    iControl.RTxDrawBackground(aTopLeft, bmpPieceRect, gc);
 
    // then the picture itself
    gc.BitBltMasked(aTopLeft, iBitmap, bmpPieceRect, iBitmapMask, ETrue);
}

The skin background is actually drawn in the container. For this reason the container must implement the MRTxBackgroundDrawer class.

class MRTxBackgroundDrawer
{
public:
    virtual void
    RTxDrawBackground(
        const TPoint   & aDstPos,
        const TRect    & aRect,
        CBitmapContext & gc) = 0;
};
class CMyAppContainer : public CCoeControl, public MRTxBackgroundDrawer
void
CMyAppContainer::RTxDrawBackground(
    const TPoint   & aDstPos,
    const TRect    & aRect,
    CBitmapContext & gc)
{
#ifdef USE_SKIN
    MAknsSkinInstance   * skin = AknsUtils::SkinInstance();
    MAknsControlContext * cc    AknsDrawUtils::ControlContext(this);
 
    AknsDrawUtils::DrawBackground(
        skin, cc, this, gc, TPoint(0, 0), aRect, KAknsDrawParamDefault);
#else
    gc.SetPenStyle(CGraphicsContext::ENullPen);
    gc.SetBrushColor(KRgbBlue);
    gc.SetBrushStyle(CGraphicsContext::ESolidBrush);
    gc.DrawRect(aRect);
#endif
}



Notes

Add
MACRO USE_SKIN
to the .mmp file.



Source code

The code consists of the following files:

  • MyAppContainer.cpp - a part of the container implementation showing how to use CRTx
  • RTxBackgroundDrawer.h - an abstract class used for drawing skin background from CRTxPicture
  • RTxPicture.h, RTxPicture.cpp - a class for handling pictures in rich text editor
  • RTx.h, RTx.cpp - a helper class for easy handling rich text editor
///////////////////////////////
// MyAppContainer.cpp (parts)
///////////////////////////////
 
#include <eikclbd.h>
#include <akniconarray.h>
#include <gulicon.h>
#include <AknIconUtils.h>
#include "RTx.h"
#include <MyAppmif.mbg>
#include "MyAppDocument.h"
#include "MyAppViewDevices.h"
#include "MyAppContainer.h"
 
#ifdef USE_SKIN
#include <AknsDrawUtils.h>
#include <AknsBasicBackgroundControlContext.h>
#endif
 
#define LKMyAppMIF L"\\resource\\apps\\myapp.mif"
 
CMyAppContainer::CMyAppContainer(CMyAppViewDevices* aView) : iView(aView)
{
}
 
CMyAppContainer::~CMyAppContainer()
{
    delete iRTx;
    delete iTextBox;
    for(int i = 0; i < iBitmap->Count(); i++)
        delete iBitmap->At(i);
    delete iBitmap;
    for(int i = 0; i < iBitmapMask->Count(); i++)
        delete iBitmapMask->At(i);
    delete iBitmapMask;
#ifdef USE_SKIN
    delete iBackGround;
#endif
}
 
void CMyAppContainer::LoadBitmapListL()
{
    _LIT(KMyAppMif, KMyAppMIF);
    PrepareBitmapL(KMyAppMif, EMbmMyAppmifImage, EMbmMyAppmifImage_mask); // the image (bitmap or svg)
}
 
void CMyAppContainer::AddSomeTextAndImageL()
{
    _LIT(KText1, "Hello World!");
 
    iRTx->AddTextL(KText1);
    iRTx->AddCarriageReturnL();
    iRTx->AddPictureL(*this, *(iBitmap->At(0)), *(iBitmapMask->At(0)));
}
 
void CMyAppContainer::ConstructL(const TRect& aRect)
{
    CreateWindowL();
 
    iBitmap = new (ELeave) CArrayFixFlat<CFbsBitmap *>(1);
    iBitmapMask = new (ELeave) CArrayFixFlat<CFbsBitmap *>(1);
 
    LoadBitmapListL();
 
    iTextBox = new (ELeave) CRTxEditor(TGulBorder::ENone);
    iTextBox->SetMopParent(this);
    iRTx = new (ELeave) CRTx(iTextBox);
 
    TInt edwinFlags = EEikEdwinInclusiveSizeFixed|EEikEdwinNoAutoSelection|EEikEdwinDisplayOnly|EEikEdwinReadOnly|
        EEikEdwinLineCursor|EEikEdwinNoHorizScrolling|EEikEdwinAvkonDisableCursor;
 
    iTextBox->ConstructL(this, 0, 0, edwinFlags,EGulFontControlAll, EGulAllFonts);
    iTextBox->SetAknEditorFlags(edwinFlags);
 
    iTextBox->SetContainerWindowL(*this);
    iTextBox->SetFocus(ETrue);
 
    AddSomeTextAndImageL(); 
    
    SetRect(aRect);
#ifdef USE_SKIN
    iBackGround = CAknsBasicBackgroundControlContext::NewL( KAknsIIDQsnBgAreaMain, Rect(), EFalse );
#endif
    ActivateL();
}
 
void CMyAppContainer::SizeChanged()
{
    TRect r = Rect();
    if (iTextBox)
    {
        TSize scr = CEikonEnv::Static()->ScreenDevice()->SizeInPixels();
        iTextBox->SetExtent(TPoint(0, 0), TSize(r.Width(), r.Height()));
    }
}
 
void CMyAppContainer::HandleResourceChange(TInt aType)
{
    CCoeControl::HandleResourceChange(aType);
    if (aType == KEikDynamicLayoutVariantSwitch)
    {
        SetRect(iView->ClientRect());
    }
}
 
void CMyAppContainer::Draw(const TRect& aRect) const
{
    CWindowGc& gc = SystemGc();
#ifdef USE_SKIN
    MAknsSkinInstance* skin = AknsUtils::SkinInstance();
    MAknsControlContext* cc = AknsDrawUtils::ControlContext(this);
    AknsDrawUtils::Background(skin, cc, this, gc, aRect);
#else
    gc.SetPenStyle(CGraphicsContext::ENullPen);
    gc.SetBrushColor(KRgbBlue);
    gc.SetBrushStyle(CGraphicsContext::ESolidBrush);
    gc.DrawRect(aRect);
#endif
}
 
TInt CMyAppContainer::CountComponentControls() const
{
    return 1;
}
 
CCoeControl* CMyAppContainer::ComponentControl(TInt aIndex) const
{
    switch (aIndex)
    {
    case 0:
        return iTextBox;
    default:
        return NULL;
    }
}
 
TKeyResponse CMyAppContainer::OfferKeyEventL(const TKeyEvent& keyEvent, TEventCode type)
{
    if (type != EEventKey )
        return EKeyWasNotConsumed;
 
    switch (keyEvent.iCode)
    {
    case EKeyLeftArrow:
    case EKeyRightArrow:
        return EKeyWasNotConsumed;
    }
    return iRTx->OfferKeyEventL(keyEvent, type);
}
 
// from MRTxBackgroundDrawer
void CMyAppContainer::RTxDrawBackground(const TPoint& aDstPos, const TRect& aRect, CBitmapContext& gc)
{
#ifdef USE_SKIN
    MAknsSkinInstance* skin = AknsUtils::SkinInstance();
    MAknsControlContext* cc = AknsDrawUtils::ControlContext(this);
    AknsDrawUtils::DrawBackground(skin, cc, this, gc, TPoint(0, 0), aRect, KAknsDrawParamDefault);
#else
    gc.SetPenStyle(CGraphicsContext::ENullPen);
    gc.SetBrushColor(KRgbBlue);
    gc.SetBrushStyle(CGraphicsContext::ESolidBrush);
    gc.DrawRect(aRect);
#endif
}
 
#ifdef USE_SKIN
TTypeUid::Ptr CMyAppContainer::MopSupplyObject(TTypeUid aId)
{
    if (aId.iUid == MAknsControlContext::ETypeId && iBackGround)
        return MAknsControlContext::SupplyMopObject(aId, iBackGround);
    return CCoeControl::MopSupplyObject(aId);
}
#endif
 
void CMyAppContainer::PrepareBitmapL(const TDesC& aFileName, TInt aId, TInt aIdMask)
{
    CFbsBitmap* bitmap, *bitmap_mask;
    AknIconUtils::CreateIconL(bitmap, bitmap_mask, aFileName, aId, aIdMask);
    TSize scr = CEikonEnv::Static()->ScreenDevice()->SizeInPixels();
    TSize iconSize(scr.iWidth / 2, scr.iWidth / 3); // sample resizing - depends on the image
    AknIconUtils::SetSize(bitmap, iconSize, EAspectRatioNotPreserved);
    AknIconUtils::SetSize(bitmap_mask, iconSize, EAspectRatioNotPreserved);
    iBitmap->AppendL(bitmap);
    iBitmapMask->AppendL(bitmap_mask);
}
 
///////////////////////////////
// RTxBackgroundDrawer.h       
///////////////////////////////
 
/* Leszek Buczkowski, Ingraal 2006 */
 
#ifndef __RTX_BACKGROUND_DRAWER_H__
#define __RTX_BACKGROUND_DRAWER_H__
 
class MRTxBackgroundDrawer
{
public:
    virtual void RTxDrawBackground(const TPoint& aDstPos, const TRect& aRect, CBitmapContext& gc) = 0;
};
 
#endif
 
///////////////////////////////
// RTxPicture.h                
///////////////////////////////
 
/* Leszek Buczkowski, Ingraal 2006 */
 
#ifndef __RTX_PICTURE_H__
#define __RTX_PICTURE_H__
 
#include <gdi.h>
 
class CWindowGc;
class TSize;
class CFbsBitmap;
class MRTxBackgroundDrawer;
 
class CRTxPicture : public CPicture
{
public:  // no destructor - bitmap not owned
    CRTxPicture(CWindowGc& gc, MRTxBackgroundDrawer& aControl, CFbsBitmap& aBitmap, CFbsBitmap& aBitmapMask);
 
public: 
    TBool LineBreakPossible(TUint aClass, TBool aBeforePicture, TBool aHaveSpaces) const {return EFalse;};
    void Draw(CGraphicsContext& aGc, const TPoint& aTopLeft, const TRect& aClipRect, MGraphicsDeviceMap* aMap) const;
    void ExternalizeL(RWriteStream& aStream) const {};
    void GetOriginalSizeInTwips(TSize& aSize) const {aSize = iSizeInTwips;};
 
protected:
    TSize iSizeInTwips;
    MRTxBackgroundDrawer& iControl;
    CFbsBitmap* iBitmap;
    CFbsBitmap* iBitmapMask;
};
 
#endif
 
///////////////////////////////
// RTxPicture.cpp              
///////////////////////////////
 
/* Leszek Buczkowski, Ingraal 2006 */
 
#include <fbs.h>
#include <w32std.h>
#include "RTxPicture.h"
#include "RTxBackgroundDrawer.h"
 
#ifdef USE_SKIN
#include <AknsDrawUtils.h>
#include <AknsBasicBackgroundControlContext.h>
#endif
 
CRTxPicture::CRTxPicture(CWindowGc& gc, MRTxBackgroundDrawer& aControl, CFbsBitmap& aBitmap, CFbsBitmap& aBitmapMask) : iControl(aControl), iBitmap(&aBitmap), iBitmapMask(&aBitmapMask)
{
    TSize sizeInPixels = gc.Device()->SizeInPixels();
    TSize sizeInTwips = gc.Device()->SizeInTwips();
    TSize bitmapSizeInPixels = aBitmap.SizeInPixels();
    iSizeInTwips = TSize(sizeInTwips.iWidth * bitmapSizeInPixels.iWidth / sizeInPixels.iWidth, sizeInTwips.iHeight * bitmapSizeInPixels.iHeight / sizeInPixels.iHeight);
}
 
void CRTxPicture::Draw(CGraphicsContext& aGc, const TPoint& aTopLeft, const TRect& aClipRect, MGraphicsDeviceMap* aMap) const
{
    CBitmapContext& gc = static_cast<CBitmapContext &>(aGc);
    TRect bmpPieceRect(TPoint(0,0),iBitmap->SizeInPixels());
    
    // here is the skin background drawn
    iControl.RTxDrawBackground(aTopLeft, bmpPieceRect, gc);
 
    // then the picture itself
    gc.BitBltMasked(aTopLeft, iBitmap, bmpPieceRect, iBitmapMask, ETrue);
}
 
///////////////////////////////                 
// RTx.h                       
///////////////////////////////
 
/* Leszek Buczkowski, Ingraal 2006 */
 
#ifndef __RTX_H__
#define __RTX_H__
 
#include <e32base.h>
#include <gdi.h>
#include <coedef.h>
#include <w32std.h>
#include <txtfrmat.h>
#include <eikrted.h>
#include <txtrich.h>
#include "RTxBackgroundDrawer.h"
 
class CWindowGc;
class CFbsBitmap;
 
// CRTxEditor is derived from CEikRichTextEditor in order to make protected GetSystemGc available
// as public (used in CRTx::InsertPictureL)
class CRTxEditor : public CEikRichTextEditor
{
public:
    CRTxEditor(const TGulBorder& aBorder) { iBorder = aBorder; };
    CWindowGc& GetSystemGc() const { return SystemGc(); };
};
 
class CRTx : public CBase
{
public:
    CRTx(CRTxEditor* aTextBox);
    ~CRTx();
    TKeyResponse OfferKeyEventL(const TKeyEvent& aKeyEvent,TEventCode aType);
    void AddCarriageReturnL();
    void AddTextL (const TDesC& aText);
    void InsertPictureL(MRTxBackgroundDrawer& aControl, TInt aPos, CFbsBitmap& aBitmap, CFbsBitmap& aBitmapMask);
    void AddPictureL(MRTxBackgroundDrawer& aControl, CFbsBitmap& aBitmap, CFbsBitmap& aBitmapMask);
 
private: 
    CRTxEditor* iTextBox;
    TCharFormatMask iCharFormatMask;
    TCharFormat iCharFormat;
};
 
#endif                 
 
///////////////////////////////
// RTx.cpp                     
///////////////////////////////
 
/* Leszek Buczkowski, Ingraal 2006 */
 
#include "RTx.h"
#include "RTxPicture.h"
#include <eikrted.h>
#include <txtrich.h>
 
CRTx::CRTx(CRTxEditor* aTextBox)
{
    iTextBox = aTextBox;
}
 
CRTx::~CRTx()
{
}
 
void CRTx::AddCarriageReturnL()
{
    CRichText* richText = iTextBox->RichText();
    richText->InsertL(richText->DocumentLength(), CEditableText::ELineBreak);
    iTextBox->HandleTextChangedL();
}
 
void CRTx::AddTextL(const TDesC& aText)
{
    CRichText* richText = iTextBox->RichText();
    TInt documentLength = richText->DocumentLength();
    richText->InsertL (documentLength, aText);
    richText->ApplyCharFormatL(iCharFormat, iCharFormatMask,documentLength,aText.Length());
    iTextBox->HandleTextChangedL();
}
 
void CRTx::InsertPictureL(MRTxBackgroundDrawer& aControl, TInt aPos, CFbsBitmap& aBitmap, CFbsBitmap& aBitmapMask)
{
    CRTxPicture* picture;
    picture = new(ELeave) CRTxPicture(iTextBox->GetSystemGc(), aControl, aBitmap, aBitmapMask);
    CleanupStack::PushL(picture);
    TPictureHeader header;
    header.iPicture = TSwizzle<CPicture>(picture);
    iTextBox->RichText()->InsertL(aPos, header);
    CleanupStack::Pop(); 
}
 
void CRTx::AddPictureL(MRTxBackgroundDrawer& aControl, CFbsBitmap& aBitmap, CFbsBitmap& aBitmapMask)
{
    CRichText* richText = iTextBox->RichText();
    TInt documentLength = richText->DocumentLength();
    InsertPictureL(aControl, documentLength, aBitmap, aBitmapMask);
}
 
TKeyResponse CRTx::OfferKeyEventL(const TKeyEvent& aKeyEvent,TEventCode aType)
{
    if (aType == EEventKey)
    {
        if (aKeyEvent.iCode == EKeyDownArrow)
        {
            iTextBox->MoveCursorL (TCursorPosition::EFPageDown, EFalse);
            return EKeyWasConsumed;
        }
        else if (aKeyEvent.iCode == EKeyUpArrow)
        {
            iTextBox->MoveCursorL (TCursorPosition::EFPageUp, EFalse);
            return EKeyWasConsumed;
        }
        else
        {
            return iTextBox->OfferKeyEventL(aKeyEvent, aType);
        }
    }
    return EKeyWasNotConsumed;
}
Related Discussions
Thread Thread Starter Forum Replies Last Post
Drawing errors using an edwin and scroll bar rparviainen Symbian User Interface 2 2006-11-03 10:56
Is CSHelp.app displaying images in help topics ? lotb General Symbian C++ 4 2007-03-05 06:44
How to show line in CEikRichTextEditor control? Symbi S Symbian User Interface 2 2004-08-20 20:30
About AknsUtils::CreateBitmapL? shiguoyong Symbian Media (Graphics & Sounds) 2 2006-09-10 15:08
CEikRichTextEditor is slooooow Kalderas General Symbian C++ 0 2004-02-27 19:26
 
Powered by MediaWiki
     
     RDF Facets:
     
     
     qfnZtopicQUqfnTopicZseriesE5f60Q
     qfnZtypeQUqfnTypeZCommunityContentQ
     qfnZtypeQUqfnTypeZWebpageQ
     qfnZtypeQUqfnTypeZWikiContentQ
     qmarsZlanguageQUxhttpE3aE2fE2fswE2enokiaE2ecomE2flanguageE2d1E2fenX