Symbian控件開發之CCoeControl

CCoeControl是所有控件的基類,它封裝了一個控件的基本屬性和功能。編寫簡單控件涉及到的函數主要有以下三類:初始化繪圖用戶輸入處理。下面是一個簡單控件的聲明。
class CSimpleControl : public CCoeControl
{
public:
void ConstuctL(const TRect& aRect);
~CSimpleControl();
private:
void Draw(const TRect& aRect) const;
TKeyResponse OfferKeyEventL(const TKeyEvent& aKeyEvent, TEventCode aType);
};
初始化:控件的初始化包括三個主要內容:創建控件窗口,設置控件大小及激活控件。控件的默認大小爲0 x 0,因此必須設置大小,否則將不可見。因此這三個步驟必不可少。初始化一般在第二階段構造函數ConstructL()完成。
void CSimpleControl::ContructL(const TRect& aRect)
{
CreateWindowL();
SetRect(aRect);
ActivateL();
}
繪圖:直接決定控件外觀的函數是Draw()函數。
void CSimpleControl::Draw(const TRect& aRect) const
{
CWindowGc& gc = SystemGc();
gc.SetPenStyle(CGraphicsContext::ENullPen);
gc.SetPenColor(KRgbRed);
gc.SetBrushColor(KRgbDarkBlue);
gc.SetBrushStyle(CGraphicsContext::ESolidBrush);
gc.DrawRect(aRect);
}
在這段代碼中,首先調用SystemGc()獲取圖形上下文,SystemGc()是CCoeControl的一個成員函數;然後設置相應的圖形上下文項;最後調用繪圖函數DrawRect()畫一個矩形。
所有的繪圖都是通過圖形上下文(graphics context,GC)來完成的。在Symbian OS中,定義了一個抽象類CGraphicsContext來統一圖形上下文的接口,爲設備無關的繪圖提供了豐富的API。派生類CWindowGcCFbsBitGc則具體實現了這些API。我們可以直接使用CFbsBitGc來繪圖,但不推薦使用這種方式。在實際編程時,應用程序應該使用CWindowGc通過窗口服務器來進行繪圖。CWindowGc的繪圖請求在窗口服務器的客戶端緩衝區上進行緩存,這樣可以一次性向窗口服務器提交多個繪圖請求以提高繪圖效率。CONE爲每個GUI應用程序提供一個CWindowGc實例作爲控件的缺省圖形上下文,它由CConEnv創建,並且可以 使用CCoeControl::SystemGc()來進行訪問。

圖形上下文保存有下列對繪圖函數有着重要影響的上下文項。
1. 畫筆: pen定義繪圖模式(顏色、樣式和大小),它用來繪製線、輪廓以及文本。
2. 刷子:brush定義了填充模式、背景色或樣式。
3. 字體:font定義了用來繪製文本的字體。圖形上下文沒有默認的字體,因此在使用相關文本函數前,必須調用UseFont()設置字體。另外,在使用完字體後必須調用DiscardFont()來刪除字體,以免內存泄漏。
4. 當前位置:當前位置由MoveTo()和各種DrawXxxTo()成員函數來設置(絕對位置),並由MoveBy()DrawXxxBy()移動(相對位置)。
5. 原點:origin定義了相對與設備原點的偏移,繪圖時使用該偏移,可以使用SetOrigin()來設置原點。默認的原點爲(0,0)。
6. 剪輯區域:clipping region定義圖形操作中想要剪輯的區域。可以指定一個簡單的矩形或任意複雜的區域。設置剪輯區域之後,只有落在剪輯區域內的繪圖操作才被顯示出來。可以使用SetClippingRect()函數來設置矩形剪輯區域,使用CancelClippingRect()來取消它;使用SetClippingRegion()函數來設置任意複雜的剪輯區域,使用CancelClippingRegion()來取消它;
使用Reset()可以將所有的上下文項設置爲默認值。系統調用Draw()函數之前會自動調用Reset()函數,因此通常不需要在控件中顯式調用該函數。
在設置好圖形上下文後,可以調用各種繪圖函數在控件上進行繪圖。幾乎所有的繪圖函數都被設計爲能夠成功執行,因而一般不返回任何值。這使得多個繪圖函數能夠被打包爲一條消息發送到服務器執行。如果繪圖函數有返回值的話,這將是不可能的。
(1) 點和線.這些函數使用當前畫筆。
virtual void Plot(const TPoint& aPoint);
virtual void DrawLine(const TPoint& aPnt1, const TPoint& aPnt2);
virtual void DrawLineTo(const TPoint& aPoint);
virtual void DrawLineBy(const TPoint& aVector);
virtual void DrawArc(const TRect& aRect, const TPoint& aStart, const TPoint& aEnd);
virtual void DrawPolyLine(const CArrayFix<TPoint>* aPointList);
virtual void DrawPolyLine(const TPoint* aPointList, TInt aNumPoints);
(2) 實心輪廓圖形.這些函數使用畫筆和畫刷,畫筆用來繪製輪廓,刷子用來填充輪廓內部。
virtual void DrawPie(const TRect& aRect, const TPoint& aStart, const TPoint& aEnd);
virtual void DrawEllipse(const TRect& aRect);
virtual void DrawRect(const TRect& aRect);
virtual void DrawRoundRect(const TRect& aRect, const TSize& aEllipse);
virtual TInt DrawPolygon(const CArrayFix<TPoint>* aPointList, TFillRule aFillRule = EAlternate);
virtual TInt DrawPolygon(const TPoint* aPointList, TInt aNumPoints, TFillRule aFillRule = EAlternate);
(3) 位圖.能夠以1:1的比例或者拉伸到所指定矩形區域的大小來繪製位圖。
virtual void DrawBitmap(const TPoint& aTopLeft, const CFbsBitmap* aSource);
virtual void DrawBitmap(const TRect& aDestRect, const CFbsBitmap* aSource);
virtual void DrawBitmap(const TRect& aDestRect, const CFbsBitmap* aSource,const TRect& aSourceRect);
(4) 文本.使用當前字體。
virtual void DrawText(const TDesc& aString, const TPoint& aPosition);
virtual void DrawText(const TDesc& aString, const TRect& aBox, TInt aBaselineOffset, TTextAlign aHoriz = ELeft, TInt aLeftMrg = 0);
繪圖和重繪:
在GUI程序中,所有的繪圖都在控件上完成,繪圖是由控件的Draw()函數來完成的,其聲明如下virtual void Draw(const TRect& aRect) const;
基類CCoeControl的Draw()爲空,因此在編寫控件時必須實現該函數,否則控件將不可見。Draw()是由應用程序框架來調用,一般不應在應用程序中直接調用Draw()。控件不只是在初始化繪製它們的外觀,而且在它發生變化時或者系統要求重繪(redraw)時進行重繪。按照重繪的觸發源來劃分,控件的重繪分爲兩種:系統發起的重繪和應用程序發起的重繪。系統發起的重繪處理從窗口服務器開始,它檢測並判斷何時需要重繪哪部分窗口。實際上,它維護窗口上的一個無效區域,並向擁有窗口的應用程序發送一個重繪事件,要求它重繪無效區域。應用程序發起的重繪處理由應用程序觸發,它可以根據需要採用如下方法來實現(這些函數最終都是通過調用Draw()來實現的):void CCoeControl::DrawNow();立即重繪整個控件;void CCoeControl::DrawDeferred()const;一旦有機會就重繪整個控件;void RWindow::Invalidate(const TRect&);一旦有機會就重繪由參數指定的矩形區域。然而通過將重繪活動限制在矩形中,幾乎不會節省很多開銷,因此,編寫大多數控件時,一般忽略傳遞限制矩形參數。
用戶輸入處理
Symbian OS中處理用戶輸入的兩個基本函數是OfferKeyEventL()和HandlePointerEventL()。由於Series60平臺不支持筆寫輸入,所以主要使用OfferKeyEventL()。下面是一個簡單控件處理按鍵事件的代碼:
TKeyResponse CSimpleControl::OfferKeyEventL(const TKenEvent& aKeyEvent, TEventCode aType)
{
switch(aType)
{
case: EEventKey:
   if (aKeyEvent.iScanCode == EStdKeyNkp5 || aKeyEvent.iScanCode == EStdKeyEnter)
    iMyGameEngine->Fire();
   break;
case: EEventKeyDown:
   //....
case: EEventKeyUp:
   //....
}
return EKeyWasNotConsumed;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章