Wiley.Symbian.OS.C.plus.plus.for.Mobile.Phones.Aug.2007 (779890), страница 93
Текст из файла (страница 93)
This should be used by controlsthat are themselves components of a control associated with the samewindow. SetContainerWindowL() tells the control to lodge in anexisting control and, hence, to use an existing window.SetContainerWindowL() is both virtual and potentially leaving.That’s not the best design in Symbian OS; really, it should be neither.You can guarantee that this function won’t leave if it is not overridden,so try to think of this function as not having been designed to beoverridden. A few classes in Uikon use it for purposes that could beachieved by other means.Component ControlsA control can have zero, one or more component controls.
The threefunctions that a control uses to manage its component controls are listedin the following extract from the CCoeControl class definition:class CCoeControl : public CBase{public:...IMPORT_C TInt Index(const CCoeControl* aControl) const;...IMPORT_C virtual TInt CountComponentControls() const;IMPORT_C virtual CCoeControl* ComponentControl(TInt aIndex) const;...};If you want to implement a container control, you can store controlsin any suitable data structure. You override CountComponentControls() to indicate how many controls you have and ComponentControl() to return the control corresponding to each index value,starting from zero.By default, CountComponentControls() returns zero and ComponentControl() panics. These functions work as a pair, so makesure you override them consistently.Index() searches through the component controls one by one, tofind one whose address matches the address passed.
If none is found,Index() returns KErrNotFound.SUPPORT FOR DRAWING IN CCOECONTROL519The CCoeControl base class does not dictate how component controls should be stored in a container.If your container is a fixed-purpose container, such as the Noughts andCrosses application view, which contains only the tiles and one othercontrol, then you can use a pointer to address each component, hardcodeCountComponentControls() to return KNumberOfTiles+1 andput code in ComponentControl() to return the relevant control.On the other hand, if your container is a general-purpose containersuch as a dialog, you may wish to implement a general-purpose array tohold your component controls.Position and Size of ControlsYou can set a control’s position and size:class CCoeControl : public CBase{public:...IMPORT_C void SetExtentL(const TPoint& aPosition, const TSize& aSize);IMPORT_C void SetSizeL(const TSize& aSize);IMPORT_C void SetPosition(const TPoint& aPosition);IMPORT_C void SetRectL(const TRect& aRect);IMPORT_C void SetExtentToWholeScreenL();...IMPORT_C TSize Size() const;IMPORT_C TPoint Position() const;IMPORT_C TRect Rect() const;IMPORT_C TPoint PositionRelativeToScreen() const;...IMPORT_C virtual void SizeChangedL();IMPORT_C virtual void PositionChanged();...IMPORT_C void SetCornerAndSizeL(TCoeAlignment aCorner,const TSize& aSize);IMPORT_C void SetSizeWithoutNotificationL(const TSize& aSize);...protected:...TPoint iPosition;TSize iSize;...};Position and size are stored in iPosition and iSize.
You caninterrogate them with Position(), Size() or Rect() and changethem with SetExtentL(), SetPosition(), SetSizeL() andSetRectL().520GRAPHICS FOR DISPLAYChanging the size of a control can, in rare cases, cause memory tobe allocated, which could fail – so all functions that change size arepotentially leaving. SetPosition() does not change size, so cannotleave.• When a control’s size is changed, its virtual SizeChangedL()function is called.• A position change is notified by PositionChanged().• SetExtentL() calls SizeChangedL() but not PositionChanged() – so think of SizeChangedL() as always notifyinga size change and potentially notifying a position change.• You can use SetSizeWithoutNotificationL() to preventSizeChangedL() being called.• You can set and interrogate the position relative to the owning windowand set the size to the whole screen.
SetCornerAndSizeL() alignsa control’s rectangle to one corner of the screen.Merely resizing a control should not cause extra resources to beallocated, except in the rare kinds of control which might need toallocate resources in Draw() for the extra area. In this case, youshould trap any leaves.Drawing FunctionsThe following extract from the CCoeControl class definition lists thefunctions related to drawing:class CCoeControl : public CBase{public:...IMPORT_C virtual void MakeVisible(TBool aVisible);...IMPORT_C virtual void ActivateL();...IMPORT_C void DrawNow() const;IMPORT_C void DrawDeferred() const;...IMPORT_C TBool IsVisible() const;...protected:...IMPORT_C void SetBlank();...IMPORT_C CWindowGc& SystemGc() const;IMPORT_C void ActivateGc() const;IMPORT_C void ResetGc() const;SPECIAL EFFECTSIMPORT_CIMPORT_CIMPORT_CIMPORT_C...private:...IMPORT_C...};521void DeactivateGc() const;TBool IsReadyToDraw() const;TBool IsActivated() const;TBool IsBlank() const;virtual void Draw(const TRect& aRect) const;You have to activate a control, using ActivateL(), as the final part ofits second-phase construction.
Assuming that the control’s extent is specified and its model is fully initialized by the time ActivateL() is called,this makes the control ready for drawing. You can use IsActivated()to test whether ActivateL() has been called.MakeVisible() sets a control to be visible or not; Draw() is notcalled for invisible controls. IsReadyToDraw() returns ETrue if thecontrol is both activated and visible. SetBlank() is an obscure functionthat only affects controls which do not override Draw(). If you do notSetBlank(), then CCoeControl::Draw() does nothing. If you doSetBlank(), then CCoeControl::Draw() blanks the control.We have already seen that Draw() is the fundamental drawing function.
DrawNow() initiates the correct drawing sequence to draw a controland all its components. DrawDeferred() simply invalidates the control’s extent, so that the window server sends a redraw message. Thisguarantees that a redraw is called on the control at the earliest availableopportunity, rather than forcing it to happen immediately.ActivateL(), MakeVisible() and DrawNow() recurse as appropriate through component controls.SystemGc() returns a windowed graphics context for drawing.ActivateGc(), ResetGc() and DeactivateGc() perform the graphics context preparation functions needed for redrawing. Always usethese functions, rather than directly calling SystemGc.Activate(Window()). They are more convenient and allow control contexts to besupported properly.17.7 Special EffectsThe window server provides many useful special effects to applicationprograms.
These include:• backed-up behind windows• animation• debug keys522GRAPHICS FOR DISPLAY• a control context• scrolling• transparent windows.Backed-up behind windows were discussed in Chapter 15. This sectionexamines each of the remaining cases in turn.The details of these special effects depend on the particular userinterface that you are using. Transparent windows, for example, needsto be supported by the system; even if two devices are running thesame user interface, one may support it and one not.AnimationSometimes, you want to do some drawing where timing is an essentialfeature of the visual effect.
This isn’t really something that fits well intothe MVC paradigm, so we need special support for it.One kind of animation is used to give reassuring cues in the GUI:• if you select OK on a dialog – even using the keyboard – the OKbutton goes down for a short time (0.2 seconds) and then the actiontakes place• if you select a menu item using the pointer, the item appears to flashbriefly, in a subtle way, before the menu bar disappears and yourcommand executes.In both cases, this animation reassures you that what you selected actually happened. Or, just as importantly, it alerts you to the possibility thatsomething you didn’t intend actually happened.
Either way, animation isan extremely important cue: without it, the Symbian OS GUI would feelless easy to use.Animation isn’t the only potential clue that something happened –sound, such as key or digitizer clicks, can be useful too.Using the flush commandAnimation can be achieved very simply. In the case of the dialog buttonanimation, for instance:• draw commands are issued to draw the button in a ‘down’ state• the window server’s client-side buffer is flushed, so that the drawcommands are executedSPECIAL EFFECTS523• the application waits for 0.2 seconds• the dialog is dismissed and the relevant action takes place – in allprobability, this causes more drawing to occur.The key thing here is the flush-and-wait sequence. CONE providesCCoeEnv::Flush(), which takes a time interval specified in microseconds.
The following code therefore implements the flush and wait:iCoeEnv->Flush(200000);The flush is vital. Without it, the window server might not executeyour draw commands until the active scheduler is next called to wait fora new event – in other words, until the processing of the current key hasfinished. By that time, the dialog has been dismissed, so that your drawcommands execute ‘flicker-free’ – just at the point when some flickerwould have been useful!Do not use this command to wait for longer than about 0.2 secondsor it will compromise the responsiveness of your application.