home *** CD-ROM | disk | FTP | other *** search
/ DP Tool Club 21 / CD_ASCQ_21_040595.iso / dos / prg / pas / tvgr70 / bitmap.doc < prev    next >
Text File  |  1995-01-01  |  21KB  |  520 lines

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