[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
The base class for windowing system is `csComponent'. `csComponent' is a very complex class with a lot of built-in functionality. This allows for easier creation of new components for specific needs. Most `csComponent' methods are virtual, allowing you to override them if needed. There are some basic methods, which are described below. Other methods are described as needed later in this document.
csComponent::Draw()
Each component should know how to paint itself. When windowing system thinks
a part of a component image or entire component image is invalid (for example,
when a window is moved from the top of other components), it adds that
rectangle to the dirty rectangle of the component. The dirty rectangle
is initially empty, then all invalid rectangles are added to it. At the end
of each frame windowing system sends a broadcast event with `cscmdRedraw'
command code. When component catches this event, it calls Redraw()
method which in turn calls csComponent::Draw()
. After
csComponent::Draw()
returns control, the dirty rectangle is emptied
again. Before calling the Draw()
method, Redraw()
sets the
component's clipping rectangle to the dirty rectangle, so usually you don't
have to take care to not draw outside the dirty rectangle; clipping will take
care of it for you (to minimize the number of draw operations).
All draw operations are clipped first against dirty rectangle and then against all component children and neightbours. So drawing inside a component does not change even a pixel in other components, even if component is partialy covered by other components.
There are a number of drawing operations that you can use. Other operations can be synthesized from existing. All coordinates used for drawing are component-origin related, so (0,0) corresponds to component top-left corner.
Here is a list of the primitive drawing methods:
Line(x1, y1, x2, y2, colorindex)
Draw a line from (x1, y1) to (x2, y2). Example:
Line(0, 0, 3, 3)
produces the following output:
0 1 2 3 4 ... | | | | | | 0 --#--+--+--+--+--+-- |//| | | | | 1 --+--#--+--+--+--+-- | |//| | | | 2 --+--+--#--+--+--+-- | | |//| | | 3 --+--+--+--#--+--+-- | | | |//| | ...--+--+--+--+--+--+-- |
Box(xmin, ymin, xmax, ymax, colorindex)
Draw a filled box that is closed between lines (X >= xmin)
,
(X < xmax)
, (Y >= ymin)
and (Y < ymax)
.
Example: Box(0, 0, 3, 2)
will produce the following output:
0 1 2 3 4 ... | | | | | | 0 --#--#--#--+--+--+-- |//|//|//| | | 1 --#--#--#--+--+--+-- |//|//|//| | | 2 --+--+--+--+--+--+-- | | | | | | ...--+--+--+--+--+--+-- |
Text(x, y, foregroundindex, backgroundindex, textstring)
Display a text string starting from (x, y) with color
foregroundindex and background backgroundindex. If
backgroundindex is -1, the text is drawn transparently. To determine
text width and height you can use the TextWidth(textstring)
and
TextHeight()
functions. There are a number of built-in CSWS
fonts, they can be used by calling SetFont(cs_Font_XXXX)
. Note
that both TextWidth()
and TextHeight()
depends on current font.
Sprite2D(sprite2d, x, y, w, h)
Draw a 2D sprite or bitmap. sprite2d is a object of `csPixmap' class. Sprite can have transparent colors, this way you can define holes in textures. (You can omit w and h to use normal sprite size.)
Rect3D(xmin, ymin, xmax, ymax, darkindex, lightindex)
Draw a 3D-looking rectangle. This method just draws four lines to form a
non-filled rectangle. Example: Rect3D(0, 0, 4, 4)
.
0 1 2 3 4 ... | | | | | | 0 --#--#--#--#--+--+-- |LL|LL|LL|DD| | 1 --#--+--+--#--+--+-- |LL| | |DD| | 2 --#--+--+--#--+--+-- |LL| | |DD| | 3 --#--#--#--#--+--+-- |LL|DD|DD|DD| | 4 --+--+--+--+--+--+-- | | | | | | |
ObliqueRect3D(xmin, ymin, xmax, ymax, cornersize, darkindex, lightindex)
Draw a rectangle with oblique corners of given size. For example, calling
ObliqueRect3D(0, 0, 10, 7, 3)
draws an oblique rectangle such as the
following:
0 1 2 3 4 5 6 7 8 9 ... | | | | | | | | | | | 0 --+--+--#--#--#--#--#--#--#--#--+-- | | |LL|LL|LL|LL|LL|LL|LL|DD| 1 --+--#--+--+--+--+--+--+--+--#--+-- | |LL| | | | | | | |DD| 2 --#--+--+--+--+--+--+--+--+--#--+-- |LL| | | | | | | | |DD| 3 --#--+--+--+--+--+--+--+--+--#--+-- |LL| | | | | | | | |DD| 4 --#--+--+--+--+--+--+--+--+--#--+-- |LL| | | | | | | | |DD| 5 --#--+--+--+--+--+--+--+--#--+--+-- |LL| | | | | | | |DD| | 6 --#--#--#--#--#--#--#--#--+--+--+-- |LL|DD|DD|DD|DD|DD|DD|DD| | | ...--+--+--+--+--+--+--+--+--+--+--+-- |
SetClipRect(xmin, ymin, xmax, ymax)
Define a local clipping rectangle for subsequent drawing operations. For
example, when drawing a button you may want to set clipping rectangle after
drawing button borders so that button text accidentally won't draw over its
borders even if it does not fit. To disable clipping you can define an empty
rectangle (SetClipRect(0, 0, 0, 0)
);
Pixel(x, y)
Plot the pixel at <x,y
with the current color.
Clear(color)
Clears the entire area of the component. Equivalent to:
|
ClearZbuffer(xmin, ymin, xmax, ymax)
Clear the Z-buffer in the given rectangle. Useful if you draw 3D Z-buffered polygons inside your window.
Polygon3D(poly, mode)
Draw a 3D polygon (clipped to the window). The `poly' structure is
of the `G3DPolygonDPFX' type, which is defined in `igraph3d.h'. This
structure should be filled, as usual with the vertices, texturing information,
and so on. The `mode' parameters is the same as the one in
iGraphics3D::DrawPolygonFX()
; that is, it defines the mode in which to
draw the polygon (gouraud, mix mode, alpha, and so on).
csComponent::HandleEvent(iEvent&)
This is the main component entry point for handling windowing system events. Each time user presses a key, moves mouse etc windowing system generates a event and sends it to appropiate component. The normal event flow is top-down, i.e. the root window receives events first, then passes them if appropiate to its children which passes it to their respective children and so on. However, there are some basical constraints on event flow that you should know about:
HandleEvent()
should return a boolean value that states whenever this
object used the event or not. If the event has been used, no other component
will receive it anymore, otherwise windowing system looks for other appropiate
candidates for this event. The only exception from this rule are broadcast
events that are sent to all children independently of the fact that component
eaten event or not.
app->CaptureMouse(this)
---in this case mouse
events are sent by application object directly to the object that captured the
mouse, bypassing normal event flow. To revert to normal mode of operation
component should call app->CaptureMouse(NULL)
.
app->CaptureKeyboard(this)
.
To disable capturing keyboard events component should call
app->CaptureKeyboard(NULL)
.
csDialog
's
HandleEvent()
. Instead you can subclass the window. In most cases you
will want to subclass the window anyway).
csComponent::HandleEvent()
, automatically.)
Aside from the exceptions above, in all other cases the events are processed
from the root of the component's hierarchy (e.g. the `csApp' object) down
along every branch and can reach every component in the tree (unless the event
is eaten somewhere). Other than broadcast events, any "true" return
code from a component's HandleEvent()
method means that the event has
been eaten and should not be sent to any other components. The
tree-like event propagation is performed by csComponent::HandleEvent()
,
in addition to a lot of other important things, thus you always should call the
parent class' HandleEvent()
method to avoid confusing the windowing
system.
There is another method called csComponent::PreHandleEvent()
which is
much like HandleEvent()
except that it is called for each event pulled
from event queue before HandleEvent()
, and without rules above, i.e.
any component can preprocess any hardware-generated event before it is sent
along normal event handling chain. This can be used for popup menus, hot keys
and so on. If PreHandleEvent()
returns true, the event is considered
eaten and is discarded. Be careful with this feature to avoid
interfering with normal component functions.
And last method related to event processing is
csComponent::PostHandleEvent()
. It is called when no component handled
the event and it is called for all components in parent-to-child order.
It can be used to process events that nobody wants, for example it is used to
process hotkeys on buttons (if active component is for example, a input line,
and user presses A key it should be entered into input text, while if
active component is a non text-hungry component (for example, a list box) the
A key can be used by some button to activate itself).
The `csComponent' class has a number of data fields. The most important are summarized here.
csRect bound
int state
You should never manually change state flags. Instead, there are two methods
for this: SetState(mask, state)
and
GetState(mask)
. For example, if component is not selectable and
you want to make it selectable, call component.SetState(CSS_SELECTABLE,
true)
. The SetState()
method is virtual and is often overriden to
execute some specific functions when component state changes. For example,
default SetState()
handler shows or hides the component if
`CSS_VISIBLE' flag state changes.
csRect dirty
int DragStyle
CS_DRAG_XXX
) that defines which sides of component can be dragged
with mouse when you call first the csComponent::Drag()
method. By
default it is equal to `CS_DRAG_ALL'. Note that if component won't call
csComponent::Drag()
you won't be able to resize the component even if
`DragStyle' is equal to `CS_DRAG_ALL'.
csApp *app
csComponent *parent
csComponent *prev
csComponent *next
NULL
, chains are always closed. If a component is the only child
of another, its next and prev fields points to himself.
csComponent *focused
NULL
. This is the only
possible case when "focused" can be NULL
.
csComponent *top
int id
parent->GetChild(int find_id)
.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |