后台运行时,在桌面显示提示界面 (例如 小图标)

试验平台:
模拟器 - S60_5th_Edition_SDK_v0.9
真机   - 5700(S60_3rd_FP1)

描述:当程序被切换到了后台运行的时候,并且手机返回到了Idle画面。这时就会出现一个工具条来提示用户此程序正在后台运行,相当于windows系统的任务栏,只不过这个工具条暂时还不能处理事件,等过段时间,我会更新这篇文章,并将事件处理的部分加进去。 ^_^


[PlayInBackgroudAppUi.h]

class CPlayInBackgroudAppUi : public CAknAppUi
{
...
public:

    void ConstructL();

    virtual ~CPlayInBackgroudAppUi();

    //TBool IsTaskInForegroundL(const TDesC & aAppCaption);
    TBool IsTaskInForegroundL(TUid aAppUid); // 判断某个程序是否在前台
    /* 之所以这里不采用应用程序的名字来判断是因为同一个应用程序在不同的平台上
的名称有可能不同,比如Idle画面这个程序在S60 3rd版本上被称为"Standby",
而在S60 5.0上却被称为"Home screen"。除此之外,如果用户在多个语言之间
进行了切换,那么不可避免的,程序的名称势必又发生了改变。综合以上,这里使
用了可以唯一标识程序的UID来来判断该程序是否在前台 */

    // call back function
    static TInt QueryStandbyIsForegroudApp(TAny * aParam);
    ...

protected:

    void HandleForegroundEventL(TBool aForeground);
    ...

public:

    /* iBackgroudWin是实现悬浮窗体的核心类,为了使此代码示例尽量精简,也为了能偷点懒,所以将其定义为public的成员变量,以便在其它类中被使用。  ^_^ */
    CBackWin * iBackgroudWin;

private:

    // Data
    /**
     * The application view
     * Owned by CPlayInBackgroudAppUi
     */

    CPlayInBackgroudAppView* iAppView;

    CPeriodic * iPeriodic;

    RWsSession & iWsSession;
};

[PlayInBackgroudAppUi.cpp]

...
CPlayInBackgroudAppUi::CPlayInBackgroudAppUi()
            : iWsSession(CEikonEnv::Static()->WsSession())
    {
    /* 由于调用CEikonEnv::Static()方法会牵涉到线程间的数据存储,会影响程序的
执行速度,所以这里在构造方法中将窗口服务器的会话实例赋值给
CPlayInBackgroudAppUi的一个成员引用。否则就只有在调用回调中都获取一次
窗口服务器的会话实例。 */
    }

void CPlayInBackgroudAppUi::ConstructL()
    {
   
// Initialise app UI with standard value.
    BaseConstructL(CAknAppUi::EAknEnableSkin);

    // Create view object
    iAppView = CPlayInBackgroudAppView::NewL(ClientRect());
    iBackgroudWin = CBackWin::NewL(); // 漂浮窗体

    // 定时查询某个程序是否在前台的定时器
    iPeriodic = CPeriodic::NewL(CActive::EPriorityUserInput);
}

CPlayInBackgroudAppUi::~CPlayInBackgroudAppUi()
    {
    delete iBackgroudWin; iBackgroudWin = NULL;

    iPeriodic->Cancel();

    delete iPeriodic; iPeriodic = NULL;

    if (iAppView)
        {
        delete iAppView;
        iAppView = NULL;
        }
    }

// 判断UID为aAppUid的应用程序当前是否在前台。
// 注意,在前台的程序不一定是能够接受focus事件的程序。
TBool CPlayInBackgroudAppUi::IsTaskInForegroundL(TUid aAppUid)
{
    TBool isFore = EFalse;
   
   
// 获取当前正在运行的所有的程序的信息
    RArray<RWsSession::TWindowGroupChainInfo> wgIds;
    iWsSession.WindowGroupList(0, &wgIds);
   
    TInt WgId = (wgIds[0]).iId;
// 第一个程序应该就是当前在前台运行的程序
    wgIds.Close();

    // 获取指定id的window group
    CApaWindowGroupName* wgn = CApaWindowGroupName::NewLC(iWsSession, WgId);

    if (wgn->AppUid() == aAppUid) // UID of the application.
        {
        isFore = ETrue;
        }

    CleanupStack::PopAndDestroy(wgn);
   
    return isFore;
}

// 回调函数,用于判断当前standby(Home screen)程序是否在前台运行。
TInt CPlayInBackgroudAppUi::QueryStandbyIsForegroudApp(TAny * aParam)
{
    CPlayInBackgroudAppUi * self = static_cast<CPlayInBackgroudAppUi *>(aParam);

    // The uid of Standby(Home screen) is 0x101FD64C
    const TUid KUidStandbyApp = {0x101FD64C};

    if(self->IsTaskInForegroundL(KUidStandbyApp))
        {
       
// 如果前台程序是Standby(Home screen),则显示漂浮窗口
        self->iBackgroudWin->MakeVisible(ETrue);
        }
    else
        {
        self->iBackgroudWin->MakeVisible(EFalse);
        }

    return 1; // return value isn't 0 means cotinue call callback.
}

void CPlayInBackgroudAppUi::HandleForegroundEventL(TBool aForeground)
{
    CAknAppUi::HandleForegroundEventL(aForeground);

    if(!aForeground) // 从前台转为后台
        {
       
// 启用定时器进行周期性地查询前台运行的程序
        if(!iPeriodic->IsActive())
            iPeriodic->Start(0, 300000, TCallBack(QueryStandbyIsForegroudApp, this));
        }
    else
// 从后台转为前台
        {
        iPeriodic->Cancel();
        iBackgroudWin->MakeVisible(/*EFalse*/ETrue);
        }
}
...

 

[CBackWin继承自CCoeControl类]

...
void CBackWin::ConstructL()
    {
    // set Window Group
    iWindowGroup = RWindowGroup(iCoeEnv->WsSession());

    User::LeaveIfError(iWindowGroup.Construct((TUint32)&iWindowGroup));

    /* 这里要保证aOrdinalPriority的值大于ECoeWinPriorityNormal,否则此窗口无法漂浮在其它窗口之上。*/
    iWindowGroup.SetOrdinalPosition(0, ECoeWinPriorityMedium);
iWindowGroup.EnableReceiptOfFocus(/*ETrue*/EFalse);
   
    // Construct Control Geometry
    CreateWindowL(&iWindowGroup);
    SetSize(TSize(176, 60));
    SetPosition(TPoint(50, 100));
   
    // Set double buffer
    iOffScrnBmp = new (ELeave) CFbsBitmap;
    User::LeaveIfError(iOffScrnBmp->Create(TSize(176, 60), EColor4K));
    iOffScrnBmpDevice = CFbsBitmapDevice::NewL(iOffScrnBmp);
    User::LeaveIfError(iOffScrnBmpDevice->CreateContext(iOffScrnContext));

    // Load Skin bmp
    iSkinBmp = new (ELeave) CFbsBitmap;
    iSkinBmp->Load(KDefaultSkinFileName, 0);
       
    iSkinMaskBmp = new (ELeave) CFbsBitmap;
    iSkinMaskBmp->Load(KDefaultSkinFileName, 1);
    //AknIconUtils::CreateIconL(iSkinBmp, iSkinMaskBmp, KDefaultSkinFileName, 16384, 16385);

    // 貌似此方法在S60 3rd上没有效果,而在S60 5.0上却是有效果的
    Window().SetTransparencyFactor(0xff119100);

    ActivateL();
    }

void CBackWin::Draw(const TRect& aRect) const
    {
    iOffScrnContext->SetBrushColor( TRgb(255, 255, 153));
    iOffScrnContext->Clear(aRect);
   
    // Draw Skin
    iOffScrnContext->BitBltMasked(TPoint(0, 0), iSkinBmp,
        TRect(TPoint(0, 0), TSize(176, 60)), iSkinMaskBmp, ETrue);

    // BitBlt
    CWindowGc& gc = SystemGc();
    gc.BitBlt(TPoint(0, 0), iOffScrnBmp);
    }
...

效果图(图中的那个工具条只会出现在Active Idle画面):

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值