Categories: Graphics | Symbian C++ | S60 | How To | Code Examples
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
AddMACRO USE_SKINto 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 |
