今天闲来无事写了一个活动对象的测试代码,谁知道一运行死活跑不起来.程序执行到SetActive()就自动退出.硬是把这个简单的例子搞了2个小时. 后来才知道原来Carbide.vs提供的Active框架没有重写NewL()或者NewLC()方法,而我直接调用new (ELeave) CActiveTest2NewClass;并没有初始化ConstructL()里面的数据.编译也不报错,Debug跟踪却是下面一行出问题.郁闷的要命.
下面的代码就是今天的收获:
CActiveTest2AppUi from ActiveTest2Appui.h/*
============================================================================
Name : CActiveTest2AppUi from ActiveTest2Appui.h
Author :
Version :
Copyright : Your copyright notice
Description : Declares UI class for application.
============================================================================
*/
#ifndef ACTIVETEST2APPUI_H
#define ACTIVETEST2APPUI_H
// INCLUDES
#include <aknappui.h>
// FORWARD DECLARATIONS
class CActiveTest2Container;
class CActiveTest2NewClass;
// CLASS DECLARATION
/**
* Application UI class.
* Provides support for the following features:
* - EIKON control architecture
*
*/
class CActiveTest2AppUi : public CAknAppUi
{
public: // // Constructors and destructor
/**
* EPOC default constructor.
*/
void ConstructL();
/**
* Destructor.
*/
~CActiveTest2AppUi();
public: // New functions
public: // Functions from base classes
private:
// From MEikMenuObserver
void DynInitMenuPaneL(TInt aResourceId,CEikMenuPane* aMenuPane);
private:
/**
* From CEikAppUi, takes care of command handling.
* @param aCommand command to be handled
*/
void HandleCommandL(TInt aCommand);
/**
* From CEikAppUi, handles key events.
* @param aKeyEvent Event to handled.
* @param aType Type of the key event.
* @return Response code (EKeyWasConsumed, EKeyWasNotConsumed).
*/
virtual TKeyResponse HandleKeyEventL(
const TKeyEvent& aKeyEvent,TEventCode aType);
private: //Data
CActiveTest2Container* iAppContainer;
CActiveTest2NewClass* iTest2NewClass;
};
#endif
CActiveTest2AppUi from ActiveTest2Appui.cpp/*
============================================================================
Name : CActiveTest2AppUi from ActiveTest2Appui.cpp
Author :
Version :
Copyright : Your copyright notice
Description : CActiveTest2AppUi implementation
============================================================================
*/
// INCLUDE FILES
#include "ActiveTest2Appui.h"
#include "ActiveTest2Container.h"
#include <ActiveTest2.rsg>
#include "ActiveTest2.hrh"
#include "ActiveTest2NewClass.h"
#include <avkon.hrh>
#include <aknnotewrappers.h>
// ================= MEMBER FUNCTIONS =======================
//
// ----------------------------------------------------------
// CActiveTest2AppUi::ConstructL()
//
// ----------------------------------------------------------
//
void CActiveTest2AppUi::ConstructL()
{
BaseConstructL();
iTest2NewClass = CActiveTest2NewClass::NewL();
iAppContainer = new (ELeave) CActiveTest2Container;
iAppContainer->SetMopParent( this );
iAppContainer->ConstructL( ClientRect() );
AddToStackL( iAppContainer );
}
// ----------------------------------------------------
// CActiveTest2AppUi::~CActiveTest2AppUi()
// Destructor
// Frees reserved resources
// ----------------------------------------------------
//
CActiveTest2AppUi::~CActiveTest2AppUi()
{
if (iAppContainer)
{
RemoveFromStack( iAppContainer );
delete iAppContainer;
}
if(iTest2NewClass)
{
delete iTest2NewClass;
}
}
// ------------------------------------------------------------------------------
// CActiveTest2AppUi::DynInitMenuPaneL(TInt aResourceId,CEikMenuPane* aMenuPane)
// This function is called by the EIKON framework just before it displays
// a menu pane. Its default implementation is empty, and by overriding it,
// the application can set the state of menu items dynamically according
// to the state of application data.
// ------------------------------------------------------------------------------
//
void CActiveTest2AppUi::DynInitMenuPaneL(
TInt /*aResourceId*/,CEikMenuPane* /*aMenuPane*/)
{
}
// ----------------------------------------------------
// CActiveTest2AppUi::HandleKeyEventL(
// const TKeyEvent& aKeyEvent,TEventCode /*aType*/)
// takes care of key event handling
// ----------------------------------------------------
//
TKeyResponse CActiveTest2AppUi::HandleKeyEventL(
const TKeyEvent& /*aKeyEvent*/,TEventCode /*aType*/)
{
return EKeyWasNotConsumed;
}
// ----------------------------------------------------
// CActiveTest2AppUi::HandleCommandL(TInt aCommand)
// takes care of command handling
// ----------------------------------------------------
//
void CActiveTest2AppUi::HandleCommandL(TInt aCommand)
{
switch ( aCommand )
{
case EAknSoftkeyBack:
case EEikCmdExit:
{
Exit();
break;
}
case EActiveTest2CmdAppTest:
{
// Info message shown only in the emulator
//iEikonEnv->InfoMsg(_L("test"));
//Load localized message from the resource file
//HBufC* message = CEikonEnv::Static()->AllocReadResourceLC(R_MESSAGE_TEXT);
// Show information note dialog
//CAknInformationNote* note = new (ELeave) CAknInformationNote;
//note->ExecuteLD(message->Des());
//CleanupStack::PopAndDestroy(message);
iTest2NewClass->StartL(3000000);
break;
}
// TODO: Add Your command handling code here
default:
break;
}
}
ActiveTest2NewClass.h
/*
============================================================================
Name : ActiveTest2NewClass.h
Author :
Version :
Copyright : Your copyright notice
Description : CActiveTest2NewClass declaration
============================================================================
*/
#ifndef ACTIVETEST2NEWCLASS_H
#define ACTIVETEST2NEWCLASS_H
#include <e32base.h> // For CActive, link against: euser.lib
#include <e32std.h> // For RTimer, link against: euser.lib
class CActiveTest2NewClass : public CActive
{
public:
// C++ constructor
CActiveTest2NewClass();
// Second-phase constructor
void ConstructL();
// Cancel and destroy
~CActiveTest2NewClass();
public: // New functions
// Function for making the initial request
void StartL(TTimeIntervalMicroSeconds32 aDelay);
//就是下面两个方法Carbide.vs没提供
static CActiveTest2NewClass* NewLC();
static CActiveTest2NewClass* NewL();
private: // From CActive
// Handle completion
void RunL();
// How to cancel me
void DoCancel();
// Override to handle leaves from RunL(). Default implementation causes
// the active scheduler to panic.
//void RunError(TInt aError);
private:
enum TActiveTest2NewClassState
{
EUninitialized, // Uninitialized
EInitialized, // Initalized
EError // Error condition
};
private:
TInt iState; // State of the active object
RTimer iTimer; // Provides async timing service
TInt iCount;
};
#endif
ActiveTest2NewClass.cpp
/*
============================================================================
Name : ActiveTest2NewClass.cpp
Author :
Version :
Copyright : Your copyright notice
Description : CActiveTest2NewClass implementation
============================================================================
*/
#include "ActiveTest2NewClass.h"
#include <eikenv.h >
CActiveTest2NewClass::CActiveTest2NewClass() : CActive(EPriorityStandard) // Standard priority
{
}
void CActiveTest2NewClass::ConstructL()
{
User::LeaveIfError(iTimer.CreateLocal()); // Initialize timer
CActiveScheduler::Add(this); // Add to scheduler
}
CActiveTest2NewClass* CActiveTest2NewClass::NewLC()
{
CActiveTest2NewClass* self = new (ELeave) CActiveTest2NewClass;
CleanupStack::PushL(self);
self->ConstructL();
return self;
}
CActiveTest2NewClass* CActiveTest2NewClass::NewL()
{
CActiveTest2NewClass* self = NewLC();
CleanupStack::Pop(self);
return self;
}
CActiveTest2NewClass::~CActiveTest2NewClass()
{
Cancel(); // Cancel any request, if outstanding
// Delete instance variables if any
}
void CActiveTest2NewClass::DoCancel()
{
iTimer.Cancel();
}
void CActiveTest2NewClass::StartL(TTimeIntervalMicroSeconds32 aDelay)
{
Cancel(); // Cancel any request, just to be sure
iState = EUninitialized;
iTimer.After(iStatus, aDelay); // Set for later
SetActive(); // Tell scheduler a request is active
}
void CActiveTest2NewClass::RunL()
{
if (iState == EUninitialized) {
// Do something the first time RunL() is called
//iState = EInitialized;
iCount++;
_LIT(TempString,"the iCount's value is :");
HBufC* iBuf = HBufC::NewLC(100);
iBuf->Des().Copy(TempString);
iBuf->Des().AppendNum(iCount);
CEikonEnv::Static()->InfoMsg(*iBuf);
CleanupStack::PopAndDestroy(iBuf);
} else if (iState != EError) {
// Do something
}
iTimer.After(iStatus, 3000000); // Set for 1 sec later
SetActive(); // Tell scheduler a request is active
}
另外就是以下几点收获:
1:debug到某一行出错并不代表就是这行的错误,可能是它上面一行,要看debug窗口里面红色显示的内容.
2:在epoc32\wins\c\system\Bootdata下面建一个ErrRd文件(无扩展名),可以让程序在关闭退出的时候报一个错误码.例如我的这个错误报kern-exec 0.之后可以到