Wiley.Symbian.OS.C.plus.plus.for.Mobile.Phones.Aug.2007 (779890), страница 92
Текст из файла (страница 92)
If the window server marked application A’s window as valid inEndRedraw(), the window server would not know that it needs tobe redrawn. Instead, the window server marks A’s window as valid inBeginRedraw() so that, by the end of a sequence like this, the windowis correctly marked invalid and can be redrawn.You might think that this sequence of events would be rare, but it ispossible, so the system has to address it properly.RedrawingYou should now find it pretty easy to understand how redrawing works.When the window server knows that a region of a window is invalid, itsends a redraw message to the window’s owning application, specifyingthe bounding rectangle of the invalid region. This is picked up by CONEand handled using the following code:EXPORT_C void CCoeControl::HandleRedrawEvent(const TRect& aRect) const{ActivateGc();Window().BeginRedraw(aRect);Draw(aRect);DrawComponents(aRect);Window().EndRedraw();DeactivateGc();}This code has exact parallels to the code we saw in DrawOneTileNow(): the ActivateGC() and BeginRedraw() calls are neededto set everything up correctly.
However, CONE does not need to callInvalidate() here, because the whole point of the redraw is thata region is already known to be invalid. In fact, if CONE did callSHARING THE SCREEN513Invalidate() on the rectangle, it would potentially extend the invalidregion, which would waste processing time.CONE draws the control using Draw(), which is passed the boundingrectangle, and then draws every component owned by the control usingDrawComponents():void CCoeControl::DrawComponents(const TRect& aRect) const{const TInt count = CountComponentControls();for(TInt ii = 0; ii < count; ii++){const CCoeControl* ctrl = ComponentControl(ii);if(!(ctrl->OwnsWindow()) && ctrl->IsVisible()){TRect rect;const TRect* pRect = (&aRect);if(!((ctrl->Flags()) & ECanDrawOutsideRect)){rect = ctrl->Rect();rect.Intersection(aRect);if(rect.IsEmpty())continue;pRect = (&rect);}ResetGc();ctrl->Draw(*pRect);ctrl->DrawComponents(*pRect);}}}CONE redraws every visible lodger component whose rectangle intersects the invalid rectangle, and then its components in turn.
CONE adjuststhe bounding invalid rectangle appropriately for each component control.CONE also makes an allowance for a rare special case: controls thatcan potentially draw outside their own rectangle.Default settings are assured here: the call to ActivateGc() setsdefaults for the window-owning control that was drawn first; later calls toResetGc() ensure that components are also drawn with default settings.The loop above does not need to draw window-owning componentsof the window-owning control that received the original redraw request.This is because the window server sends redraw messages to such controlsin any case, in due time. (In fact, it usually sends them first as it tries tosend redraw events in a front to back z-order on all the windows of aparticular client.)514GRAPHICS FOR DISPLAYYou can see again how lodger components promote system efficiency.For each component that is a lodger control (rather than a windowowning control), you avoid the client–server message and the calls toactivate and begin the redraw.
All you need is a single ResetGc(),which occupies a single byte in the window server’s client-side buffer.Support for Flicker-free DrawingAs an application programmer, you should be aware of two aspects ofthe window server that promote flicker-free drawing.First, the window server clips drawing down to the intersection ofthe invalid region and the rectangle passed to BeginRedraw(), so ifyour drawing code tends to flicker, the effect is confined to the areabeing redrawn. You can exploit this in some situations. Imagine thatwe want to implement a cursor-movement function, but do not wantto alter the drawing functions of COandXAppView and COandXTile.We could write a DrawTwoTilesNow() function that accepted the(x, y) coordinates of two tiles to be drawn, enabling us to calculateand invalidate only those two rectangles.
We could then activate agraphics context and BeginRedraw() on the whole board area, callingDrawNow() on the COandXAppView class. The window server wouldclip drawing activity to the two tiles affected, eliminating flicker anywhereelse. It is not a very effective flicker-free solution, but in some cases itmight just make the difference.Secondly, the window server’s client-side buffer provides useful flickerfree support.
For a start, it improves overall system efficiency, so thateverything works faster and flickers are therefore shorter. Also, it causesdrawing commands to be batched up and executed rapidly by the windowserver using the BITGDI and a constant clipping region. In practice, thismeans that some sequences of draw commands are executed so fast that,even if your implementation flickers by nature, no one sees the problem,especially on high-persistence LCD displays. The key here is to confinesequences that cause flicker to only a few consecutive draw commands,so that they are all executed as part of a single window-server buffer.Finally, and most obviously, the use of lodger controls helps heretoo, because it means the window-server buffer contains only a singleResetGc() command between controls, rather than redrawing anddeactivating the graphics context for one control, followed by activatingthe graphics context and redrawing the next control.17.6Support for Drawing in CCoeControlNow is a good time to summarize the drawing-related features ofCCoeControl that we have seen so far.SUPPORT FOR DRAWING IN CCOECONTROL515First and foremost, a control is a rectangle that covers all or part of awindow.
All concrete controls are (ultimately) derived from the abstractbase class CCoeControl. Various relationships exist between controls,other controls, and windows:• a control can own a window or be a lodger• a control may have zero or more component controls: a control’scomponents should not overlap and should be contained entirelywithin the control’s rectangle• a control is associated with precisely one window, whether as thewindow-owning control or as a lodger• all lodgers are components of some control (ultimately, the componentcan be traced to a window-owning control)• component controls can own a window (say, for a small backed-upregion).Controls contain support for drawing, application-initiated redrawing,and system-initiated redrawing.
Applications request controls to drawusing the DrawNow() function; the window server causes controls todraw when a region of the control’s window becomes invalid. In eithercase, Draw() is called to handle the drawing. Functions exist to activate,deactivate and reset a graphics context for use on the control’s window.Control EnvironmentEach control contains a pointer to the control environment, which anycontrol can reach by specifying ControlEnv() (public) or iCoeEnv(protected):class CCoeControl : public CBase{public:...inline CCoeEnv* ControlEnv() const;...protected:CCoeEnv* iCoeEnv;...};From a derived control or app UI class, including your own application’s app UI, you can use iCoeEnv to get at the CCoeEnv.
If you havea pointer to a control or app UI, you can use its public ControlEnv()function. If you have access to neither of these things, you can use thestatic function CCoeEnv::Static(), which uses thread-local storage516GRAPHICS FOR DISPLAYCCoeEnvCCoeControlStatic()FsSession()NormalFont()Flush()AllocReadResourceL()CreateResourceReaderLC()iCoeEnvCoeEnv()CCoeAppUiiCoeEnvCoeEnv()Figure 17.11 The control environment(TLS) to find the current environment.
Since TLS isn’t particularly quick,you can store a pointer somewhere in your object for faster access, if youneed to do this frequently.The control environment’s facilities (see Figure 17.11) include:• access to the basic GUI resources: window-server session, windowgroup, screen device and graphics context• a permanently-available file-server session, available via FsSession()• a font for drawing to the screen (10-point sans serif), available viaNormalFont()• a function to Flush() the window-server buffer and, optionally, waitfor a short period• convenience functions for creating new graphics contexts and fontson the screen device• support for multiple resource files and functions to read resources (seeChapter 13).See the definition of CCoeEnv in coemain.h for the full list.Window-owning and Lodger ControlsA control may either own a window or be a lodger.
As illustrated inFigure 17.12, a window-owning control ‘has-a’ window; a lodger simply‘uses-a’ window.Throughout the lifetime of a control, an iWin member points to adrawable window. The drawable window may be standard (RWindow) orbacked-up (RBackedUpWindow) – RDrawableWindow is a base classfor both of these.You can call a CCoeControl function during the second-phaseconstructor of a concrete control class, to indicate whether it isSUPPORT FOR DRAWING IN CCOECONTROLWindow owningcontrolLodgercontrolCCoeControlCCoeControl517RWindowFigure 17.12 Basic control typeswindow-owning or a lodger. The functions for specifying and testingthe window are:class CCoeControl : public CBase{public:...IMPORT_C virtual void SetContainerWindowL(const CCoeControl& aContainer);IMPORT_C void SetContainerWindow(RWindow& aWindow);IMPORT_C void SetContainerWindow(RBackedUpWindow& aWindow);...inline RDrawableWindow* DrawableWindow() const;...IMPORT_C TBool OwnsWindow() const;IMPORT_C TBool IsBackedUp() const;...protected:...inline RWindow& Window() const;inline RBackedUpWindow& BackedUpWindow() const;IMPORT_C void CloseWindow();IMPORT_C void CreateWindowL();IMPORT_C void CreateWindowL(const CCoeControl* aParent);IMPORT_C void CreateWindowL(RWindowTreeNode& aParent);IMPORT_C void CreateWindowL(RWindowGroup* aParent);IMPORT_C void CreateBackedUpWindowL(RWindowTreeNode& aParent);IMPORT_C void CreateBackedUpWindowL(RWindowTreeNode& aParent,TDisplayMode aDisplayMode);...protected:CCoeEnv* iCoeEnv;...private:RDrawableWindow* iWin;...};The CreateWindowL() functions cause a new window – eitherstandard, or backed-up – to be created.518GRAPHICS FOR DISPLAYThe SetContainerWindow() functions tell the control to use anexisting standard or backed-up window.