home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
DP Tool Club 21
/
CD_ASCQ_21_040595.iso
/
dos
/
prg
/
pas
/
tvgr70
/
bitmap.doc
< prev
next >
Wrap
Text File
|
1995-01-01
|
21KB
|
520 lines
Documentation of BitMaps in TVGraphic 2.0
September 1994
v2.02 December 1994
procedure WinToTVColor now handles correctly those bitmaps whose
light and dark gray palette entries are reversed from the order in
Windows Paintbrush.
As a graphical environment, TVGraphic supports bitmapped images.
Bitmaps and bitmap related views (static views, buttons, toolbar) are
documented separately in this file for now.
TVGraphic can read a .BMP format bitmap file. It can draw
non-compressed 16 color bitmaps with file sizes less than 64K bytes.
Bitmaps in this format can be generated by Borland's Resource Workshop
and by the Paintbrush program that comes with Microsoft's Windows.
A color translation utility is included with TVGraphic to convert
the order of palette colors from Windows to Borland BGI order.
You can also link bitmaps into your program as explained later.
A fully clippable bitmap driver is included. It reads a TBitMap
record which has the same format as a .BMP file.
Two views have been added that use bitmaps.
TIconButton inherits the behavior from TButton but draws itself
using a single bitmap. Its appearance changes depending on whether
the button is the Default button, Selected or not, Pressed and,
optionally, on whether it is Disabled. It will also optionally draw
a thick or thin button frame around the bitmap.
IconButtons are designed to be inserted into Dialogs and the ToolBar.
TStaticBitMap is the simplest possible view that draws itself
from a bitmap.
A ToolBar window that holds bitmapped buttons has also been added.
The low level routines are in BMPDRVR.TPU and the new views are in
GBUT.TPU.
WORKING WITH BITMAPS
Bitmap details
non-compressed 16 color (4 bits/pixel) format only
max bitmap file size 64K bytes (about 127K pixels)
"PelsPerMeter" fields ignored
TVGraphic does not use the palette information stored in the file.
TVGraphic's TBitMap record uses the same format as a .BMP file.
Color Order
The order of colors in the color palette differs between Windows
and Borland BGI. This means that colors will be swapped around if
you draw a bitmap file directly. There are two ways to correct this.
The TVGraphic utility BMP2BMG.exe reads a .BMP file and creates a
.BMG file with correct colors for TVGraphic. (Type BMP2BMG at the
DOS prompt for syntax.)
Alternatively, you can load a .BMP file at runtime and pass
a pointer to it to
procedure WinToTVColor(ABitPtr : PBitMap);
which will correct the colors.
Black and White Screens (as in VGA Laptops, etc.)
This release does not directly support having a second bitmap
image for back and white. However you can determine which mode
the screen is in at startup and Init your buttons with the
appropriate bitmaps. Or you can change ImgPtr after construction.
DRAWING A BITMAP
Assuming you have linked or loaded a bitmap as explained later,
call (unit BMPDRVR}
procedure PutBitMap(X,Y : integer; BitPtr : PBitMap;
ColorPair : byte; Mode : byte);
to draw the bitmap pointed to by BitPtr at screen location X,Y.
X, Y coordinates are viewport relative like the Borland BGI calls.
The bitmap will be clipped to the current viewport if it extends
outside the viewport and BGI clipping is turned on, otherwise
clipped to the screen.
ColorPair is only used with Mode = ReMapPut.
Modes are the same as in BGI's PutImage.
LOADING A BITMAP FILE
Three routines are used when loading a .BMP or .BMG file at run
time. These are in BMPDRVR.TPU.
function BMPFormatOKStr(ABitPtr : PBitMap; FName : DirStr):string;
function AllocateBMPmem(ABitPtr : PBitMap) : PBitMap;
function GetBitImageSize(ABitPtr : PBitMap) : longint;
See the demo program for exact code. Since bitmaps have no fixed
file length, must load in two steps.
First you open the file and read the fixed length
TBitmapInfoHeader into a variable such as
Buf : array[0..Sizeof(TBitmapInfoHeader)-1] of byte.
Buf now contains all the information about this bitmap. Typecast Buf
and call (where BMPfilename is the DOS file name of .BMP or .BMG)
ErrorStr := BMPFormatOKStr(PBitMap(Buf), BMPfilename);
BMPFormatOKStr checks if the file is a bitmap file, if size < 64K
and if the current version of TVGraphic can draw it. If the bitmap
file is readable and drawable, ErrorStr will return empty.
Otherwise you should display ErrorStr in an error MessageBox and
then close the file.
Assuming ErrorStr was empty, next call
MyBitMapPtr := AllocateBMPmem(PBitMap(Buf));
which will allocate memory for the bitmap and return the pointer
to this memory. Please use this function to allocate memory to
allow for future changes. Allocation respects the safety pool.
The memory can be freed with
if MyBitMapPtr <> nil
then FreeMem(MyBitMapPtr, GetBitImageSize(MyBitMapPtr));
If there is not a big enough block of memory to hold the bitmap,
the function announces this in a MessageBox and returns a nil pointer.
If memory was successfully allocated, then call
function GetBitImageSize(PBitMap(Buf)) : longint;
to find the size of the bitmap including the Infoheader.
Do a BlockRead of GetBitImageSize bytes from the BEGINNING
of the file. (You will have to Reset the file.) Read directly
into the memory returned by AllocateBMPmem.
(The memory image of the bitmap must include the InfoHeader.)
Refer to the bitmap by its pointer (MyBitMapPtr in this example).
LINKING A BITMAP to YOUR PROGRAM/UNIT
It is often convenient to link small bitmaps into your program
at compilation. Borland provides the command line utility
BINOBJ.exe which makes this possible. It allows one to convert
any binary file (a .BMP or .BMG for example) into a .OBJ file
which can then be linked using the {$L} compiler directive.
The following will look a little strange because you link the
bitmap in as if it were a procedure but its simple to do and use.
Note that it is least confusing to correct the bitmap colors
before linking.
Convert your .BMP file to a .BMG file using BMP2BMG.exe.
c:> BMP2BMG MyBitMap.BMP [optional name for .BMG file]
this creates MyBitMap.BMG (unless you use the optional name).
Borland documentation for BINOBJ is in a file but the utility
is simple to use - just type BINOBJ to see the syntax.
The "public name" in the syntax is the name you will use in
your program to refer to the bitmap.
c:> BINOBJ MyBitMap.BMG MyBitMap BitMapNameToUseInProgram
this creates MyBitMap.OBJ. Make sure it is in a directory the
compiler can find.
Then add in your unit or program the following lines:
procedure BitMapNameToUseInProgram; external;
{$L MyBitMap.OBJ}
Note that the name of the "procedure" must be the same as you
specified to BINOBJ as the public name. You don't call this
"procedure", its just your bitmap data in disguise.
Refer to the Bitmap by using the @ pointer operator:
wherever you need to pass the bitmap as a PBitMap pointer
use
@BitMapNameToUseInProgram
Alternatively you could assign the bitmap to a PBitMap pointer.
MyBitPtr := @BitMapNameToUseInProgram
IF YOU do this, do NOT free memory or dispose the pointer!!!
The bitmap is still located in code, not allocated on the heap.
*******
TIconButton, TStaticBitMap
NOTES on Disposing Bitmap Memory, using with Streams/Resources
When you dispose of an IconButton or StaticBitMap, it does NOT automatically
free the memory of the bitmap pointed to by the ImgPtr field. This bit
map may be linked into the program's code segment, for example, and not
allocated on the heap.
When you save a IconButton or StaticBitMap to a stream, the view saves
a copy of the bitmap pointed to by its ImgPtr field (unless you set
this field to nil!). Then when the view loads from the stream,
a new copy of the bitmap will be created on the heap.
Starting with v2.0:
To allow automatic disposal of this copy's heap memory,
TIconButton.Load and TStaticBitMap.Load set the tbDisposeBitMap flag in
the VOptions field if they successfully load a bitmap for the view.
A Done method has been added to each view which will free the bitmap
memory if ImgPtr <> nil and tbDisposeBitMap is set.
You may set/clear this flag bit if you need to.
*******
NOTES ON THE TOOLBAR
The toolbar descends from TDialog and is intended for insertion
into the DeskTop (see Demo program) or a Window. It has its own palette
which uses the colors for a gray Dialog's "Button Normal"/bkgnd to draw the
window frame and background. Generally you will want your bitmapped
buttons to have the same background color as this palette entry so they
match the text buttons in the standard views. Then the ToolBar will
also match. The standard TVGraphic button background is light gray.
Buttons have ofSelectable set by default. If so, the Selected
button will have a dotted line drawn around it. Setting bfGrabFocus
in the Opts field of a button's constructor will cause it to Select
itself when clicked with the mouse. So the dotted line will be on
the last clicked button.
If you don't want the dotted line , clear the ofSelectable flag
in the button's Options field after construction. bfGrabFocus is
not needed in this case but doesn't hurt.
Note that the buttons will respond to HotKeys, if you have set
them, but Turbo Vision does not cause such a button to select itself.
The HotKey must be pressed in combination with the Alt key.
Permanent Toolbar
Since TVGraphic's toolbar is a non-selectable dialog inserted in the
desktop, other views can cover it up. The alternative is a permanent
toolbar inserted in the application like a menu.
If you want to make a permanent toolbar along one edge of the
DeskTop, you will need to override TProgram.InitDeskTop to reduce
the size of the DeskTop.
procedure TProgram.InitDeskTop; {Modify this standard TVGraphic code}
var
R: TRect;
begin
GetExtent(R);
if MenuBar <> nil then
Inc(R.A.Y, MenuBar^.Size.y +1);
if StatusLine <> nil then
Dec(R.B.Y, StatusLine^.Size.y +1);
New(DeskTop, Init(R));
end;
The easiest way to create this type of toolbar is probably to
descend it directly from TGroup so it acts only as a holder for
the buttons. Clear the ofSelectable flag in TGroup's Options
field so clicking on a button won't deselect your active window.
This type of bar is mouse accessible only unless you assign HotKeys
to the buttons and set the ofPostProcess flag in the Options field
of the Toolbar.
Be sure to give the toolbar a GetPalette function returning the
CToolBar palette.
function TMyToolbar.GetPalette: PPalette;
const
P: string[Length(CToolBar)] = CToolBar;
begin
GetPalette := @P;
end;
See Reference later for details on palette.
************************************************
REFERENCE
Unit BMPDRVR
type
{entire BMP file must fit into TBMPArray}
{largest array you can allocate}
PBMPArray = ^TBMPArray;
TBMPArray = array[0..65534] of byte;
TRGBQuad = record
rgbBlue: Byte;
rgbGreen: Byte;
rgbRed: Byte;
rgbReserved: Byte;
end;
ColorMapArray = array[0..15] of TRGBQuad;
PBitmapInfoHeader = ^TBitmapInfoHeader;
TBitmapInfoHeader = record
bfType : word; {ASCII "BM"}
bfSize : longint; {Size in longint units of the file}
bfres1 : integer; {reserved = 0}
bfres2 : integer; {reserved = 0}
bfOffBits : longint; {Byte offset of actual bit image start}
biSize: Longint;
biWidth: Longint;
biHeight: Longint;
biPlanes: Word;
biBitCount: Word;
biCompression: Longint;
biSizeImage: Longint;
biXPelsPerMeter: Longint;
biYPelsPerMeter: Longint;
biClrUsed: Longint;
biClrImportant: Longint;
ColorMap : ColorMapArray{array[1..16] of TRGBQuad}; {Added}
end;
PBitMap = ^TBitMap; {used to declare BitMap variables}
TBitMap = record
case integer of {two ways of looking at same data}
0: (InfoHeader : TBitMapInfoHeader);
1: (MapArray : TBMPArray);
end;
procedure PutBitMap(X,Y : integer; BitPtr : PBitMap;
Mode : byte; ColorPair : byte);
Graphic drawing call. Draws a bitmap to screen.
Clips to viewport if BGI clipping is turned on, otherwise clips
to the screen.
X,Y are viewport relative screen coordinates.
BitPtr is pointer to a TBitMap.
ColorPair is only used with Mode = ReMapPut. The background color
is in the upper 4 bits and the foreground color is in the lower
4 bits. In mode ReMapPut, any bitmap pixel that doesn't match
the background color is drawn in the foreground color. This
lets a TIconButton bitmap appear "disabled".
Modes are the same as in BGI's PutImage.
Mode Value Meaning
══════════╪═══════╪═════
NormalPut │ 0 │ overwrite screen pixel with bitmap pixel
CopyPut │ 0 │
XORPut │ 1 │ screen pixel is current color XOR'd with
the bitmap pixel color
OrPut │ 2 │ screen pixel is current color OR'd with
the bitmap pixel color
AndPut │ 3 │ screen pixel is curent color AND'd with
the bitmap pixel color
NotPut │ 4 │ Bitmap pixel color is XOR'd and then
overwrites screen pixel
ReMapPut 10 bitmaps draws in two colors using TVGraphic
TButton palette - see TIconButton.DrawState
{see previous text for these functions}
function GetBitImageSize(ABitPtr : PBitMap) : longint;
function BMPFormatOKStr(ABitPtr : PBitMap; FName : DirStr) : string;
function AllocateBMPmem(ABitPtr : PBitMap) : PBitMap;
procedure WinToTVColor(ABitPtr : PBitMap);
Resets the color in every byte of BitMap to adjust for
differences between Windows and TV palette color order.
Converts colors in either direction.
If called twice on a bitmap, colors will revert to original.
v2.02 - now handles correctly either order of light and
dark gray palette entries.
Unit GBUT
const
CToolBar - palette for TToolBar
CToolBar = #41#41#41#35#36#37#38#39#40#41#42#43#44#45#46;
{use with Opts field of TIconButton}
{DefaultOpts = 0; defined in GDialogs}
tbDefault = bfDefault; {=01 used to set bfDefault flag through
Opts field}
tbDrawFrame = $02; {draws a button shadow frame over the perimeter
of the bitmap}
tbBroadcast = bfBroadcast; {=04 used to set bfBroadcast flag through
Opts field}
tbGrabFocus = bfGrabFocus; {= $08 used to set bfGrabFocus flag through
Opts field}
tbAutoSize = $20; {the button sizes itself to match the bitmap}
tbDrawDisabled = $40; {bitmap colors change when Command is disabled,
see TIconButton.DrawState}
tbDrawThickFrame = $80;
tbDisposeBitMap = $10; {causes Done to dispose of bitmap image memory}
Type
PIconButton = ^TIconButton;
TIconButton = Object(TButton)
ImgPtr : PBitMap;
constructor Init(var Bounds : TRect; Cmd : word;
ShortCut : string; Opts : byte; Iptr : PBitMap);
Command := Cmd the command issued when pressed
Title^ := ShortCut Use to enter shortcut key if desired
example: Shortcut := '~Y~';
otherwise set ShortCut to empty string.
VOptions := Opts option flags for VOptions field
ImgPtr := IPtr the pointer to this button's bitmap
If tbAutoSize is set in OPts, then adjusts Bounds.B so view
will match the size of the bitmap before calling TButton.Init.
if tbBroadcast, tbGrabFocus, tbDefault is set in Opts,
the corresponding bf.... flag is set in the Flags field.
constructor Load(var S: TStream);
loads button, ImgPtr and its bitmap (if ImgPtr <> nil) from a Stream.
Sets ImgPtr to nil if not enough memory for bitmap.
if ImgPtr <> nil, sets tbDisposeBitMap flag in VOptions field,
otherwise clears flag.
destructor Done; virtual;
if tbDisposeBitMap is set in VOptions and ImgPtr <> nil,
calls FreeMem for the memory pointed to by ImgPtr.
Calls TButton.Done.
procedure DrawState(Down : Boolean); Virtual;
draws the button using PutBitMap and bitmap ImgPtr^.
when pressed, momentarily draws bitmap with the colors
inverted (Mode for PutBitMap = NotPut)
draws a button frame/border over the perimeter of the bitmap
if tbDrawFrame is set in VOptions field. Draws thicker frame
if tbDrawThickFrame is set instead.
draws a 2 pixel border (black with the standard TVGraphic palette)
around selected and default (Flags and bfDefault <> 0) buttons
if button's command is not disabled, and the button is not the
only selectable view in its owner.
If the button is Selected, then the inner line of this border
is dotted, else solid for default button.
if Command is disabled and VOptions' tbDrawDisabled is set,
draws the button altering the colors from the bitmap.
Bitmap colors not matching TButton's palette's Disabled
Text Background color are drawn in the Disabled Text
ForeGround color. IF bitmapped buttons are created with
the same background color as disabled TButtons, they
will look similar to TButtons when disabled.
For the default TVGraphic colors, active and disabled
buttons have a light gray background. Disabled text is
dark gray - the same look as for disabled menu items.
procedure SetState(AState: Word; Enable: Boolean); virtual;
redraws the view only in response to state change of
sfSelected.
TButton.HandleEvent redraws if the button command is en/disabled
and then calls SetState(sfDisabled,...).
procedure Store(var S: TStream);
stores a button (and its bitmap if ImgPtr <> nil) on a Stream.
end;
{DeskTop toolbar for bitmapped buttons}
PToolBar = ^TToolBar;
TToolBar = object(TDialog)
constructor Init(var Bounds: TRect; ATitle: TTitleStr);
GrowMode := 0;
Options := Options and not ofSelectable; {make non-selectable}
{next line to allow HotKeys in buttons}
Options := Options or ofPostProcess;
DrawFlags := DrawFlags and not dfPanning;
prevents view from panning if in a TPanWindow
function GetPalette : PPalette; virtual;
identical to first 15 entries of gray Dialog palette except
it maps all three Frame entries [1,2,3] to same value
as ButtonNormal (=41).
procedure HandleEvent(var Event: TEvent); virtual;
To prevent regular keystrokes from being recognized as HotKeys,
call TWindow.HandleEvent only
if not ((Event.What = evKeyDown) and (Event.KeyCode and $00FF <> 0))
procedure SizeLimits(var Min, Max: TPoint); virtual;
overrides TWindow.SizeLimits - calls TView.SizeLimits.
end;
{simple view that draws itself from a bitmap}
PStaticBitMap = ^TStaticBitMap;
TStaticBitMap = object(TView)
ImgPtr : PBitMap;
constructor Init(var Bounds : TRect; Iptr : PBitMap);
calls TView.Init
ImgPtr := IPtr
constructor Load(var S: TStream);
loads view, ImgPtr and its bitmap (if ImgPtr <> nil) from a Stream.
Sets ImgPtr to nil if not enough memory for bitmap.
if ImgPtr <> nil, sets tbDisposeBitMap flag in VOptions field,
otherwise clears flag.
destructor Done; virtual;
if tbDisposeBitMap is set in VOptions and ImgPtr <> nil,
calls FreeMem for the memory pointed to by ImgPtr.
Calls TView.Done.
procedure Draw; virtual;
if ImgPtr is not nil, draws ImgPtr^ using PutBitMap
procedure Store(var S: TStream);
stores view and its bitmap on a Stream.
end;
procedure RegisterBitMaps;
{ Stream Registration Records }
const
RIconButton: TStreamRec = (
ObjType: gRegBase+ 2100;
VmtLink: Ofs(TypeOf(TIconButton)^);
Load: @TIconButton.Load;
Store: @TIconButton.Store
);
RStaticBitMap: TStreamRec = (
ObjType: gRegBase+ 2101;
VmtLink: Ofs(TypeOf(TStaticBitMap)^);
Load: @TStaticBitMap.Load;
Store: @TStaticBitMap.Store
);
RToolBar: TStreamRec = (
ObjType: gRegBase+ 2102;
VmtLink: Ofs(TypeOf(TToolBar)^);
Load: @TToolBar.Load;
Store: @TToolBar.Store
);