从缺省堆中分配内存单元实现日程表监测
概述:
当日程表被其他程序添加、删除或修改后,某第三方程序可能需要知道这些变化。他们可能也想知道具体哪项日程当前被执行了。
下面的解决方案描述了如何通过在S60第二版中写下一个日程表监测DLL来完成上述需求,具体可查看关于Calendar Interim API的文档。
解决方案:
1)首先生成一个独立的日程表监测DLL,如通过CAgendaObs::NewL()方法从CAgnObserver派生的一个CAgendaObs对象。
下面的小实例演示了这样的情况:
CAgnObserver* CAgendaObs::CloneL()
{
if(!iClone) // initial value (TBool) EFalse
{
// Log: Creating clone
CAgendaObs* result = NewL();
result->iClone = ETrue;
return result;
}
}
void CAgendaObs::StartObserving()
{
if(iClone)
{
//Log: Start observing
}
}
void CAgendaObs::StopObserving()
{
if(iClone)
{
// Log: Stop observing
}
}
void CAgendaObs::Send(TInt aFunction, CAgnEntry *aEntry)
{
if(iClone)
{
switch(aFunction)
{
case ENotifyAddEntry:
// Entry added
break;
case ENotifyDeleteEntry:
// Entry deleted
break;
case ENotifyUpdateEntry:
// Entry updated
break;
case ENotifyAddTodoList:
// ToDo entry added
break;
case ENotifyDeleteTodoList:
// ToDo entry deleted
break;
case ENotifyUpdateTodoList:
// ToDo entry updated
break;
default:
// Unexpected command
break;
}
}
}
void CAgendaObs::Send(TInt aFunction, CAgnTodoList *aTodoList)
{
if(iClone)
{
switch(aFunction)
{
case ENotifyAddEntry:
// Entry added
break;
case ENotifyDeleteEntry:
// Entry deleted
break;
case ENotifyUpdateEntry:
// Entry updated
break;
case ENotifyAddTodoList:
// ToDo entry added
break;
case ENotifyDeleteTodoList:
// ToDo entry deleted
break;
case ENotifyUpdateTodoList:
// ToDo entry updated
break;
default:
// Unexpected command
break;
}
}
}
void CAgendaObs::ExternalizeL(RWriteStream &aStream) const
{
//write your code here
if(iClone)
{
// Log: ExternalizeL called
}
//closing
CAgnObserver::WriteEndMarkerL(aStream);
}
void CAgendaObs::InternalizeL(RReadStream &aStream)
{
//write your code here
if(iClone)
{
// Log: InternalizeL called
}
//closing
CAgnObserver::ReadEndMarkerL(aStream);
}
// The NewL of the DLL, to be exported
EXPORT_C CAgendaObs* CAgendaObs::NewL()
{
CAgendaObs* self = new (ELeave) CAgendaObs();
CleanupStack::PushL(self);
self->ConstructL();
CleanupStack::Pop(self);
return self;
}2) In another application register the observer using the following code:
#ifdef __WINS__
_LIT(KObserverFile,"agendaobs.dll");
#else
_LIT(KObserverFile,"c:\\system\\libs\\agendaobs.dll");
#endif
_LIT(KAgendaFile,"c:\\system\\data\\calendar");
// In ConstructL:
RAgendaServ *iServer = RAgendaServ::NewL();
iServer->Connect();
CAgendaObs* iObserver = CAgendaObs::NewL();
CAgnEntryModel *iModel = CAgnEntryModel::NewL(this);
iModel->SetServer(iServer);
iModel->OpenL(KAgendaFile);
// Call this method to register the observer DLL
void CSomeAppUi::Register()
{
if(iModel)
{
iModel->RegisterObserverL(TFileName(KObserverFile), iObserver);
}
}
// Before exiting, unregister the DLL
void CAgendaAppAppUi::Unregister()
{
if(iModel)
{
iModel->UnregisterObserverL(TFileName(KObserverFile));
}
}注意,在MMP文件中,监测DLL要使用0x10000135作为UID2才行。
使用CHWRMVibra类来启动/停止/查询设备震动的状态
详细描述:
CHWRMVibra类是在S60第三版才开始发布的,它提供了控制设备震动模块的能力。
我们需要的链接库为:WRMVibraClient.lib
链接头文件为:hwrmvibra.h
下列代码演示了如何获得震动状态:
iVibrate = CHWRMVibra::NewL(); CHWRMVibra::TVibraStatus iStatus = iVibrate->VibraStatus();
返回的值有:
EVibraStatusUnknown EVibraStatusNotAllowed EVibraStatusStopped EVibraStatusOn
下列代码演示了如何获取情景模式下的震动部分设置“
CHWRMVibra::TVibraModeState iState = iVibrate->VibraSettings();
返回值为:
EVibraModeUnknown EVibraModeON EVibraModeOFF
下列代码演示了如何启动震动,这时震动的设置必须是EVibraModeON。
iVibrate->StartVibraL(0,50);
第一个参数表示是持续的时间(微秒),如果是0值表明震动将持续到StopVibraL()被调用为止。
第二个参数表明强度值,它的范围是-100至100之间。
下面的代码演示了如何停止震动
iVibrate->StopVibraL();
如何获取设备当前情景模式
详细描述:
我们可以通过使用Profiles Engine Wrapper API来获取当前情景模式。
首先需要包含这两个头文件:
mproengengine.h proengfactory.h
然后是链接库:
ProfileEngine.lib
再看下列演示代码:
MProEngEngine* engine = ProEngFactory::NewEngineLC(); TInt activeId( engine->ActiveProfileId() );
通过调用ActiveProfileId()我们可以获取如下返回值:
0 - General 1 - Silent 2 - Meeting 3 - Outdoor 4 - Pager 5 – Offline
如何在Avkon tabs中使用SVG图标
概述:
我们可以在Avkon tab group的每个tab中显示我们自己的SVG图标。这一情况下对SVG文件有一些限制,现在描述如下。
解决方案:
CAknTabGroup::AddTabL()可用来生成一个带自定义SVG图标的tab,只有图标的mask层(如alpha或transparency)呗使用来生成该图表,其他数据被忽略了。
举例来说,现在有一个白色SVG带有如下图案:白色背景上一个黑色椭圆。
<ellipse fill="#FFFFFF" stroke="#000000" stroke-width="5" cx="25" cy="25" rx="20" ry="20"/>
为了让椭圆显示在tab上,填充参数必须修改如下:
<ellipse fill="none" stroke="#000000" stroke-width="5" cx="25" cy="25" rx="20" ry="20"/>.
只有这样修改后,图片的mask才会出现黑色背景和白色椭圆,当该SVG被使用在tab icon上时,就会现实出黑色的椭圆,而其他图片的其他地方都是做透明处理了。
注意,当mask被用来生成icon时,无法在TAB上绘制有色的SVG。
如何同时建立GMS和GPRS连接
概述:
S60第三方程序可能需要在保持GSM通话时提供访问GPRS的能力。
解决方案:
S60设备按基于GSM通话时保持GPRS的能力,分为三个类型。
Class A
可以同时建立GPRS服务和GSM服务(语音,SMS),并同时使用这两者。
这样的设备现在包括S60第三版机型(Nokia N73/N80/N91/N93, Nokia E60/E61/E70等)
Class B
可以同时建立GPRS服务和GSM服务(语音,SMS),但只能一次使用一种服务。当进行GSM服务时(通话,短信),则GPRS服务将被暂停,直到GSM服务结束才自动继续下去。
大部分S60第二版机型都在此类中(Nokia N70, Nokia N90, Nokia 6680等)
Class C
只能建立GPRS服务或GMS服务(通话,短信)其中一种,如果要切换服务必须手动控制。
注意:
目前没有一个直接可操控的API来询问当前设置支持GPRS类的能力,大部分S60第三版机器3G(WCDMA)电话都归属于A类,有一个API可用来检查当前电话是否支持WCDMA,代码为:
TBool isSupported = CFeatureDiscovery::IsFeatureSupportedL(KFeatureIdProtocolWcdma);
if (isSupported)
{
// activate the service
}绘制动画图片
概述:
应用程序可以通过ICL(Image Converter Library)使用CImageDecoder类在自定义的UI控件中绘制动画图片,比如GIF动画图片。
解决方案:
ICL允许使用CImageDecoder::Convert()将动画图片(多帧)转换为CFbsBitmap位图机型显示,我们可以通过使用CImageDecoder::FrameCount()获得图片文件的帧数,通过CImageDecoder::FrameInfo(TInt aFrameNumber = 0)返回每帧的信息、
对每帧来说都要调用CImageDecoder::Convert(),这个转换是异步的。每次完成后,完成后将返回一个CFbsBitmap实例。
帧之间的时间间隔可以通过TFrameInfo类获得,通过这些信息,我们可以依次播放CFbsBitmap以产生动画效果。
注意:在S60 2nd中可以使用CPAlbImageViewerBasic来播放动画,但在第三版中已经去除了。
当程序通过HTTP进行下载时无法接通来电
详细描述:
当我们使用HTTP Client API通过GPRS下载内容时会造成来电无法接通。当我们在下载一个大文件室需要考虑到这样的问题,如果有可能的话应该将大文件分割为许多小模块进行下载,因为HTTP的
传输能力很低(HTTP头很大),这时开发者需要平衡传输效率和来电接通的问题。
打开WAP Push信息
创建日期:
在访问Smart Message(BIO)数据时有几种不同的方式,大多数信息类型中,信息内容是存放在附件中,我们可以通过新的附件管理示例(CMsvStore)来访问。
某些情况下,内容是存放在CMsvStore流中的,可以通过public stream UID来读取
(定义在pushentry.h)
/** UID for the WAP Push MTM. */
const TUid KUidMtmWapPush = {0x10009158};
/** UID for WAP Push SI messages. */
const TUid KUidWapPushMsgSI = {0x10009159};
/** UID for WAP Push SL messages. */
const TUid KUidWapPushMsgSL = {0x1000915A};
/** UID for WAP Push multipart messages. */
const TUid KUidWapPushMsgMultiPart = {0x1000915B};
/** UID for WAP Push unknown-type messages. */
const TUid KUidWapPushMsgUnknown = {0x1000915C};从缺省堆中分配内存单元
描述:
一般来说内存单元是从当前线程堆中分配的,但有时无法这样做,特别当要分配的内存单元很大时。
我们可以生成一个新的堆,从它那里获取我们需要的内存单元,示例如下:
//Try to create a heap in a local chunk.
//The minimum length of the heap is 10M and the maximum length is 20M
RHeap *pChunkHeap = UserHeap::ChunkHeap(NULL, 10000*1024, 20000*1024);
if (RHeap)
{
void *mallocBuffer = NULL;
TInt size = 8000*1024; //Try to allocate a 8M memory cell
mallocBuffer = pChunkHeap->Alloc(size);
if (mallocBuffer )
{
//... Use this memory cell ...
}
}当N93翻转屏幕时动态更新的CBA在多视图程序中无法显示的问题
描述:
如何产生:
肖像模式->View1->风景模式(设备翻转)->切换到View->肖像模式(设备翻转)->View2中的CBA动态更新
但无法显示
TKeyResponse Ctest1Container2::OfferKeyEventL(const TKeyEvent& aKeyEvent,TEventCode aType)
{
if(aKeyEvent.iCode == EKeyOK)
{
if(iCba == R_AVKON_SOFTKEYS_OPTIONS_BACK)
{
CEikButtonGroupContainer* cba = CEikButtonGroupContainer::Current();
cba->SetCommandSetL(R_AVKON_SOFTKEYS_CANCEL);
cba->MakeVisible(EFalse); //Add this line to the source code
cba->DrawNow();
cba->MakeVisible(ETrue); //Add this line to the source code
//CEikonEnv::Static()->InfoWinL(_L("info"), _L("hi"));
iCba = R_AVKON_SOFTKEYS_CANCEL;
}
else
{
CEikButtonGroupContainer* cba = CEikButtonGroupContainer::Current();
cba->SetCommandSetL(R_AVKON_SOFTKEYS_OPTIONS_BACK);
cba->MakeVisible(EFalse); //Add this line to the source code
cba->DrawNow();
cba->MakeVisible(ETrue); //Add this line to the source code
//CEikonEnv::Static()->InfoWinL(_L("info"), _L("hi"));
iCba = R_AVKON_SOFTKEYS_OPTIONS_BACK;
}
return EKeyWasConsumed;
}
return EKeyWasNotConsumed;
}描述:
一般来说如果将N93的摄像头进行翻转操作,则当前程序会切换到后台,而摄像机程序会出现在前台。
但有时为了防止这样的情况发生,我们可以通过如下方式来操作:
MCoeForegroundObserver::HandleLosingForeground()
{
const TUid KNativeCameraAppUID = { 0x101ffa86}; //The UID of the native camera application
TUid id( KNativeCameraAppUID);
TApaTaskList taskList( CEikonEnv::Static()->WsSession() );
TApaTask task = taskList.FindApp( id );
if ( task.Exists() ) //If the native camera application is running
{
RWsSession WsSession = CCoeEnv::Static()->WsSession();
TWsEvent event;
TInt ForegroundWinGroup = WsSession.GetFocusWindowGroup();
if (task.WgId()==ForegroundWinGroup) //If the native camera application is on the foreground
{
const TUid KCurrentAppUID = { 0x20004A79 }; //The UID of current runing application
TUid thisid( KCurrentAppUID );
TApaTaskList taskList1( CEikonEnv::Static()->WsSession() );
TApaTask task1 = taskList1.FindApp( thisid );
if ( task1.Exists() )
{
task1.BringToForeground();
}
}
}
}浏览器控件API无法显示Flash内容
描述:
第三方程序使用Browder Control API,可以显示HTML内容,但如果页面包含有Flash动画,则无法被正确显示,如何配置才能显示出Flash内容呢?
解答:
当前Adobe的Flash播放插件只为Nokia应用程序设计(通过VendorID检测),对其他程序来说,调用插件将返回NULL。无论你使用Netscapge Plug-in API或Browser Control API时,都会出现这样的情况。
使用document handler拷贝或移动未被识别文件时发生的问题
创建日期:
当你使用CDocumentHandler::CopyL()或MoveL()或SilentMoveL()时,被操作文件MIME类型不在下表中的话,那目标文件夹将会是一个临时目录
• image/vnd.nokia.ota-bitmap • image/x-ota-bitmap • application/vnd.nokia.ringing-tone • audio/* • image/* • video/* • application/vnd.rn-realmedia • application/sdp
当CDocumentHandler实例被删除后,那拷贝或移动的文件也将在临时目录中被删除,这可能会导致无意删除行为,特别是在移动文件时。
解决方案:
当使用CDocumentHandler进行拷贝或移动文件操作时,非上述列表类型文件是不推荐使用该方法的。
PathInfo类有个方法叫OthersPath()可用来返回一般内容的路径。
S60 3rd Edition和S60 3rd Edition, FP1中不同的浏览器UID
在启动S60第三版中启动web浏览器打开特定URL的方法无法在S60第三版, FP1设备上完成(如Nokia N95)
这是因为S60第三版设备(如N73)有两个浏览器:“服务”和“网络”
“服务”的UID为0x10008D39而“网络”的UID为 0x1020724D
在第三版FP1设备(如N95)上,只有一个浏览器,UID为0x10008D39
为了能在FP1设备上工作,你必须将0x1020724D转换为0x10008D39
const TUid KOSSBrowserUidValue = {0x10008D39};详细描述:
==概述==
当你绘制一个控件(如list box, grid, editor等)时会需要使用scroll bar,但这时其背景可能会保持白色。这种情况一般发生在Container没有传递一个正确的对象(context-specific skin parameters)到它的子控件中造成的。完成container类的CCoeControl::MopSupplyObject()方法会帮助子控件拥有正确的皮肤绘制,并且保证控件和他们父类之间的对象链表设置正确。
更多信息可以参考SDK文档中的MObjectProvider和CCoeControl::SetMopParent()部分
==解决方案==
要正确绘制scroll bar的背景,需要如下:
'''首先'''在从CCoeControl派生的view class的构造函数中加入如下代码:
CAknsBasicBackgroundControlContext*
iSkinContext = CAknsBasicBackgroundControlContext::NewL(
KAknsIIDQsnBgAreaMainAppsGrid,
iAvkonAppUi->ApplicationRect(),
EFalse );'''然后'''实现MopSupplyObject()如下:
TTypeUid::Ptr CMyCustomGridAppView::MopSupplyObject( TTypeUid aId )
{
if( aId.iUid == MAknsControlContext::ETypeId && iSkinContext != NULL )
{
return MAknsControlContext::SupplyMopObject( aId, iSkinContext );
}
return CCoeControl::MopSupplyObject( aId );
}如何定制一个list box
详细描述:
==概述==
开发者可能需要根据自己的需求定制一个list box,这个提供一个示例,从一个double style list box中去除dotted column line.
==解决方案==
我们需要重载list box的item drawer方法,下面这个示例定义了一个double number style list box.
class CDSListItemDrawer : public CFormattedCellListBoxItemDrawer
{
public:
CDSListItemDrawer( MTextListBoxModel* aTextListBoxModel,
const CFont* aFont,
CFormattedCellListBoxData* aFormattedCellData );
void DrawItemText( TInt aItemIndex, const TRect &aActualItemRect,
TBool aItemIsCurrent, TBool aViewIsEmphasized,
TBool aItemIsSelected) const;
void SetColour( const TRgb& aTextForeground,
const TRgb& aTextBackground,
const TRgb& aHighlightForeground,
const TRgb& aHighlightBackground );
private: // data
TRgb iTextForegroundColour;
TRgb iTextBackgroundColour;
TRgb iHighlightForegroundColour;
TRgb iHighlightBackgroundColour;
const CFont* iPersistentFont;
CFormattedCellListBoxData* iCellData;
TInt iScrollOffset;
};
/*******************************************************************/
// A list box class whose only responsibility is to look after a CDSListItemDrawer.
class CDSListBox : public CAknDoubleNumberStyleListBox
{
public:
CDSListBox( const CFont* aFont,
CFormattedCellListBoxData* aFormattedCellListBoxData );
void SetScrollFrame();
void FindCellSize();
protected:
virtual void CreateItemDrawerL();
virtual CListBoxView* MakeViewClassInstanceL();
private:
const CFont* iFont;
CFormattedCellListBoxData* iFormattedCellListBoxData;
};
/****************************************************************/
The .cpp source file should have the following implementation.
CDSListItemDrawer::CDSListItemDrawer( MTextListBoxModel* aTextListBoxModel,
const CFont* aFont,
CFormattedCellListBoxData* aFormatedCellData )
: CFormattedCellListBoxItemDrawer( aTextListBoxModel, aFont, aFormatedCellData ),
iPersistentFont( aFont )
{
}
void CDSListItemDrawer::DrawItemText( TInt aItemIndex,
const TRect &aItemTextRect,
TBool aItemIsCurrent,
TBool aViewIsEmphasized,
TBool aItemIsSelected) const
{
Gc()->SetBrushStyle( CGraphicsContext::ESolidBrush );
Gc()->SetBrushColor( KRgbWhite );
Gc()->Clear( aItemTextRect );
TPtrC itemText = iModel->ItemText( aItemIndex );
TInt textLength = itemText.Length();
TInt tabPosition1 = itemText.Locate( '\t' );
TInt tabPosition2 = itemText.Mid(tabPosition1+1).Locate( '\t' );
const CFont* font = Font( aItemIndex );
Gc()->SetPenStyle( CGraphicsContext::ESolidPen );
Gc()->SetBrushStyle( CGraphicsContext::ESolidBrush );
TRgb textColour;
TRgb bgColour;
if ( aItemIsCurrent )
{
textColour = iHighlightForegroundColour;
bgColour = iHighlightBackgroundColour;
}
else
{
textColour = iTextForegroundColour;
bgColour = iTextBackgroundColour;
}
Gc()->UseFont( iPersistentFont );
// Set the item's background.
Gc()->SetBrushStyle( CGraphicsContext::ESolidBrush );
Gc()->SetBrushColor( bgColour );
Gc()->SetPenColor( textColour );
TRect textRect( TPoint( aItemTextRect.iTl.iX, (aItemTextRect.iTl.iY-10) ),
aItemTextRect.iBr );
textRect.iBr.iY -= aItemTextRect.Height() / 2;
if ( !font )
{
font = CEikonEnv::Static()->LegendFont();
}
Gc()->UseFont(font);
TInt baseline = ( textRect.iBr.iY
- textRect.iTl.iY
- font->HeightInPixels() ) / 2 + font->AscentInPixels();
Gc()->DrawText( itemText.Mid( 0,tabPosition1 ),
textRect, baseline-20, CGraphicsContext::ELeft);
Gc()->DrawText( itemText.Mid( tabPosition1+1, tabPosition2 - tabPosition1 ),
textRect, baseline, CGraphicsContext::ELeft, 0);
font = CCoeEnv::Static()->NormalFont();
Gc()->UseFont(font);
textRect.Move( 0, aItemTextRect.Height() / 2 );
baseline = ( textRect.iBr.iY
- textRect.iTl.iY
- font->HeightInPixels() ) / 2 + font->AscentInPixels();
Gc()->DrawText( itemText.Mid( tabPosition2,textLength-tabPosition2 ),
textRect, baseline, CGraphicsContext::ELeft, 1);
}
void CDSListItemDrawer::SetColour( const TRgb& aTextForeground,
const TRgb& aTextBackground,
const TRgb& aHighlightForeground,
const TRgb& aHighlightBackground)
{
iTextForegroundColour = aTextForeground;
iTextBackgroundColour = aTextBackground;
iHighlightForegroundColour = aHighlightForeground;
iHighlightBackgroundColour = aHighlightBackground;
iBackColor = iTextBackgroundColour;
}
CDSListBox::CDSListBox( const CFont* aFont,
CFormattedCellListBoxData* aFormattedCellListBoxData )
{
iFont = aFont;
iFormattedCellListBoxData=aFormattedCellListBoxData;
}
void CDSListBox::CreateItemDrawerL()
{
iItemDrawer = new (ELeave) CDSListItemDrawer(
Model(),
iFont,
iFormattedCellListBoxData );
}
CListBoxView* CDSListBox::MakeViewClassInstanceL()
{
return new (ELeave) CListBoxView();
}
void CDSListBox::SetScrollFrame()
{
}
void CDSListBox::FindCellSize()
{
}
/******************************************************************/
The calling function from a CCoeControl should contain:
SetExtentToWholeScreen(); // Drawing it to the whole screen
iTextForegroundColour = KRgbGreen;
iTextBackgroundColour = KRgbRed;
iHighlightForegroundColour = KRgbWhite;
iHighlightBackgroundColour = KRgbBlue;
iListItems = new (ELeave) CDesC16ArrayFlat( 2 );
const CFont *font;
_LIT( KTextFont, "LatinBold13" );
CFont* myFont;
CFormattedCellListBoxData* myFormattedCellListBoxData;
CGraphicsDevice* screenDevice = CEikonEnv::Static()->ScreenDevice();
TFontSpec textFontSpec( KTextFont, 200 );
screenDevice->GetNearestFontInTwips( myFont,textFontSpec );
myFormattedCellListBoxData = CFormattedCellListBoxData::NewL();
iListBox1 = new (ELeave) CDSListBox( myFont, myFormattedCellListBoxData );
iListBox1->ConstructL( this, 0 );
iListBox1->SetRect( TRect( 0, 0, 3000, 3000 ) );
CDSListItemDrawer* drawer = (CDSListItemDrawer*) iListBox1->View()->ItemDrawer();
drawer->SetColour( iTextForegroundColour,
iTextBackgroundColour,
iHighlightForegroundColour,
iHighlightBackgroundColour );
CColumnListBoxData* columnData=CColumnListBoxData::NewL();
columnData->SetControl( iListBox1 );
TInt columnSize;
columnData->ColumnWidthPixel( columnSize );
_LIT( KListItemFormat, "%d\t%S\t%S" );
_LIT( KName1, "Name11" );
_LIT( KContactNo,"123" );
_LIT( KName2,"Name22" );
_LIT( KContactNo2,"789" );
TBuf<40> item;
MDesCArray* itemList = iListBox1->Model()->ItemTextArray();
CDesCArray* itemArray = (CDesCArray*) itemList;
TBuf<30> NameBuf;
TBuf<30> ConBuf;
// add first item in the array
NameBuf.Copy( KName1 );
ConBuf.Copy( KContactNo );
TInt id = 1;
item.Format( KListItemFormat, id, &NameBuf, &ConBuf );
itemArray->AppendL( item );
// add second item in the array
NameBuf.Zero();
ConBuf.Zero();
NameBuf.Copy( KName2 );
ConBuf.Copy( KContactNo2 );
item.Format( KListItemFormat, id, &NameBuf, &ConBuf );
itemArray->AppendL( item );
NameBuf.Zero();
ConBuf.Zero();
iListBox1->SetRect( TRect( TPoint( 0,0 ),
TPoint( 20000, 20000 )) );
iListBox1->ActivateL();
iListBox1->HandleItemAdditionL();
DrawNow();注意:这里仅仅是示例,没有包括完整代码。为了正确绘制,相应元素如text, icons, highlight等都需要计算正确,这些需要花一番工夫。
通过CVideoRecorderUtility录制更大尺寸视频
详细描述:
如果想要录制尺寸超过QCIF(176x144)的视频,那就要使用MPEG-4格式("video/mp4v-es")。
_LIT8(KMimeTypeMPEG4VSPL3, "video/mp4v-es; profile-level-id=3");
// MPEG-4 Visual Simple Profile Level 3
_LIT8(KMimeTypeMPEG4VSPL4, "video/mp4v-es; profile-level-id=4");
// MPEG-4 Visual Simple Profile Level 4我们可以在支持MPEG-4 VSP Level4(Visual Simple Profile Level 4)的设备上捕捉到30fps的VGA(640x480)视频,大部分S60第三版手机至少都支持VSP Level 3,即CIF(352x288)30fps的视频。
如:
iRecorder->OpenFileL( iFilename,
iCameraHandle,
iControllerUid,
iFormatUid,
KMimeTypeMPEG4VSPL4,
KMMFFourCCCodeAAC );
在MvruoOpenComplete回调函数中,capture size, frame rate以及bit rate应该在CVideoRecorderUtility::Prepare()前设置好,如下示例:
void CMyVideoRecorder::MvruoOpenComplete( TInt aError )
{
if( aError == KErrNone )
{
// instead of using TRAP_IGNORE, proper error checking should be done
TRAP_IGNORE( iRecorder->SetVideoFrameSizeL( iResolution ));
TRAP_IGNORE( iRecorder->SetVideoFrameRateL( iFps ));
TRAP_IGNORE( iRecorder->SetVideoBitRateL( KMMFVariableVideoBitRate ));
...
iRecorder->Prepare();我们可以通过CCamera获得当前设备所支持最大的视频capture size和frame rate
TInt sizeIndex = 0, rateIndex = 0;
iCamera->EnumerateVideoFrameSizes( iResolution, sizeIndex, CCamera::EFormatYUV420Planar );
iCamera->EnumerateVideoFrameRates( iFps, rateIndex, CCamera::EFormatYUV420Planar, sizeIndex );详细描述:
下列代码演示了如何使用一个可以显示多行信息的询问对话框:
_LIT(KTxtApplicationName, "Application Title");
HBufC* sMessage =
StringLoader::LoadLC( R_MESSAGE );
HBufC* sTitle = HBufC::NewLC( KTxtApplicationName().Length() );
sTitle->Des().Append( KTxtApplicationName );
CAknMessageQueryDialog* dialog = new ( ELeave ) CAknMessageQueryDialog();
CleanupStack::PushL( dialog );
dialog->PrepareLC( R_AVKON_MESSAGE_QUERY_DIALOG );
dialog->QueryHeading()->SetTextL( *sTitle );
dialog->SetMessageTextL( *sMessage );
dialog->RunLD();
CleanupStack::Pop(); // dialog
CleanupStack::PopAndDestroy(2); // sTitle, sMessage要显示在对话框中的信息是从资源文件加载的,我们在.rss文件中需要有如下定义:
#define qtn_message “First Line \nSecond Line”
RESOURCE TBUF r_message
{
buf = qtn_message;
}如何获取当前函数的名称
详细描述:
有时候debug时为了记录相关信息,我们需要知道当前函数的名称,这时可以通过__func__来获取。
void LogFunctionName(const char* name)
{
RDebug::Printf("current function: %s\n", name);
}现在,我们可以通过如下语句打印出函数名:
LogFunctionName(__func__);

2468

被折叠的 条评论
为什么被折叠?



