Controls are drawn using the drawing functions provided by a
graphics context, which is part of the window
server, not of the control framework itself. A graphics context can be obtained
using CCoeEnv::SystemGc()
. This graphics context is used for most
drawing of controls, and is known as the system graphics
context.
There are two different circumstances in which controls are drawn:
when the window server generates a redraw event, because the contents of the control on the screen are no longer up-to-date: for example, because another window, which was obscuring the control, has moved or disappeared
when the application requests the control to draw itself, either because some application data has changed or because the control is appearing on the screen for the first time
Whenever the window server generates a redraw event, the control
framework function HandleRedrawEvent()
is called. This calls
Draw()
, a private virtual member function of
CCoeControl
, which is implemented by each concrete control class
and draws the control on the screen.
Redraw events are generated for windows, not for
controls, so HandleRedrawEvent()
is called on a window-owning
control, even if only one of its components requires a redraw. However, this
doesn't mean that all the components of the window-owning control are redrawn:
the redraw event contains a rectangle which indicates the area of the screen
that needs redrawing, and HandleRedrawEvent()
calls
Draw()
only on controls whose extent intersects the redaw
rectangle. The redraw rectangle is also passed to the control's
Draw()
function, so that the control may redraw only the region
required.
When HandleRedrawEvent()
calls Draw()
on
a compound control, it also calls Draw()
for all its
non-window-owning component controls, and all their components, recursively.
Unlike DrawNow()
, HandleRedrawEvent()
doesn't call
Draw()
on components that are window-owning, because if they need
redrawing they will receive their own redraw event from the window
server.
Applications need to request a control to draw itself when either some application data has changed or the control is appearing on the screen for the first time. The way to do application-initiated drawing depends on whether the whole control, or only part of the control, needs drawing.
An application can request a control to draw the whole of itself
by calling either CCoeControl::DrawNow()
or
CCoeControl::DrawDeferred()
. DrawNow()
calls the
control's Draw()
function directly; DrawDeferred()
invalidates the area of screen containing the control, resulting in a window
server-initiated redraw. DrawDeferred()
should be preferred in
those cases where the application may generate repeated draw events for a
control, not as a result of a user action. Note, however, that the preferred
programming style is to decouple changes in state from drawing actions.
When DrawNow()
is called on a compound control, the
control framework also calls DrawNow()
on all its component
controls (both non-window-owning and window-owning). Applications typically
call DrawNow()
on their top-level
control when initialisation is complete, to cause the
application to be displayed.
In some cases an application will need to draw only part of a control in response to changes in application data. This is often the case if the control displays a large amount of data, because a partial redraw reduces processing and improves performance.
As an example, consider a word processor when the user deletes a character from the end of a line. To draw the entire contents of the document window the word processor must carry out extensive calculations to position text on the screen, taking account of line-wrapping, tab positions, font sizes, and so on. In the case of a character being deleted from the end of a line, however, all that is required is to draw the area of the screen that was occupied by the deleted character.
Assuming that the application view (in this case the word processor’s document window) is implemented in the control framework as a single control, the application program should do the following:
implement member functions for drawing parts of the screen in various granularities (e.g. a single character, a single line, a single paragraph, etc.)
call these functions, instead of DrawNow()
, when
changes in application data occur
Note that these drawing functions must activate the graphics context before it is drawn to, and deactivate it after drawing is complete.