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 );
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 );