Home > Programmer's Guide > More About Programming > Adding Program Functionality
Graphics
The HB++ language provides various methods to draw on the screen or into a bitmap, to perform color management, to support high density screens, and so on. This section explains the basic concepts behind these features.
The Display class
The Display class encapsulates the notion of "a virtual surface on which you can draw". It provides properties for setting colors, fonts, or coordinates systems, and methods to actually perform drawings, such as PutPixel, Line, or Rectangle. All the classes representing a physical surface, such as a bitmap, a form, or a control, derive from this base class.
This architecture gives you much flexibility when implementing your drawing routines. The same code can be used to draw onto a bitmap, a form, or into a user control, the internals of the Display object being responsible for handling differences between these surfaces. The Double Buffering sample illustrates this. It uses the same code to directly draw on a form or into an offscreen bitmap, depending on the state of a check box:
Private Sub t_Timer()
Dim d As Display
Dim b As clsBall
' when double-buffering is enabled, draw into the bitmap
If CheckBox1.Value Then Set d = bmBuffer Else Set d = Me
' perform drawings
d.Rectangle 0,0,160,140,hbRectFillSolid
For Each b In balls
b.bounceAndDraw d
Next b
' when double-buffering is enabled, copy the bitmap onto the form
If CheckBox1.Value Then Me.CopyArea 0,0,160,140,d,0,0 Else Me.Flush
End SubEach Display object encapsulates state information necessary for carrying out graphics operations. This information includes the following properties:
The first three items are not accessible directly, and are implicitly determined by the object on which you are drawing. For example, a control automatically defines its coordinates origin as being the top left corner of the control, and the clipping area as corresponding to the size of the control. The last four items on the other hand can be set by the programmer. All of these are specific to each Display object. For example, if you modify the foreground color of a control, you will not change the foreground color of the form on which it is placed.
You can refer to the documentation of the Display class for more information on the available graphic primitives provided by the HB++ language.
Color management
Each Display object is associated a color palette. If the object refers to the screen, this palette is determined by the current graphic mode, and can be modified using the ScreenMode object. If the object refer to a Bitmap, this palette is set when the bitmap is first created, either directly by calling the Create method, or indirectly by loading an image family from the application resources.
Currently, up to 5 color models are supported, depending on the Palm OS® version. The table below describes these color models, and their corresponding bit depth:
| Bit Depth | Availability | Description |
| 1 | Since Palm OS® 1.0 | The object uses a monochrome black and white palette. |
| 2 | Since Palm OS® 3.0 | The object uses a 4 grey levels palette. |
| 4 | Since Palm OS® 3.3 | The object uses a 16 grey levels palette. |
| 8 | Since Palm OS® 3.5 | The object uses a 256 colors palette. |
| 16 | Since Palm OS® 4.0 | The object does not have a palette, and uses true colors. |
When you design bitmaps to be included in your project, you may need to know which colors make up a given palette. To do this, you can simply create blank images by using the "Project > Add images" wizard. The created BMP files will contain the proper palettes. You can then export these palettes to whatever format you need by using your favorite bitmap editor.
Specifying colors for drawing is always performed using true RGB values. The system is responsible for mapping the colors you wish to the nearest available color in the palette currently associated to the Display object you are drawing onto. Thus, most of the time, you don't have to worry about actual characteristics of the device.
For more information on color management, you can refer to the Color Handling section.
High density screens and high density bitmaps
The screens of most devices are 160 pixel wide and 160 pixel high. Starting with Palm OS® 4.1, some systems provide support for other screen sizes. Currently, one can find double-density screens (320 by 320), or one and a half density screens (240 by 320 with collapsible input area). The support for these new screen sizes is designed in such a way that nearly all applications designed for low-density screens will run unaltered, by adding the notion of density.
The density refers to the ratio of the screen's width and height expressed in number of pixels, to the width and height of a standard 160 by 160 screen. Note that the screen density has no relation to the screen physical size.
A double-density screen packs twice as many pixels in each dimension into the same physical space as a single-density screen. Regardless of the screen density, graphic primitives have the same footprint, taking up the same percentage of screen space. For example, an application designed to display 10 lines of text will still display that same number of line on a double-density screen. But the text will look better, however, because each character will be composed of more pixels.
The same notion is applied to bitmaps. The density refers here to the ratio of the physical size of the bitmap expressed in number of pixel, to the size that this bitmap occupies on the screen when it is displayed on a standard 160 by 160 screen. For example, when displaying a single-density bitmap to a double density screen, each source pixel is copyied twice along each axis.
When handling bitmaps, you always work with logical sizes, that is size the bitmap would have if blitted on a single-density screen. You never have to deal with pixels. You can get familiar to this notion by playing around the "Project > Add images" wizard.
Create a simple project, and use that "Project > Add images" wizard to create an image family containing a low-density bitmap, and a double-density bitmap (the color depth does not matter). When editing these two bitmaps with your favorite bitmap editor, you will notice that the double-density bitmap is twice bigger that the low-density one. They still have the same logical size. Simply, their densities are different.
Then, place a Picture control on a form, and associate it with the previous image family. Run this sample on the Palm OS® Emulator, and then on the Palm OS® Simulator. You will notice that despite their different physical sizes, the two bitmaps occupy the same percentage of the screen.
To avoid the necessity of floating point computations when handling densities, HB++ normalizes the low-density value to be 72. This yields the following constants, which can be used with all methods and properties requiring you specify a density:
| Constant | Value | Description |
| hbDensityLow | 72 | Low density. |
| hbDensityOneAndAHalf | 108 | One and a half density. |
| hbDensityDouble | 144 | Double density. |
| hbDensityTriple | 216 | Triple density. |
| hbDensityQuadruple | 288 | Quadruple density. |
These values should not be interpreted as representing pixels per inch.
You can determine at runtime the physical properties of the screen by calling the ScreenWidth, ScreenHeight and ScreenDensity properties of the SystemInfo class. A given device usually only supports two densities: low-density, and the density of its screen.
Coordinates system
Starting with the high density feature, you can stop thinking in terms of pixels, and start thinking in terms of logical coordinates. The system takes care of mapping coordinates to physical pixels, and all the graphic primitives as well as controls and forms positionning work with coordinates.
The most important coordinates system provided by the system is the standard coordinates system. It maps the actual display to a standard 160 by 160 screen, and is used to position controls and forms on the screen. All coordinates you enter in the property window of the IDE as well as those accepted or returned by the various methods and properties of the UIComponent class, such as Width, Height or Move are expressed in standard coordinates. Similarly, the position of the stylus as reported by the PenDown, PenMove and PenUp events are also expressed in standard coordinates. You cannot change this behaviour. It permits existing applications to run unaltered on high-density devices.
By default, graphic primitives also use standard coordinates, but you can override this behaviour by setting a new value to the CoordinateSystem property of the Display object you are drawing onto. It can define various mapping mode, as follows:
| Constant | Value | Description |
| hbCoordinatesNative | 0 | Coordinates are interpreted as pixels, and are passed "as is" to the underlying hardware. |
| hbCoordinatesStandard | 72 | Coordinates are normalized so that the bottom right corner of the full screen is located at (159,159). This is the standard coordinates system described above. |
| hbCoordinatesOneAndAHalf | 108 | Coordinates are normalized so that the bottom right corner of the full screen is located at (239,239). |
| hbCoordinatesDouble | 144 | Coordinates are normalized so that the bottom right corner of the full screen is located at (319,319). |
| hbCoordinatesTriple | 216 | Coordinates are normalized so that the bottom right corner of the full screen is located at (479,479). |
| hbCoordinatesQuadruple | 288 | Coordinates are normalized so that the bottom right corner of the full screen is located at (639,639). |
The hbCoordinatesNative mode allows full positionning of drawings on the screen or in a bitmap. In this mode, coordinates are expressed in pixels. In all other modes, coordinates are considered to be logical coordinates, and are converted to native coordinates taking into account the screen or bitmap density on which the drawing takes place, using the following formula:
Coord(pixels) = Coord(logical) * Density / CoordinateSystem
Note that hbCoordinatesNative and hbCoordinatesStandard define the same coordinates system when running on a low-density device, while hbCoordinatesNative and hbCoordinatesDouble define the same coordinates system when running on a double-density device, and so on.
For more information, you can refer to the CoordinateSystem page.