views:

418

answers:

2

I am amazed at how well the native Symbian components are implemented. One of them is CAknSlider. CAknSlider is a control that has a slider that users can use to slide it along a bar whose orientation can be vertical or horizontal.

Now when you slide the slider the sliding is very smooth and does not flicker. But if for some reason I were to implement a custom slider control I would not get it as neat as CAknSlider.

So my question is how can I figure out how CAknSlider is implemented under the hood. I want to implement a custom slider for my radio application to control the volume of audio stream.

Any idea how should I go about it.


[EDIT: In response to the comment from laalto]

The CAknSlider control is often implemented as a setting item in the settings screen.

I have never seen it implemented as a component control within a compound control container ( like CCoeControl or CAknView ). This is what I have tried so far:

First I created a resource file describing the slider control like below:

RESOURCE SLIDER r_volume_slider
{
 layout=EAknCtSlider;
 minvalue=0;
 maxvalue=10;
 step=1;
 valuetype=EAknSliderValuePercentage;
 minlabel="mute";
 maxlabel="full";
}

Then I am using the resource file in my source to create the slider like below:

void CVolumePopupAppView::ConstructL(const TRect& aRect)
{
// Create a window for this application view
CreateWindowL();

InitComponentArrayL( );
iSlider = new ( ELeave ) CAknSlider( );
TResourceReader reader;
iEikonEnv->CreateResourceReaderLC( reader, R_VOLUME_SLIDER );

iSlider->ConstructFromResourceL( reader );
CleanupStack::PopAndDestroy ( );
iSlider->SetContainerWindowL( *this );
iSlider->SetParent( this );

Components().AppendLC( iSlider );

CleanupStack::Pop ( iSlider );

// Set the windows size
SetRect(aRect);

// Activate the window, which makes it ready to be drawn
ActivateL();
}

Now here is the comparison between the CAknSlider as a setting item ( Screenshot1 ) and the CAknSlider that gets created by the above described technique ( Screenshot2 ). Notice that the one I create does not have a percentage value indicator and the minimum and maximum text labels even though I specified them in the resource. The look and feel is also pathetic.

Please help.

+2  A: 

There are lots of techniques to avoid flicker, from double-buffering the whole screen down to more simple optimizations, like only re-drawing the parts of the control that have actually changed. Having appropriate rectangles pre-drawn to blit over where the slider was and its next step is probably the easiest way to do it efficiently.

To find out exactly how CAknSlider does it, you can either: 1) Wait for the relevant package in the Symbian Foundation platform to go open source (EPL) - should sometime in the next 12 months, or 2) Join the Symbian Foundation and get access to the source now

EDIT: (In response to request for more details on graphics optimisation)

Most commonly flicker is caused by redrawing the whole control. I have implemented (via a porting project) some custom controls that don't flicker here:http://developer.symbian.com/main/documentation/porting/#linux2 There's even something a bit like a slider. This example is far from ideal, it doesn't have pre-drawn rectangles for blitting but the graphics are very simple lines and filled rectangles. The concept of overwriting just the changed part is identical though. To blit pre-drawn sections. Draw the backgroud of the slider to an off-screen bitmap and do the same with the movable part of the slider. When the slider is moved, erase the movable part by doing a BitBlt() from the off-screen background (of only the part that needs to be erased) and then BitBlt() the movable part into the new position.

Does that make sense?

Mark Wilcox
BTW, you may find a slider for a volume control a little disappointing because the underlying audio adaptation implementation on most Nokia devices only has 10 discrete volume levels, even though the API allows you to set an arbitrary value between 0 and MaxVolume.
Mark Wilcox
Mark, in your response you mentioned "having pre-drawn rectagles to blit..." as the simpliest optimization technique. Could you point me to an example application that uses this technique or help me by explaining how to do it myself.
ardsrk
+1  A: 

You need CAknSlider? steal it! :) CAknSliderSettingPage do everything for us. We, just use that.

iSettingPage = new(ELeave) CAknSliderSettingPage(R_SLIDER_PAGE, iValue); iSettingPage->ConstructL();

iSettingPage->SetSize(iSettingPage->MinimumSize());

TInt CCustomColorPalette::CountComponentControls() const { return 1; }

CCoeControl* CCustomColorPalette::ComponentControl( TInt aIndex ) const { return iSettingPage->SliderControl(); }

Valentin, nice technique. I will try it and let you know what I got. Thanks
ardsrk