home *** CD-ROM | disk | FTP | other *** search
/ Monster Media 1994 #1 / monster.zip / monster / PROG_GEN / TVGRAPH.ZIP / BITMAP.DOC < prev    next >
Text File  |  1993-12-19  |  19KB  |  471 lines

  1. Documentation of BitMaps in TVGraphic
  2.     December 19, 1993
  3.  
  4. Version 1.5 of TVGraphic is the first to have bitmaps. They are
  5. documented separately in this file for now.
  6.  
  7. TVGraphic can read a .BMP format bitmap file. It can draw
  8. non-compressed 16 color bitmaps with file sizes less than 64K bytes.
  9. Bitmaps in this format can be generated by Borland's Resource Workshop
  10. and by the Paintbrush program that comes with Microsoft's Windows.
  11. A color translation utility is included with TVGraphic to convert
  12. the order of palette colors from Windows to Borland BGI order.
  13. You can also link bitmaps into your program as explained later.
  14.  
  15. A fully clippable bitmap driver is included. It reads a TBitMap
  16. record which has the same format as a .BMP file.
  17.  
  18. Two views have been added that use bitmaps.
  19.  
  20. TIconButton inherits the behavior from TButton but draws itself
  21. using a single bitmap. Its appearance changes depending on whether
  22. the button is the Default button, Selected or not, Pressed and,
  23. optionally, on whether it is Disabled. It will also optionally draw
  24. a thick or thin button frame around the bitmap.
  25. IconButtons are designed to be inserted into Dialogs and the ToolBar.
  26.  
  27. TStaticBitMap is the simplest possible view that draws itself
  28. from a bitmap.
  29.  
  30. A ToolBar window that holds bitmapped buttons has also been added.
  31.  
  32. The low level routines are in BMPDRVR.TPU and the new views are in
  33. GBUT.TPU.
  34.  
  35.  
  36. WORKING WITH BITMAPS
  37.  
  38. Bitmap details
  39.   non-compressed 16 color (4 bits/pixel)  format only
  40.   max bitmap file size 64K bytes  (about 127K pixels)
  41.   "PelsPerMeter" fields ignored
  42.   TVGraphic does not use the palette information stored in the file.
  43.   TVGraphic's TBitMap record uses the same format as a .BMP file.
  44.  
  45. Color Order
  46.  
  47.   The order of colors in the color palette differs between Windows
  48. and Borland BGI. This means that colors will be swapped around if
  49. you draw a bitmap file directly. There are two ways to correct this.
  50.  
  51. The TVGraphic utility BMP2BMG.exe reads a .BMP file and creates a
  52. .BMG file with correct colors for TVGraphic. (Type BMP2BMG at the
  53. DOS prompt for syntax.)
  54.  
  55. Alternatively, you can load a .BMP file at runtime and pass
  56. a pointer to it to
  57.         procedure WinToTVColor(ABitPtr : PBitMap);
  58. which will correct the colors.
  59.  
  60.  
  61. Black and White Screens (as in VGA Laptops, etc.)
  62.   This release does not directly support having a second bitmap
  63.   image for back and white. However you can determine which mode
  64.   the screen is in at startup and Init your buttons with the
  65.   appropriate bitmaps. Or you can change ImgPtr after construction.
  66.  
  67.  
  68. DRAWING A BITMAP
  69.  
  70.   Assuming you have linked or loaded a bitmap as explained later,
  71. call  (unit BMPDRVR}
  72.   procedure PutBitMap(X,Y : integer; BitPtr : PBitMap;
  73.                       ColorPair : byte; Mode : byte);
  74.  
  75. to draw the bitmap pointed to by BitPtr at screen location X,Y.
  76.   These coordinates are viewport relative like the Borland
  77. BGI calls. The bitmap will be clipped to the current viewport
  78. if it extends outside the viewport and BGI clipping is turned
  79. on, otherwise clipped to the screen.
  80.   ColorPair is only used with Mode = ReMapPut.
  81.   Modes are the same as in BGI's PutImage.
  82.  
  83.  
  84. LOADING A BITMAP FILE
  85.  
  86.   Three routines are used when loading a .BMP or .BMG file at run
  87. time. These are in BMPDRVR.TPU.
  88.  
  89.   function BMPFormatOKStr(ABitPtr : PBitMap; FName : DirStr):string;
  90.   function AllocateBMPmem(ABitPtr : PBitMap) : PBitMap;
  91.   function GetBitImageSize(ABitPtr : PBitMap) : longint;
  92.  
  93. See the demo program for exact code. Since bitmaps have no fixed
  94. file length, must load in two steps.
  95.  
  96. First you open the file and read the fixed length
  97. TBitmapInfoHeader into a variable such as
  98.      Buf : array[0..Sizeof(TBitmapInfoHeader)-1] of byte.
  99.  
  100. Buf now contains all the information about this bitmap. Typecast Buf
  101. and call   (where BMPfilename is the DOS file name of .BMP or .BMG)
  102.      ErrorStr := BMPFormatOKStr(PBitMap(Buf), BMPfilename);
  103.  
  104. BMPFormatOKStr checks if the file is a bitmap file, if size < 64K
  105. and if the current version of TVGraphic can draw it. If the bitmap
  106. file is readable and drawable, ErrorStr will return empty.
  107. Otherwise you should display ErrorStr in an error MessageBox and
  108. then close the file.
  109.  
  110. Assuming ErrorStr was empty, next call
  111.      MyBitMapPtr := AllocateBMPmem(PBitMap(Buf));
  112. which will allocate memory for the bitmap and return the pointer
  113. to this memory. Please use this function to allocate memory to
  114. allow for future changes. Allocation respects the safety pool.
  115. The memory can be freed with
  116.      if MyBitMapPtr <> nil
  117.        then FreeMem(MyBitMapPtr, GetBitImageSize(MyBitMapPtr));
  118.  
  119. If there is not a big enough block of memory to hold the bitmap,
  120. the function announces this in a MessageBox and returns a nil pointer.
  121.  
  122. If memory was successfully allocated, then call
  123.      function GetBitImageSize(PBitMap(Buf)) : longint;
  124.  
  125. to find the size of the bitmap including the Infoheader.
  126. Do a BlockRead of GetBitImageSize bytes from the BEGINNING
  127. of the file. (You will have to Reset the file.) Read directly
  128. into the memory returned by AllocateBMPmem.
  129. (The memory image of the bitmap must include the InfoHeader.)
  130.  
  131. Refer to the bitmap by its pointer (MyBitMapPtr in this example).
  132.  
  133.  
  134. LINKING A BITMAP to YOUR PROGRAM/UNIT
  135.  
  136. It is often convenient to link small bitmaps into your program
  137. at compilation. Borland provides the command line utility
  138. BINOBJ.exe which makes this possible. It allows one to convert
  139. any binary file (a .BMP or .BMG for example) into a .OBJ file
  140. which can then be linked using the {$L} compiler directive.
  141. The following will look a little strange because you link the
  142. bitmap in as if it were a procedure but its simple to do and use.
  143.  
  144. Note that it is least confusing to correct the bitmap colors
  145. before linking.
  146. Convert your .BMP file to a .BMG file using BMP2BMG.exe.
  147.  
  148.     c:>  BMP2BMG  MyBitMap.BMP  [optional name for .BMG file]
  149. this creates MyBitMap.BMG (unless you use the optional name).
  150.  
  151. Borland documentation for BINOBJ is in a file but the utility
  152. is simple to use - just type BINOBJ to see the syntax.
  153. The "public name" in the syntax is the name you will use in
  154. your program to refer to the bitmap.
  155.  
  156.    c:>  BINOBJ  MyBitMap.BMG  MyBitMap  BitMapNameToUseInProgram
  157.  
  158. this creates MyBitMap.OBJ. Make sure it is in a directory the
  159. compiler can find.
  160.  
  161. Then add in your unit or program the following lines:
  162.  
  163.      procedure BitMapNameToUseInProgram; external;
  164.      {$L MyBitMap.OBJ}
  165.  
  166. Note that the name of the "procedure" must be the same as you
  167. specified to BINOBJ as the public name. You don't call this
  168. "procedure", its just your bitmap data in disguise.
  169.  
  170. Refer to the Bitmap by using the @ pointer operator:
  171.   wherever you need to pass the bitmap as a PBitMap pointer
  172.       use
  173.         @BitMapNameToUseInProgram
  174.  
  175. Alternatively you could assign the bitmap to a PBitMap pointer.
  176.           MyBitPtr := @BitMapNameToUseInProgram
  177.     IF YOU do this, do NOT free memory or dispose the pointer!!!
  178.     The bitmap is still located in code, not allocated on the heap.
  179.  
  180. *****
  181.  
  182. NOTES ON THE TOOLBAR
  183.  
  184.   The toolbar descends from TDialog and is intended for insertion
  185. into the DeskTop (see Demo program). It has its own palette which uses
  186. the colors for a Dialog's "Button Normal"/bkgnd to draw the window
  187. frame and background. Generally you will want your bitmapped buttons
  188. to have the same background color as this palette entry so they
  189. match the text buttons in the standard views. Then the ToolBar will
  190. also match. The standard TVGraphic button background is light gray.
  191.  
  192.   Buttons have ofSelectable set by default.  If so, the Selected
  193. button will have a dotted line drawn around it. Setting bfGrabFocus
  194. in the Opts field of a button's constructor will cause it to Select
  195. itself when clicked with mouse. So the dotted line will be on the
  196. last clicked button.
  197.   If you don't want the dotted line , clear the ofSelectable flag
  198. in the button's Options field after construction. bfGrabFocus is
  199. not needed in this case but doesn't hurt.
  200.   Note that the buttons will respond to HotKeys, if you have set
  201. them, but Turbo Vision does not cause such a button to select itself.
  202. The HotKey must be pressed in combination with the Alt key.
  203.  
  204.   At this time, the toolbar does not draw itself with correct colors
  205. if inserted into a Window.
  206.  
  207.  
  208. Permanent Toolbar
  209.   Since TVGraphic's toolbar is a non-selectable dialog inserted in the
  210. desktop, other views can cover it up. The alternative is a permanent
  211. toolbar inserted in the application like a menu.
  212.   If you want to make a permanent toolbar along one edge of the
  213. DeskTop, you will need to override TProgram.InitDeskTop to reduce
  214. the size of the DeskTop.
  215.  
  216.   procedure TProgram.InitDeskTop; {Modify this standard TVGraphic code}
  217.   var
  218.     R: TRect;
  219.   begin
  220.     GetExtent(R);
  221.     if MenuBar <> nil then
  222.       Inc(R.A.Y, MenuBar^.Size.y +1);
  223.     if StatusLine <> nil then
  224.       Dec(R.B.Y, StatusLine^.Size.y +1);
  225.     New(DeskTop, Init(R));
  226.   end;
  227.  
  228. The easiest way to create this type of toolbar is probably to
  229. descend it directly from TGroup so it acts only as a holder for
  230. the buttons. Clear the ofSelectable flag in TGroup's Options
  231. field so clicking on a button won't deselect your active window.
  232. This type of bar is mouse accessible only unless you enable HotKeys
  233. as described for TToolBar in the Reference section.
  234.  
  235. Be sure to give the toolbar a GetPalette function returning the
  236. CToolBar palette.
  237.  
  238.   function TMyToolbar.GetPalette: PPalette;
  239.   const
  240.     P: string[Length(CToolBar)] = CToolBar;
  241.   begin
  242.     GetPalette := @P;
  243.   end;
  244.  
  245. See Reference later for details on palette.
  246. ************************************************
  247.  
  248. REFERENCE
  249.  
  250. Unit BMPDRVR
  251. type
  252.         {entire BMP file must fit into TBMPArray}
  253.         {largest array you can allocate}
  254.   PBMPArray = ^TBMPArray;
  255.   TBMPArray = array[0..65534] of byte;
  256.  
  257.   TRGBQuad = record
  258.     rgbBlue: Byte;
  259.     rgbGreen: Byte;
  260.     rgbRed: Byte;
  261.     rgbReserved: Byte;
  262.   end;
  263.  
  264.   ColorMapArray = array[0..15] of TRGBQuad;
  265.  
  266.   PBitmapInfoHeader = ^TBitmapInfoHeader;
  267.   TBitmapInfoHeader = record
  268.     bfType : word;      {ASCII "BM"}
  269.     bfSize : longint;   {Size in longint units of the file}
  270.     bfres1 : integer;   {reserved = 0}
  271.     bfres2 : integer;   {reserved = 0}
  272.     bfOffBits : longint; {Byte offset of actual bit image start}
  273.  
  274.     biSize: Longint;
  275.     biWidth: Longint;
  276.     biHeight: Longint;
  277.     biPlanes: Word;
  278.     biBitCount: Word;
  279.     biCompression: Longint;
  280.     biSizeImage: Longint;
  281.     biXPelsPerMeter: Longint;
  282.     biYPelsPerMeter: Longint;
  283.     biClrUsed: Longint;
  284.     biClrImportant: Longint;
  285.  
  286.     ColorMap : ColorMapArray{array[1..16] of TRGBQuad};   {Added}
  287.   end;
  288.  
  289.   PBitMap = ^TBitMap;     {used to declare BitMap variables}
  290.   TBitMap = record
  291.     case integer of   {two ways of looking at same data}
  292.       0: (InfoHeader : TBitMapInfoHeader);
  293.       1: (MapArray : TBMPArray);
  294.     end;
  295.  
  296.  
  297.  
  298. procedure PutBitMap(X,Y : integer; BitPtr : PBitMap;
  299.                         Mode : byte; ColorPair : byte);
  300.   Graphic drawing call.   Draws a bitmap to screen.
  301.   Clips to viewport if BGI clipping is turned on, otherwise clips
  302.   to the screen.
  303.     X,Y are viewport relative screen coordinates.
  304.     BitPtr is pointer to a TBitMap.
  305.     ColorPair is only used with Mode = ReMapPut. The background color
  306.     is in the upper 4 bits and the foreground color is in the lower
  307.     4 bits. In mode ReMapPut, any bitmap pixel that doesn't match
  308.     the background color is drawn in the foreground color. This
  309.     lets a TIconButton bitmap appear "disabled".
  310.     Modes are the same as in BGI's PutImage.
  311.  
  312.         Mode     Value   Meaning
  313.      ══════════╪═══════╪═════
  314.      NormalPut │   0   │ overwrite screen pixel with bitmap pixel
  315.      CopyPut   │   0   │
  316.      XORPut    │   1   │ screen pixel is current color XOR'd with
  317.                                        the bitmap pixel color
  318.      OrPut     │   2   │ screen pixel is current color OR'd with
  319.                                        the bitmap pixel color
  320.      AndPut    │   3   │ screen pixel is curent color AND'd with
  321.                                        the bitmap pixel color
  322.      NotPut    │   4   │ Bitmap pixel color is XOR'd and then
  323.                                        overwrites screen pixel
  324.      ReMapPut     10     bitmaps draws in two colors using TVGraphic
  325.                            TButton palette - see TIconButton.DrawState
  326.  
  327. {see previous text for these functions}
  328. function GetBitImageSize(ABitPtr : PBitMap) : longint;
  329. function BMPFormatOKStr(ABitPtr : PBitMap; FName : DirStr) : string;
  330. function AllocateBMPmem(ABitPtr : PBitMap) : PBitMap;
  331.  
  332. procedure WinToTVColor(ABitPtr : PBitMap);
  333.     Resets the color in every byte of BitMap to adjust for
  334.     differences between Windows and TV palette color order.
  335.     Converts colors in either direction.
  336.     If called twice on a bitmap, colors will revert to original.
  337.  
  338.  
  339. Unit GBUT
  340.  
  341. const
  342.   CToolBar - palette for TToolBar
  343.  
  344.   {use with Opts field of TIconButton}
  345.     {DefaultOpts = 0; defined in GDialogs}
  346.   tbDefault   = bfDefault; {=01   used to set bfDefault flag through
  347.                                    Opts field}
  348.   tbDrawFrame = $02;  {draws a button shadow frame over the perimeter
  349.                                 of the bitmap}
  350.   tbBroadcast = bfBroadcast; {=04  used to set bfBroadcast flag through
  351.                                    Opts field}
  352.   tbGrabFocus = bfGrabFocus; {= $08 used to set bfGrabFocus flag through
  353.                               Opts field}
  354.   tbAutoSize  = $20;  {the button sizes itself to match the bitmap}
  355.   tbDrawDisabled   = $40; {bitmap colors change when Command is disabled,
  356.                            see TIconButton.DrawState}
  357.   tbDrawThickFrame = $80;
  358.  
  359. Type
  360.   PIconButton = ^TIconButton;
  361.   TIconButton = Object(TButton)
  362.     ImgPtr : PBitMap;
  363.     constructor Init(var Bounds : TRect; Cmd : word;
  364.             ShortCut : string; Opts : byte; Iptr : PBitMap);
  365.       Command := Cmd     the command issued when pressed
  366.       Title^ := ShortCut  Use to enter shortcut key if desired
  367.           example:  Shortcut := '~Y~';
  368.           otherwise set ShortCut to empty string.
  369.       VOptions := Opts   option flags for VOptions field
  370.       ImgPtr := IPtr     the pointer to this button's bitmap
  371.       If tbAutoSize is set in OPts, then adjusts Bounds.B so view
  372.         will match the size of the bitmap before calling TButton.Init.
  373.       if tbBroadcast, tbGrabFocus, tbDefault is set in Opts,
  374.         the corresponding bf....  flag is set in the Flags field.
  375.     constructor Load(var S: TStream);
  376.       loads button and its bitmap from a Stream. Sets
  377.       ImgPtr to nil if not enough memory for bitmap.
  378.     procedure DrawState(Down : Boolean); Virtual;
  379.       draws the button using PutBitMap and bitmap ImgPtr^.
  380.       when pressed, momentarily draws bitmap with the colors
  381.         inverted    (Mode for PutBitMap = NotPut)
  382.       draws a button frame/border over the perimeter of the bitmap
  383.         if tbDrawFrame is set in VOptions field. Draws thicker frame
  384.         if tbDrawThickFrame is set instead.
  385.       draws a 2 pixel border (black with the standard TVGraphic palette)
  386.         around selected and default (Flags and bfDefault <> 0) buttons
  387.         if button's command is not disabled, and the button is not the
  388.         only selectable view in its owner.
  389.         If the button is Selected, then the inner line of this border
  390.         is dotted, else solid for default button.
  391.       if Command is disabled and VOptions' tbDrawDisabled is set,
  392.         draws the button altering the colors from the bitmap.
  393.         Bitmap colors not matching TButton's palette's Disabled
  394.         Text Background color are drawn in the Disabled Text
  395.         ForeGround color. IF bitmapped buttons are created with
  396.         the same background color as disabled TButtons, they
  397.         will look similar to TButtons when disabled.
  398.         For the default TVGraphic colors, active and disabled
  399.         buttons have a light gray background. Disabled text is
  400.         dark gray - the same look as for disabled menu items.
  401.  
  402.     procedure SetState(AState: Word; Enable: Boolean); virtual;
  403.       redraws the view only in response to state change of
  404.         sfSelected.
  405.       TButton.HandleEvent redraws if the button command is en/disabled
  406.         and then calls SetState(sfDisabled,...).
  407.     procedure Store(var S: TStream);
  408.       stores a button and its bitmap on a Stream.
  409.   end;
  410.  
  411.  
  412.     {DeskTop toolbar for bitmapped buttons}
  413.   PToolBar = ^TToolBar;
  414.   TToolBar = object(TDialog)
  415.     constructor Init(var Bounds: TRect; ATitle: TTitleStr);
  416.       GrowMode := 0;
  417.       Options := Options and not ofSelectable; {make non-selectable}
  418.        {next line to allow HotKeys in buttons}
  419.       Options := Options or ofPostProcess;
  420.     function GetPalette : PPalette; virtual;
  421.       identical to first 15 entries of Dialog palette except
  422.       it maps all three Frame entries [1,2,3] to same value
  423.       as ButtonNormal (=41).
  424.     procedure HandleEvent(var Event: TEvent); virtual;
  425.       To prevent regular keystrokes from being recognized as HotKeys,
  426.         call TWindow.HandleEvent only
  427.       if not ((Event.What = evKeyDown) and (Event.KeyCode and $00FF <> 0))
  428.     procedure SizeLimits(var Min, Max: TPoint); virtual;
  429.       overrides TWindow.SizeLimits - calls TView.SizeLimits.
  430.   end;
  431.  
  432.  
  433.     {simple view that draws itself from a bitmap}
  434.   PStaticBitMap = ^TStaticBitMap;
  435.   TStaticBitMap = object(TView)
  436.     ImgPtr : PBitMap;
  437.     constructor Init(var Bounds : TRect; Iptr : PBitMap);
  438.       calls TView.Init
  439.       ImgPtr := IPtr
  440.     constructor Load(var S: TStream);
  441.       loads view and its bitmap from a Stream.
  442.       ImgPtr set to nil if not enough memory for bitmap.
  443.     procedure Draw; virtual;
  444.       if ImgPtr is not nil, draws ImgPtr^ using PutBitMap
  445.     procedure Store(var S: TStream);
  446.       stores view and its bitmap on a Stream.
  447.   end;
  448.  
  449. procedure RegisterBitMaps;
  450.  
  451. { Stream Registration Records }
  452. const
  453.   RIconButton: TStreamRec = (
  454.      ObjType: gRegBase+ 2100;
  455.      VmtLink: Ofs(TypeOf(TIconButton)^);
  456.      Load:    @TIconButton.Load;
  457.      Store:   @TIconButton.Store
  458.   );
  459.   RStaticBitMap: TStreamRec = (
  460.      ObjType: gRegBase+ 2101;
  461.      VmtLink: Ofs(TypeOf(TStaticBitMap)^);
  462.      Load:    @TStaticBitMap.Load;
  463.      Store:   @TStaticBitMap.Store
  464.   );
  465.   RToolBar: TStreamRec = (
  466.      ObjType: gRegBase+ 2102;
  467.      VmtLink: Ofs(TypeOf(TToolBar)^);
  468.      Load:    @TToolBar.Load;
  469.      Store:   @TToolBar.Store
  470.   );
  471.