Wiley.Symbian.OS.C.plus.plus.for.Mobile.Phones.Aug.2007 (779890), страница 88
Текст из файла (страница 88)
They are declared in gdi.h:virtual void MoveTo(const TPoint& aPoint) = 0;virtual void MoveBy(const TPoint& aVector) = 0;virtual void Plot(const TPoint& aPoint) = 0;virtual void DrawArc(const TRect& aRect, const TPoint& aStart,const TPoint& aEnd) = 0;virtual void DrawLine(const TPoint& aPoint1, const TPoint& aPoint2) = 0;virtual void DrawLineTo(const TPoint& aPoint) = 0;virtual void DrawLineBy(const TPoint& aVector) = 0;virtual void DrawPolyLine(const CArrayFix<TPoint>* aPointList) = 0;virtual void DrawPolyLine(const TPoint* aPointList, TInt aNumPoints) = 0;Note that line drawing (including arcs and the last line in a polyline)excludes the last point of the line. As with the specification of TRect, thisis a mixed blessing: sometimes it makes things easier, sometimes harder.If the last pixel were plotted automatically, it would be harder to un-plotit in the cases where this behavior is not desired.
It is easy enough to fixtricky cases by using Plot().Check out the SDK for the interpretation of DrawArc() parameters.THE CGRAPHICSCONTEXT API491DrawPolyLine() starts at the current cursor position. Effectively,DrawPolyLine() uses DrawLineTo() to draw to every point specified.Filled shapesYou can draw several filled shapes: a pie slice, an ellipse, a rectangle,a rectangle with rounded corners or a polygon. These functions use thepen and the brush. Use only the pen to draw an outline; use only thebrush to draw the shape; use both to draw an outlined shape.Here are the functions:virtual void DrawPie(const TRect& aRect, const TPoint& aStart,const TPoint& aEnd) = 0;virtual void DrawEllipse(const TRect& aRect) = 0;virtual void DrawRect(const TRect& aRect) = 0;virtual void DrawRoundRect(const TRect& aRect,const TSize& aCornerSize) = 0;virtual TInt DrawPolygon(const CArrayFix<TPoint>* aPointList,TFillRule aFillRule = EAlternate) = 0;virtual TInt DrawPolygon(const TPoint* aPointList, TInt aNumPoints,TFillRule aFillRule = EAlternate) = 0;The DrawPie() parameters are essentially the same as forDraw Arc().DrawPolygon() connects all the points specified and fills the resulting enclosed region.
Just as for DrawLine(), no relative drawing isused or needed. Intersecting polygons may be drawn, in which case thefill-rule parameter specifies the behavior for regions of even enclosureparity. Check the SDK and the grshell example for details. Unlike theother drawing functions, the DrawPolygon() function can return errors.This is because the parameters can specify an arbitrarily large amount ofdata and memory may need to be allocated to deal with it.BitmapsYou can draw a bitmap at a scale of 1:1 or stretched to fit a rectangle youspecify.
Here are the functions:virtual void DrawBitmap(const TPoint& aTopLeft,const CFbsBitmap* aSource) = 0;virtual void DrawBitmap(const TRect& aDestRect,const CFbsBitmap* aSource) = 0;virtual void DrawBitmap(const TRect& aDestRect, const CFbsBitmap* aSource,const TRect& aSourceRect) = 0;Use the same-size variant for high-performance blitting1 of GUI iconsand the stretch variants for device-independent view code that supports on-screen zooming or printing. If the above functions are called1Blitting is an operation in which several bitmap patterns are combined into one.492GRAPHICS FOR DISPLAYwith the source and the destination containing the same number ofpixels, then they switch to working in a high-performance way.
However, there are functions added to the graphics context classes at theCBitmapContext-level, called BitBlt, that perform one-to-one drawing, which is always fast.TextYou draw text in the current font using the following functions:virtual void DrawText(const TDesC& aString, const TPoint& aPosition) = 0;virtual void DrawText(const TDesC& aString, const TRect& aBox,TInt aBaselineOffset, TTextAlign aHoriz = ELeft,TInt aLeftMrg = 0) = 0;The first (and apparently simpler) function uses the graphics context’sjustification settings, but you shouldn’t call it yourself.
Instead, use FORMif you need to handle properly laid-out text. For general use, use theTRect variant that clips the text to the specified rectangle and paints therectangle background with the current brush.A graphics context has no default font. If a text-drawing function iscalled without a previous call to UseFont(),a panic occurs. The panicis particularly ugly when you are drawing to a CWindowGc because allwindow-drawing functions are batched together and sent to the windowto be executed later.
The window server does not detect the absenceof UseFont() until the buffer is executed – by which time there is nocontext information about where the panic occurred. Always rememberto use DiscardFont() to discard the font after use and so avoid amemory leak.If you do get a panic while drawing and you cannot work out whichof your drawing commands is at fault, then you can use the autoflushing function of the window server.
Calling the function RWsSession::SetAutoFlush(ETrue) means that every drawing commandis sent to the window server as soon as it is generated and so the panicoccurs before the next command is executed. This should only be used asa debugging measure as it greatly reduces the performance of drawing andother code and may increase the amount of flickering that the user sees.17.3Drawing and RedrawingIn a GUI program, all drawing is done to controls, which form all or partof a screen window, as we saw with CHelloWorldAppView::Draw().• The derived control class’s Draw() function is called when drawingis required.DRAWING AND REDRAWING493• Draw() gets a graphics context using SystemGc().• It draws into the area defined by its Rect() function.But it is a bit more complicated than that. Your control must not onlydraw its content, but must also redraw it when the content changes orwhen the system requires a redraw.
System-initiated redraws can occurwhen the window is first constructed or the window, or part of it, isexposed after having been obscured by some other application or adialog box.Application-initiated redraws occur when the application changes thecontrol’s content or the drawing parameters (such as color, scrolling orzoom state) and wants these changes to be shown in an updated display.In addition, there are various other circumstances – partly systeminitiated, partly application-initiated – in which redrawing must occur.For example, dismissing a dialog is application-initiated, but the redrawing of the controls underneath is a system-initiated request and the contentmay have changed due to the user input into the dialog.To understand redrawing properly, we must first review the model–view–controller (MVC) paradigm.
This is a good way to think aboutGUI systems and using MVC concepts makes the subsequent discussionsmuch easier.The Model–View–Controller PatternThe CHelloWorldAppView::Draw() function assumes that the datawe need is already available. It does not interrogate a database or askthe user for the string to draw; it uses the data that’s already there in theiHelloWorld member of the control.This is a standard paradigm in graphics: draw functions simply drawtheir model data, they do not change anything. If you want to changesomething, you use another function and then call a draw function toreflect the update.
In fact, this pattern is so common that it has a name:model–view–controller, often abbreviated simply to MVC.• The model is the data that the program manipulates: in the case of‘Hello World’, it is the string text.• The view is the view through which a user sees the model: in the caseof ‘Hello World’, it is the CHelloWorldAppView class.• The controller is the part of the program that updates the modeland then requests the view to redraw in order to show the updates.In ‘Hello World’, there are no updates and therefore there is nocontroller.
When we come to the Noughts and Crosses application,the controller is more sophisticated because updates may be generatedfrom user interaction.494GRAPHICS FOR DISPLAYModelViewControllerFigure 17.5 Model–view–controller architectureA strict MVC structure has the architecture shown in Figure 17.5.• The model is an independent entity; if the program is file-based, themodel very often corresponds with the program’s persistent data.• The view uses the model, since its job is to draw its content.• The controller coordinates the model and view updates, so it usesboth the model and the view.Depending on the program design, either of the ‘uses-a’ relationshipsmay be upgraded into a stronger ‘has-a’ relationship. The MVC pattern dictates the ‘uses-a’ relationships, but does not force the ‘has-a’relationships specifically.Blurring the MVC distinctionsIn some programs, the distinctions between model, view, and controllerare cleanly reflected by boundaries between classes.
But there are manyreasons for the boundaries to become blurred in practice.The ‘Hello World’ program is so simple that there is no point in makingsuch fine distinctions – the CHelloWorldAppView contains both themodel and the view, and there is no controller at all. The Noughts andCrosses application, on the other hand, is complicated enough to use theMVC structure and greatly benefits from it. However, it turns out that themodel (in the MVC sense) isn’t the same as the COandXEngine class: italso includes some aspects of the COandXController, since knowledgeof whose turn it is is contained in this class. Thus the boundary betweenthe MVC model and controller is not quite the same as that between theC++ engine and controller classes.A sophisticated application uses the MVC pattern again and again – atthe large scale for the whole application and at a smaller scale for eachinteraction within it.