複合控制項,editor控制項,觀察者的一些簡單運用,實現一個類似對話方塊的控制項

來源:互聯網
上載者:User

     原本是想做一個自訂的帶輸入框的對話方塊控制項,開始的思路是用繼承CAknDilog來做的,但是後來發現,這麼做的時候,對話方塊的CBA不好出來,雖然可以可以通過方法隱藏,當時當隱藏CBA後,對話方塊的按鍵就不好處理,所以想了一個代替的方法。

     控制項繼承於CCoeControl的。同時還繼承於MAknEditingStateIndicator,MAknEditingStateIndicator這個主要是為了擷取編輯框當前的輸入狀態。具體的作用自己查SDK吧。廢話不多說先貼代碼,在講思路。

 

 

.h檔案

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

#ifndef __NEWDILOG_H__
#define __NEWDILOG_H__

// INCLUDES

 #include <e32std.h>
#include <eikedwin.h>
#include <akneditstateindicator.h>  // for MAknEditingStateIndicator
#include "MEventObserver.h"
// CLASS DECLARATION
class CClientEventExample;
/**
*  CNewDilog
*
*/
class CNewDilog : public CCoeControl,public MAknEditingStateIndicator
{
public: // Constructors and destructor

 enum   EInputMode   //自己定義的枚舉,用來儲存IME的模式,方便識別
 {
  EUnknown,
  EABC,
  Eabc,
  EAbc,
  E123,
  EPinYin,
  EBiHua
 };

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

 /**
 * Two-phased constructor.
 */
 static CNewDilog* NewL(MInputDilogObserver &aObserver,CCoeControl *aParent);

 /**
 * Two-phased constructor.
 */
 static CNewDilog* NewLC(MInputDilogObserver &aObserver,CCoeControl *aParent);

 TKeyResponse OfferKeyEventL(const TKeyEvent &aKeyEvent, TEventCode aType);
 
private:

 /**
 * Constructor for performing 1st stage construction
 */
 CNewDilog(MInputDilogObserver &aObserver);

 /**
 * EPOC default constructor for performing 2nd stage construction
 */
 void ConstructL(CCoeControl *aParent);
 void Draw( const TRect& aRect ) const;

 void SetState(TAknEditingState aState);    //這個函數以及下面一個函數,是MAknEditingStateIndicator的兩個純虛方法
 CAknIndicatorContainer* IndicatorContainer();
 CEikEdwin *iEditor;

 TInt CountComponentControls() const;
 CCoeControl* ComponentControl( TInt aIndex ) const;
private:
 TRect iRect;
 TRect iEditorRect;
 MInputDilogObserver &iObserver;
 //儲存editor的狀態
 TBool iStatus;

 CCoeControl *iParent;

 //輸入狀態
 EInputMode iCurInputMode;
 //輸入狀態對應的名字
 TBuf<8> iCurModeName;

 //擷取輸入狀態
 void GetInputMode();
public:
 void MakeVisible(TBool aVisible);
 void SetDilogRect(TRect aRect,TRect aEditorRect);
 TBool IsFocus();
 void ConvGbk2Uni(TDesC8& original, TDes& res);
};

struct  S_uid:  public   TUid
{
 S_uid(int   i)
 {  
  iUid   =   i;
 }
};

#endif //__NEWDILOG_H__

 

 

控制項的觀察者 MEventObserver.h檔案

#ifndef __MEVENTOBSERVER_H__
#define __MEVENTOBSERVER_H__

/***********************************************************
* 輸入對話方塊的觀察者
***********************************************************/
class MInputDilogObserver
{
public:
 virtual void GetContent(TDesC &aText,TBool aStatus) = 0;
};

#endif
// End of File

 

.cpp檔案

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

#include "NewDilog.h"
#include <EIKENV.H>
#include <aknenv.h>
#include <aknindicatorcontainer.h>
#include <avkon.hrh>
#include <CHARCONV.H>
#include "InputDilog.h"

CNewDilog::CNewDilog(MInputDilogObserver &aObserver):iObserver(aObserver)
{
 // No implementation required
 iStatus = ETrue;
}

CNewDilog::~CNewDilog()
{
 delete iEditor;
}

CNewDilog* CNewDilog::NewLC(MInputDilogObserver &aObserver,CCoeControl *aParent)
{
 CNewDilog* self = new (ELeave)CNewDilog(aObserver);
 CleanupStack::PushL(self);
 self->ConstructL(aParent);
 return self;
}

CNewDilog* CNewDilog::NewL(MInputDilogObserver &aObserver,CCoeControl *aParent)
{
 CNewDilog* self=CNewDilog::NewLC(aObserver,aParent);
 CleanupStack::Pop(); // self;
 return self;
}

void CNewDilog::ConstructL(CCoeControl *aParent)
{
// iRect = TRect(TPoint(0,160),TSize(240,160));
 iCurModeName.Copy(_L("Abc"));
 iParent = aParent;
// CEikEdwin::ConstructL(EAknEditorFlagDefault | EEikEdwinNoAutoSelection | EEikEdwinJustAutoCurEnd, 0, 10, 1);//調用系統控制項的二段建構函式 
}

TKeyResponse CNewDilog::OfferKeyEventL(const TKeyEvent &aKeyEvent, TEventCode aType)
{

 GetInputMode();

 

//  if(aType == EEventKey &&  aKeyEvent.iScanCode == EStdKeyDevice0)
//  {
//   TBuf<100> TextBuf;
//   iEditor->GetText(TextBuf);
//   iObserver.GetContent(TextBuf,ETrue);
//  }
//  else if(aType == EEventKey &&  aKeyEvent.iScanCode == EStdKeyDevice1)
//  {
//   TBuf<100> TextBuf;
//   iEditor->GetText(TextBuf);
//   iObserver.GetContent(TextBuf,EFalse);
//  }
//  else
//  {
  iEditor->OfferKeyEventL(aKeyEvent,aType);
// }
 return iEditor->OfferKeyEventL(aKeyEvent,aType);
}

void CNewDilog::Draw( const TRect& aRect ) const
{
  CWindowGc& gc = SystemGc();
 if(iStatus)                                                      //是否畫控制項
  {
  gc.SetBrushStyle(CGraphicsContext::ESolidBrush);
  gc.SetBrushColor(KRgbGreen);
  gc.DrawRect(iRect);     //背景色          
  
  gc.SetBrushColor(KRgbWhite);
  gc.DrawRect(TRect(TPoint(iEditorRect.iTl.iX-1,iEditorRect.iTl.iY-1),TSize(iEditorRect.Width()+2,iEditorRect.Height()+2)));  //畫editor矩形框
  gc.SetBrushStyle(CGraphicsContext::ENullBrush);
  const CFont *font = CEikonEnv::Static()->DenseFont();
  gc.UseFont(font);
  gc.SetPenColor(KRgbBlack);
  gc.DrawText(iCurModeName,TPoint(iEditorRect.iTl.iX,iEditorRect.iTl.iY+font->HeightInPixels()+iEditorRect.Height() ));
  gc.DiscardFont();
  iEditor->TextView()->DrawL(iEditorRect);    //解決控制項重新整理時,可能前面輸入的都不顯示了,
 }
}

void CNewDilog::MakeVisible(TBool aVisible)
{
 iStatus = aVisible;
 iEditor->SetFocus(aVisible);
 iEditor->MakeVisible(aVisible);
}

void CNewDilog::SetDilogRect(TRect aRect,TRect aEditorRect)
{
 iRect = aRect;
 iEditorRect = aEditorRect;

 iEditor = new(ELeave) CEikEdwin;
 iEditor->SetContainerWindowL(*iParent);
 iEditor->ConstructL(EAknEditorFlagDefault | EEikEdwinNoAutoSelection | EEikEdwinJustAutoCurEnd, 0, 100, 1);//調用系統控制項的二段建構函式
 iEditor->SetExtent(iEditorRect.iTl,iEditorRect.Size());
 iEditor->MakeVisible(EFalse);
}

TBool CNewDilog::IsFocus()
{
 return iStatus;
}

void CNewDilog::SetState(TAknEditingState aState)
{

}

CAknIndicatorContainer* CNewDilog::IndicatorContainer()
{
 return NULL;
}

void CNewDilog::GetInputMode()
{
 MAknEditingStateIndicator*   ei   =   CAknEnv::Static()->EditingStateIndicator()   ;
 if   (!ei)      return;

 CAknIndicatorContainer* ic   =   ei->IndicatorContainer();                
 if   (!ic)       return;

 iCurModeName.Zero();

 if(ic->IndicatorState(S_uid(EAknNaviPaneEditorIndicatorPinyin)))
 {
  iCurInputMode = EPinYin;
  TBuf8<20>   msg8 ;
  msg8.Format(_L8("拼音"));
  ConvGbk2Uni(msg8, iCurModeName) ;
 }
 if(ic->IndicatorState(S_uid(EAknNaviPaneEditorIndicatorStroke)))
 {
  iCurInputMode = EBiHua;
  TBuf8<20>   msg8 ;
  msg8.Format(_L8("筆畫"));
  ConvGbk2Uni(msg8, iCurModeName) ;
 }
 else   if(ic->IndicatorState(S_uid(EAknNaviPaneEditorIndicatorLowerCase)))
 {
  iCurInputMode = Eabc;
  iCurModeName.Copy(_L("abc"));
 }
 else   if(ic->IndicatorState(S_uid(EAknNaviPaneEditorIndicatorUpperCase)))
 {
  iCurInputMode = EABC;
  iCurModeName.Copy(_L("ABC"));
 }
 else   if(ic->IndicatorState(S_uid(EAknNaviPaneEditorIndicatorTextCase)))
 {
  iCurInputMode = EAbc;
  iCurModeName.Copy(_L("Abc"));
 }
 else   if(ic->IndicatorState(S_uid(EAknNaviPaneEditorIndicatorNumberCase)))
 {
  iCurInputMode = E123;
  iCurModeName.Copy(_L("123"));
 }

 DrawNow();
// CEikEdwin::DrawNow();
}

void CNewDilog::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;
}

TInt CNewDilog::CountComponentControls() const
{
 // return number of controls inside this container
 return 1;
 // return 0;
}

CCoeControl* CNewDilog::ComponentControl( TInt aIndex ) const
{
 switch(aIndex)
 {
 case 0:
  return iEditor;
 }
 return NULL;
}

 

在container中的使用:

1.在container.h中,container需要繼承我們的觀察者代碼如是:

class CContainer:MInputDilogObserver

2.實現MInputDilogObserver的虛方法

void GetContent(TDesC &aText,TBool aStatus);

這個時候我們就直接可以在這個函數中處理返回的的控制項中返回的值和狀態了。

3.定義一個CNewDilog *iNewDilog;成員

4.初始化

iNewDilog = CNewDilog::NewL(*this,this);
 iNewDilog->SetContainerWindowL(*this);
 iNewDilog->SetDilogRect(TRect(TPoint(0,160),TSize(240,160)),TRect(TPoint(50,235), TSize(150,20)));
 iNewDilog->SetExtent(TPoint(0,0), TSize(240,320));
 iNewDilog->MakeVisible(ETrue);

5.CountComponentControls 加1 和 ComponentControl 返回控制項指標

6.在OfferKeyEventL函數中調用控制項的OfferKeyEventL函數來傳遞索引值

7.在解構函式中寫釋放函數

8.編譯運行。

 

總結:我們可以通過makevisible函數來讓控制項顯示和隱藏。同時當點擊確認或取消時,通過觀察者iObserver將狀態和資料返回給使用控制項的container。思路還是比較簡單的。但是遇到的問題確實不少啊~~

 

主題問題:

1.擷取IME時。不識別abc和ABC狀態。當時直接使用的是CEikEdwin的TInt nTemp = AknEditorCurrentInputMode()這個方法。

這個方法在abc,Abc和ABC狀態時都返回1.

2.在中文IME的時候,當選擇中文字的時候,點取消,這個時候不好識別時關閉控制項,還是取消漢字的選擇。經過長時間的嘗試,發現當點擊取消漢字的選擇時,控制項的OfferKeyEventL函數只會走一遍,就是只會走EEventKeyDown,所以可以通過這個判斷是關閉控制項還是漢字的選擇,如代碼中通過aType == EEventKey 事件來判斷關閉控制項。

4.iEditor->TextView()->DrawL(iEditorRect); 這個函數的使用。它的作用是解決控制項重新整理時,可能前面輸入的內容都不顯示了的問題。

5.複合控制項的作用類似於一個container。在控制項中添加控制項時,如果container一樣,需要寫CountComponentControls和ComponentControl函數。複合控制項的ConstructL中也像普通的複合控制項一樣,擁有視窗或者共用container的視窗。本文中用的是共用container的視窗。

 

昨天沒在手機上測試,幾天測了下,發現拼音和筆畫顯示不出來,今天在改下代碼把拼音和筆畫的判斷條件改為如下代碼就OK了

 

if(ic->IndicatorState(S_uid(EAknNaviPaneEditorIndicatorPinyin)) || ic->IndicatorState(S_uid(EAknNaviPaneEditorIndicatorPinyinPhrase)))
 {
  iCurInputMode = EPinYin;
  TBuf8<20>   msg8 ;
  msg8.Format(_L8("拼音"));
  ConvGbk2Uni(msg8, iCurModeName) ;
//  iCurModeName.Copy(_L("PinYin"));
 }
 if(ic->IndicatorState(S_uid(EAknNaviPaneEditorIndicatorStroke)) || ic->IndicatorState(S_uid(EAknNaviPaneEditorIndicatorStrokePhrase)))
 {
  iCurInputMode = EBiHua;
  TBuf8<20>   msg8 ;
  msg8.Format(_L8("筆畫"));
  ConvGbk2Uni(msg8, iCurModeName) ;
//  iCurModeName.Copy(_L("BiHua"));
 }

 

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.