大家可能对自定义控件有所了解,其实自定义对话框和自定义控件类似。但是自定义模态对话的实现最关键的地方就是进行阻塞。比如:
CAknInformationNote* pNote = new(ELeave) CAknInformationNote;
TInt nRet = pNote->ExecuteLD(_L(“Test”));
首先介绍一下,我自己实现的思路:
1、建立一个活动对象;
2、建立一个活动对象调度器,使用调度器来达到阻塞的目的;
3、在活动对象类中新建一个自定义控件;并将该控件加入到AppUi的Stack,以获得按键信息;
以下是相应的代码,如有更好的解决方案,请多多赐教。。
/*
============================================================================
Name : MdDialog.h
Author : 赵旭峰
Version : 1.0
Time : 2011/05/30
Description : 自定义模态对话框
============================================================================
*/
#ifndef MDDIALOG_H_
#define MDDIALOG_H_
#include <e32base.h>
#include “MdCtrl.h”
class CMdDialog : public CActive, public MMdCtrl
{
public:
static CMdDialog* NewL();
static CMdDialog* NewLC();
~CMdDialog();
private:
CMdDialog();
void ConstructL();
public:
void StartL();
public:
static TInt DoModalLD();
public:
/*
* 功能: 通知退出
* 参数:
* 返回:
*/
virtual void NotifyExit();
// from CActive
private:
virtual void RunL();
virtual void DoCancel();
virtual TInt RunError(TInt aError);
private:
RTimer iTimer; // 定时器
CMdCtrl* iCtrl; // 自定义控件
};
#endif /* MDDIALOG_H_ */
/*
============================================================================
Name : MdDialog.cpp
Author : 赵旭峰
Version : 1.0
Time : 2011/05/30
Description : 自定义模态对话框
============================================================================
*/
#include “MdDialog.h”
CMdDialog* CMdDialog::NewL()
{
CMdDialog* self = CMdDialog::NewLC();
CleanupStack::Pop(self);
return self;
}
CMdDialog* CMdDialog::NewLC()
{
CMdDialog* self = new(ELeave) CMdDialog;
CleanupStack::PushL(self);
self->ConstructL();
return self;
}
CMdDialog::CMdDialog():
CActive(EPriorityStandard)
{
}
CMdDialog::~CMdDialog()
{
// 取消运行
if(IsActive())
Cancel();
// 定时器
iTimer.Close();
}
void CMdDialog::ConstructL()
{
// 初始化计数器和定时器
User::LeaveIfError(iTimer.CreateLocal());
}
void CMdDialog::StartL()
{
// 设定定时器状态为0.1秒
iTimer.After(iStatus, 1000*100);
// 提交异步请求
SetActive();
}
TInt CMdDialog::DoModalLD()
{
// 创建活动对象调度器
CActiveScheduler* scheduler = new (ELeave) CActiveScheduler();
CleanupStack::PushL(scheduler);
// 创建活动对象
CMdDialog* active = CMdDialog::NewL();
scheduler->Add(active);
active->StartL();
// 启动活动对象调度器
CActiveScheduler::Start();
// 删除活动对象
if (active)
{
delete active;
active = NULL;
}
// 删除活动对象调度器
CleanupStack::PopAndDestroy(scheduler);
return 0;
}
/*
* 功能: 通知退出
* 参数:
* 返回:
*/
void CMdDialog::NotifyExit()
{
// 删除自定义控件
if(iCtrl)
delete iCtrl, iCtrl = NULL;
// 停止活动对象调度器
CActiveScheduler::Stop();
}
void CMdDialog::RunL()
{
// 创建自定义控件
iCtrl = CMdCtrl::NewL(this);
}
void CMdDialog::DoCancel()
{
}
TInt CMdDialog::RunError(TInt aError)
{
}
/*
============================================================================
Name : MdCtrl.h
Author : 赵旭峰
Version : 1.0
Time : 2011/05/30
Description : 自定义控件
============================================================================
*/
#ifndef MDCTRL_H_
#define MDCTRL_H_
#include <coecntrl.h> // CCoeControl
class MMdCtrl
{
public:
/*
* 功能: 通知退出
* 参数:
* 返回:
*/
virtual void NotifyExit() = 0;
};
// CMdCtrl
// 命令控制按钮组
class CMdCtrl : public CCoeControl
{
public:
static CMdCtrl* NewL(MMdCtrl* aObserver);
static CMdCtrl* NewLC(MMdCtrl* aObserver);
// 析构函数
~CMdCtrl();
private:
CMdCtrl(MMdCtrl* aObserver);
void ConstructL();
public: // 来自CCoeControl
// 指针事件
virtual TKeyResponse OfferKeyEventL(const TKeyEvent& aKeyEvent,TEventCode aType);
// 按键事件
virtual void HandlePointerEventL(const TPointerEvent& aPointerEvent);
// 大小改变
virtual void SizeChanged();
// 位置改变
virtual void PositionChanged();
// 绘制
virtual void Draw(const TRect& aRect) const;
private: // 绘制
/* 功能: 画背景
* 参数: aGc:窗口设备句柄; aRect:控件区域
* 返回值: -
* 注解: -
*/
void DrawBackground(CWindowGc& aGc, TRect& aRect) const;
/* 功能: 画前景
* 参数: aGc:窗口设备句柄; aRect:控件区域
* 返回值: -
* 注解: -
*/
void DrawForeground(CWindowGc& aGc, TRect& aRect) const;
private:
MMdCtrl* iObserver;
};
#endif /* MDCTRL_H_ */
/*
============================================================================
Name : MdCtrl.cpp
Author : 赵旭峰
Version : 1.0
Time : 2011/05/30
Description : 自定义控件
============================================================================
*/
#include <eikenv.h> // CEikonEnv
#include <coeaui.h> // CCoeAppUi
#include “MdCtrl.h”
CMdCtrl* CMdCtrl::NewL(MMdCtrl* aObserver)
{
CMdCtrl* self = CMdCtrl::NewLC(aObserver);
CleanupStack::Pop();
return self;
}
CMdCtrl* CMdCtrl::NewLC(MMdCtrl* aObserver)
{
CMdCtrl* self = new(ELeave) CMdCtrl(aObserver);
CleanupStack::PushL(self);
self->ConstructL();
return self;
}
// 二次构造
void CMdCtrl::ConstructL()
{
// 创建窗口
CreateWindowL();
// 设置区域
SetExtentToWholeScreen();
// 加入堆栈
CEikonEnv::Static()->AppUi()->AddToStackL(this);
// 没有父窗口时,激活自己
ActivateL();
}
// 构造函数
CMdCtrl::CMdCtrl(MMdCtrl* aObserver):
iObserver(aObserver)
{
}
// 析构函数
CMdCtrl::~CMdCtrl()
{
// 移出堆栈
CEikonEnv::Static()->AppUi()->RemoveFromStack(this);
}
// 指针事件
TKeyResponse CMdCtrl::OfferKeyEventL(const TKeyEvent& aKeyEvent,TEventCode /*aType*/)
{
// 响应按键
switch(aKeyEvent.iCode)
{
case EKeyDevice0:
case EKeyDevice1:
case EKeyDevice3:
if(iObserver) iObserver->NotifyExit();
break;
}
// 处理所有按键消息
return EKeyWasConsumed;
}
// 按键事件
void CMdCtrl::HandlePointerEventL(const TPointerEvent& aPointerEvent)
{
}
// 大小改变
void CMdCtrl::SizeChanged()
{
DrawNow();
}
// 位置改变
void CMdCtrl::PositionChanged()
{
DrawNow();
}
// 绘制
void CMdCtrl::Draw(const TRect& /*aRect*/) const
{
CWindowGc& gc = SystemGc();
TRect rect = Rect();
// 设置画板区域
gc.SetClippingRect(rect);
// 画背景
DrawBackground(gc, rect);
// 画前景
DrawForeground(gc, rect);
}
/* 功能: 画背景
* 参数: aGc:窗口设备句柄; aRect:控件区域
* 返回值: -
* 注解: -
*/
void CMdCtrl::DrawBackground(CWindowGc& aGc, TRect& aRect) const
{
aGc.SetBrushColor(TRgb(255,0,0));
aGc.SetPenColor(TRgb(0,255,0));
aGc.SetBrushStyle(CWindowGc::ESolidBrush);
aGc.DrawRect(aRect);
}
/* 功能: 画前景
* 参数: aGc:窗口设备句柄; aRect:控件区域
* 返回值: -
* 注解: -
*/
void CMdCtrl::DrawForeground(CWindowGc& aGc, TRect& aRect) const
{
}
使用方法很简单:
#include “MdDialog.h”
TInt nRet = CMdDialog::DoModalLD();