Symbian系统皮肤的使用【转】

1.一句话的方法

最基本的一招就是在AppUi中的ConstructL()中加一句话搞定。如下:

C++代码
void CTestMIMAppUi::ConstructL() {  
BaseConstructL(CAknAppUi::EAknEnableSkin);  
//add your code here...  
}  
用上面这句话基本上能让大部分控件的透明化,显示出系统的皮肤。

但是,有时我们会发现部分控件(比如那个CEikEdwin)仍显示的一个难看的白底,此时,我们需要做一些额外的工作了。

修改Container的头文件,增加一个成员变量:



C++代码
CAknsBasicBackgroundControlContext* iBgContext;  
然后在对应的ConstructL函数中初始它:



C++代码
iBgContext = CAknsBasicBackgroundControlContext::NewL(KAknsIIDQsnBgAreaMainIdle,aRect,ETrue);  
这儿的KAknsIIDQsBgAreaMainIdle你可以选择其它的,不碍事的。
然后,因为CEidEdwin有一个很方便的成员方法SetSkinBackgroundControlContextL,所以接下来的代码就简单了:



C++代码
iEdWin=new(ELeave)CEikEdwin;  
CleanupStack::PushL(iEdWin);  
iEdWin->SetContainerWindowL(*this);  
iEdWin->ConstructL();  
iEdWin->SetSkinBackgroundControlContextL(iBgContext);  
iEdWin->SetExtentToWholeScreen();  
iEdWin->SetFocus(ETrue);  
iEdWin->ActivateL();  
CleanupStack::Pop(iEdWin);  
这样就可以了。别忘了,在析构时delete它。

2.终极方法显示系统皮肤

再进一步,如果控件没有这么方便的成员让我们去设置它的背景,也有办法(参考http://www.newlc.com/Enable-Skin-support-in-your.html)。

很好办,先在H文件中增加一个MopSupplyObject的声明:



C++代码
TTypeUid::Ptr MopSupplyObject(TTypeUid aId);  
然后实现中,ContructL中就不用iEdWin->SetSkinBackgroundControlContextL了,而是在三个函数中分别处理:



C++代码
void CTestMIMEdtContainer::Draw(const TRect& aRect) const {  
CWindowGc& gc = SystemGc();  

MAknsSkinInstance* skin = AknsUtils::SkinInstance();       //皮肤的接口
MAknsControlContext* cc = AknsDrawUtils::ControlContext( this );   //得到皮肤参数
AknsDrawUtils::Background( skin, cc, this, gc, aRect );       //画皮肤
}  

void CTestMIMEdtContainer::SizeChanged() {  
if(iBgContext)  
{  
iBgContext->SetRect(Rect());  
if ( &Window() )  
{  
iBgContext->SetParentPos( PositionRelativeToScreen() );  
}  
}   
DrawNow();  
}  
TTypeUid::Ptr CTestMIMEdtContainer::MopSupplyObject(TTypeUid aId)  
{  
if (iBgContext )  
{  
return MAknsControlContext::SupplyMopObject( aId, iBgContext );  
}  
return CCoeControl::MopSupplyObject(aId);  
}    
这样也可以让控件透明显示出系统皮肤。

3.显示自定义皮肤

来说自定义皮肤的显示,关键在于那个iBgContext成员如何弄出来,前面的NewL()的第一个参数是系统定义的东西,现在我们需要自定义了。

同样,先修改一个H文件,增加一个成员:



C++代码
TAknsItemID aSkinItem;  
然后实现文件中的ContructL函数中,我们要从MIF文件中取图片弄成背景:



C++代码
TFileName iMFileName;  
iMFileName.Copy(KMifFileName);  
CompleteWithAppPath(iMFileName);  

aSkinItem.iMinor = 0xE2139689;  
aSkinItem.iMajor = 1 ;  

CAknsItemDef* mainBgItemDef = AknsUtils::CreateBitmapItemDefL(aSkinItem, iMFileName, EMbmTestmimGrid);  
AknsUtils::SkinInstance()->SetLocalItemDefL( mainBgItemDef );   
iBgContext = CAknsBasicBackgroundControlContext::NewL(aSkinItem,aRect,ETrue );    
这儿的KMifFileName是定义的资源MIF文件(与其它例子中加载资源图像的方法类似)。


=================================================================================================


如果控件的container实现了MopSupplyObject()并且返回了创建CAknsBasicBackgroundControlContext对象,那么就可以在自定义控件中通过下面的代码获取并使用:
Code:

void CYourControl:ConstructL()
{
//Get parent's skin context
MAknsControlContext *context = NULL;

MopGetObject( context );

if( context )
{
iBackground = static_cast<CAknsBasicBackgroundControlContext*>( context );
}
..................
}

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

gc.Clear(aRect);

TRect rect = Rect();

if( iBackground )
{
MAknsSkinInstance* skin = AknsUtils::SkinInstance();
AknsDrawUtils::Background( skin, iBackground, this, gc, rect );
}
........................
}

如果控件的container没有实现并提供背景上下文对象,那就需要控件自己创建 CAknsBasicBackgroundControlContext。但在实践中我碰到了自定义控件自己创建 CAknsBasicBackgroundControlContext,但是背景的大小和位置总是不正确,造成同一container添加多个控件后,背景显示混乱的问题,最后还是通过前面的代码解决的。

系统控件对于皮肤的支持有下面的几种:
Compulsorily skin-providing controls:总是提供皮肤参数,不需要开发者额外操作,比如程序上方的control pane和status pane.

Optionally skin-providing controls:是否提供皮肤参数需要显示设置,比如list和grid需要显示调用ItemDrawer()->SetSkinEnabledL()来激活对皮肤的支持。

Skin-observing controls:本身并不提供皮肤参数,但是可以通MObjectProvider链猎取并使用皮肤,这时需要container获应用提供皮肤参数。

Non-skin-aware controls:既不提供也不使用皮肤参数。

===================================================

通过皮肤取Bitmap
MAknsSkinInstance* skin = AknsUtils::SkinInstance();

CAknsItemData* skinItem = skin->GetCachedItemData( someUID, EAknsITBitmap );   

if( skinItem != NULL )
{
CFbsBitmap* bitmap = static_cast<CAknsBitmapItemData*>(skinItem)->Bitmap();
}
CFbsBitmap* offScreenBitmap = new (ELeave) CFbsBitmap();
User::LeaveIfError( offScreenBitmap->Create( aSize, aDisplayMode ) );
CFbsBitGc* bitGc = 0;
CFbsBitmapDevice* bitmapDevice = CFbsBitmapDevice::NewL( offScreenBitmap );
User::LeaveIfError( bitmapDevice->CreateContext( bitGc ) );
// Draw the content on the off-screen bitmap
AknsDrawUtils::DrawBackground( AknsUtils::SkinInstance(),iSkinContext,this,*bitGc, TPoint(0,0), rect,KAknsDrawParamDefault );
来自: http://hi.baidu.com/ldxcln/blog/item/92f9d512fd62778a6438db74.html
原文地址:https://www.cnblogs.com/zziss/p/2360704.html