home *** CD-ROM | disk | FTP | other *** search
/ CD Actual 15 / CDACTUAL15.iso / cdactual / program / basic / QBSCR20.ZIP / 3D.BAS next >
Encoding:
BASIC Source File  |  1992-07-08  |  20.7 KB  |  490 lines

  1. '┌────────────────────────────────────────────────────────────────────────┐
  2. '│                                                                        │
  3. '│                              3 D . B A S                               │
  4. '│                                                                        │
  5. '│                   Supplementary Source Code for the                    │
  6. '│       The QBSCR Screen Routines for QuickBASIC 4.0+ Programmers        │
  7. '│                              Version 2.0                               │
  8. '│                                                                        │
  9. '│                   (C) Copyright 1992 by Tony Martin                    │
  10. '│                                                                        │
  11. '├────────────────────────────────────────────────────────────────────────┤
  12. '│                                                                        │
  13. '│  This source code is copyright 1992 by Tony Martin.  You may change    │
  14. '│  it to suit your programming needs, but you may not distribute any     │
  15. '│  modified copies of the library itself.  I retain all rights to the    │
  16. '│  source code and all library modules included with the QBSCR package,  │
  17. '│  as well as to the example programs.  You may not remove this notice   │
  18. '│  from any copies of the library itself you distribute.                 │
  19. '│                                                                        │
  20. '│  You are granted the right to use this source code for your own pro-   │
  21. '│  grams, without royalty payments or credits to me (though, if you      │
  22. '│  feel so inclined to give me credit, feel free to do so).  You MUST    │
  23. '│  register this software if you release a shareware or commercial       │
  24. '│  program that uses it.  You may use these routines in any type of      │
  25. '│  software you create, as long as it is not a programming toolbox or    │
  26. '│  package of routines OF ANY KIND.                                      │
  27. '│                                                                        │
  28. '│  This package is shareware.  If you find it useful or use it in any    │
  29. '│  software you release, you are requested to send a registration fee of │
  30. '│  $25.00 (U.S. funds only) to:                                          │
  31. '│                                                                        │
  32. '│                            Tony Martin                                 │
  33. '│                       1611 Harvest Green Ct.                           │
  34. '│                          Reston, VA 22094                              │
  35. '│                                                                        │
  36. '│  All registered users receive an 'official' disk set containing the    │
  37. '│  latest verison of the QBSCR routines.  For more information, see      │
  38. '│  the QBSCR documentation.                                              │
  39. '│                                                                        │
  40. '├────────────────────────────────────────────────────────────────────────┤
  41. '│                                                                        │
  42. '│  For information on using these routines and incorporating them into   │
  43. '│  your own programs, see the accompanying documentation.                │
  44. '│                                                                        │
  45. '└────────────────────────────────────────────────────────────────────────┘
  46.  
  47. REM $INCLUDE: 'mouse.bi'
  48.  
  49. CONST FLUSHLEFT = 0
  50. CONST FLUSHRIGHT = 1
  51. CONST CENTERED = 2
  52.  
  53. CONST SINGLEBORDER = 0        ' Single-line border for buttons and boxes
  54. CONST DOUBLEBORDER = 1        ' Double-line border for buttons and boxes
  55.  
  56. CONST STYLE3D = 0
  57. CONST STYLE2D = 1
  58.  
  59. CONST EMmoved = -1            ' getEvent code: Mouse Moved
  60. CONST EMpressedLeft = -2      ' getEvent code: Mouse left button pressed
  61. CONST EMpressedRight = -3     ' getEvent code: Mouse right button pressed
  62. CONST EMpressedCenter = -4    ' getEvent code: Mouse center button pressed
  63. CONST EMreleasedLeft = -5     ' getEvent code: Mouse left button releases
  64. CONST EMreleasedRight = -6    ' getEvent code: Mouse right button released
  65. CONST EMreleasedCenter = -7   ' getEvent code: Mouse center button released
  66. CONST EKpressed = -8          ' getEvent code: Key on keyboard pressed
  67.  
  68. CONST F1 = 15104              ' Unique integers (scan codes) for special
  69. CONST F2 = 15360              ' keys.  May be used to refer to codes returned
  70. CONST F3 = 15616              ' by getEvent function by name.
  71. CONST F4 = 15872
  72. CONST F5 = 16128
  73. CONST F6 = 16384
  74. CONST F7 = 16640
  75. CONST F8 = 16896
  76. CONST F9 = 17152
  77. CONST F10 = 17408
  78. CONST UPARROW = 18432
  79. CONST DOWNARROW = 20480
  80. CONST LEFTARROW = 19200
  81. CONST RIGHTARROW = 19712
  82. CONST HOMEKEY = 18176
  83. CONST ENDKEY = 20224
  84. CONST PGUP = 18688
  85. CONST PGDN = 20736
  86. CONST INSERT = 20992
  87. CONST DELETE = 21248
  88.  
  89. DECLARE FUNCTION getEvent% (checkMouse%, keyCode%, mouseX%, mouseY%)
  90. DECLARE SUB DepressedBox (boxType%, x1%, y1%, x2%, y2%, fg%, bg%, buttonStyle%)
  91. DECLARE SUB DrawButton (buttonType%, x1%, y1%, x2%, y2%, fg%, bg%, txt$, buttonStyle%)
  92. DECLARE SUB PressButton (buttonType%, x1%, y1%, x2%, y2%, fg%, bg%, txt$, buttonStyle%)
  93. DECLARE SUB PressedButton (buttonType%, x1%, y1%, x2%, y2%, fg%, bg%, txt$, buttonStyle%)
  94. DECLARE SUB RaisedBox (boxType%, x1%, y1%, x2%, y2%, fg%, bg%, buttonStyle%)
  95.  
  96. COMMON SHARED mouseExists%, mouseState%
  97.  
  98. SUB DepressedBox (boxType%, x1%, y1%, x2%, y2%, fg%, bg%, buttonStyle%)
  99.  
  100.     ' ────────────────────────────────────────────────────────────────────────
  101.     '  This function displays a 3D box that appears to be depressed into the
  102.     '  screen. The boxType% parameter is either SINGLEBORDER or DOUBLEBORDER,
  103.     '  both of which are defined in QBSCR.INC.  The buttonStyle% parameter is
  104.     '  either STYLE3D or STYLE2D, both of which are defined in QBSCR.INC. The
  105.     '  button style STYLE3D is used for color displays or 3D interfaces,
  106.     '  while STYLE2D is used for monochrome or non-3D interfaces.
  107.     ' ────────────────────────────────────────────────────────────────────────
  108.  
  109.     ' ────────────────────────────────────────────────────────────────────────
  110.     '  Define the box drawing characters based on the boxType%.
  111.     ' ────────────────────────────────────────────────────────────────────────
  112.     IF boxType% = SINGLEBORDER THEN
  113.         ulc$ = CHR$(218)
  114.         urc$ = CHR$(191)
  115.         ver$ = CHR$(179)
  116.         hor$ = CHR$(196)
  117.         llc$ = CHR$(192)
  118.         lrc$ = CHR$(217)
  119.     END IF
  120.     IF boxType% = DOUBLEBORDER THEN
  121.         ulc$ = CHR$(201)
  122.         urc$ = CHR$(187)
  123.         ver$ = CHR$(186)
  124.         hor$ = CHR$(205)
  125.         llc$ = CHR$(200)
  126.         lrc$ = CHR$(188)
  127.     END IF
  128.  
  129.     ' ────────────────────────────────────────────────────────────────────────
  130.     '  If buttonStyle% is STYLE2D, draw a simple box.
  131.     ' ────────────────────────────────────────────────────────────────────────
  132.     IF buttonStyle% = STYLE2D THEN
  133.         COLOR fg%, bg%
  134.         LOCATE y1%, x1%, 0: PRINT ulc$; STRING$(x2% - x1% - 1, hor$); urc$;
  135.         FOR i% = y1% + 1 TO y2% - 1
  136.             LOCATE i%, x1%, 0: PRINT ver$;
  137.             LOCATE i%, x2%, 0: PRINT ver$;
  138.         NEXT i%
  139.         LOCATE y2%, x1%, 0: PRINT llc$; STRING$(x2% - x1% - 1, hor$); lrc$;
  140.         EXIT SUB
  141.     END IF
  142.  
  143.     ' ────────────────────────────────────────────────────────────────────────
  144.     '  The rest of the code is dedicated to drawing a 3D shaded box.  The
  145.     '  top and left sides are drawn in a black foreground, and the bottom and
  146.     '  right sides are drawn in a white foreground.  This gives the appearance
  147.     '  of a shaded box that is depressed into the screen.
  148.     ' ────────────────────────────────────────────────────────────────────────
  149.     COLOR 0, bg%                              ' Draw the top side.
  150.     LOCATE y1%, x1%, 0: PRINT ulc$;
  151.     PRINT STRING$(x2% - x1% - 1, hor$);
  152.     COLOR 15, bg%
  153.     PRINT urc$;
  154.  
  155.     FOR i% = y1% + 1 TO y2% - 1               ' Draw the left and right sides.
  156.         LOCATE i%, x1%, 0: COLOR 0, bg%: PRINT ver$;
  157.         LOCATE i%, x2%, 0: COLOR 15, bg%: PRINT ver$;
  158.     NEXT i%
  159.  
  160.     COLOR 0, bg%                              ' Draw the bottom side.
  161.     LOCATE y2%, x1%, 0: PRINT llc$;
  162.     COLOR 15, bg%
  163.     PRINT STRING$(x2% - x1% - 1, hor$);
  164.     PRINT lrc$;
  165.  
  166. END SUB
  167.  
  168. SUB DrawButton (buttonType%, x1%, y1%, x2%, y2%, fg%, bg%, txt$, buttonStyle%)
  169.  
  170.     ' ────────────────────────────────────────────────────────────────────────
  171.     '  This routine draws a button on the screen with a text label inside it.
  172.     '  The buttonType% is either SINGLEBORDER or DOUBLEORDER, and the button-
  173.     '  Style%  is either STYLE3D or STYLE2D.  All these constants are defined
  174.     '  in QBSCR.INC. It will appear to be raised from the screen.
  175.     ' ────────────────────────────────────────────────────────────────────────
  176.  
  177.     ' ────────────────────────────────────────────────────────────────────────
  178.     '  Use the RaisedBox routine to draw the basic button border.
  179.     ' ────────────────────────────────────────────────────────────────────────
  180.     RaisedBox buttonType%, x1%, y1%, x2%, y2%, fg%, bg%, buttonStyle%
  181.  
  182.     ' ────────────────────────────────────────────────────────────────────────
  183.     '  Add the text to the button, centered (left-right) in the button.
  184.     ' ────────────────────────────────────────────────────────────────────────
  185.     LOCATE y1% + 1, (((x2% - x1%) - LEN(txt$)) \ 2) + x1% + 1, 0
  186.     COLOR fg%, bg%
  187.     PRINT txt$
  188.  
  189. END SUB
  190.  
  191. '***************************************************************************
  192. '*  Function: getEvent                                                     *
  193. '*  Purpose:  Obtain keyboard and mouse events and return them.            *
  194. '*  Params:   checkMouse% (IN): If TRUE (non-zero), causes this routine    *
  195. '*            to check the mouse.  If FALSE (zero), this routine will      *
  196. '*            NOT check the mouse for events.                              *
  197. '*            keyCode% (OUT): On return, contains scan code or ASCII code  *
  198. '*            of the key that was pressed on the keyboard.  If the key     *
  199. '*            was a normal character, it returns the ASCII code.  If it    *
  200. '*            was a special key (like a function or arrow key), it returns *
  201. '*            a unique integer.  See QBSCR_3D.BI for these integers.       *
  202. '*            mouseX% (OUT): Current X-coordinate of mouse if mouse event  *
  203. '*            occurred.                                                    *
  204. '*            mouseY% (OUT): Current Y-coordinate of mouse if mouse event  *
  205. '*            occurred.                                                    *
  206. '*  Returns:  A predefined code that identified the type of event that     *
  207. '*            occurred.  They are named constants in the QBSCR_3D.BI file  *
  208. '*            and are also duplicated here:                                *
  209. '*                                                                         *
  210. '*            RETURN CODE          EVENT                                   *
  211. '*            ----------------     --------------------------------------  *
  212. '*            EMmoved              Mouse Moved                             *
  213. '*            EMpressedLeft        Mouse left button pressed               *
  214. '*            EMpressedRight       Mouse right button pressed              *
  215. '*            EMpressedCenter      Mouse center button pressed             *
  216. '*            EMreleasedLeft       Mouse left button released              *
  217. '*            EMreleasedRight      Mouse right button released             *
  218. '*            EMreleasedCenter     Mouse center button released            *
  219. '*            EKpressed            Key pressed on keyboard                 *
  220. '*                                                                         *
  221. '***************************************************************************
  222. FUNCTION getEvent% (checkMouse%, keyCode%, mouseX%, mouseY%)
  223.  
  224.     ' **
  225.     ' ** Clear all events from all buffers
  226.     ' **
  227.     WHILE (INKEY$ <> "")        ' Clear all keypresses from keyboard buffer.
  228.     WEND
  229.     IF (checkMouse%) THEN
  230.         MouseButtonPressInfo LEFTBUTTON, numLeftPresses%, mx%, my%
  231.         MouseButtonPressInfo RIGHTBUTTON, numRightPresses%, mx%, my%
  232.         MouseButtonPressInfo CENTERBUTTON, numCenterPresses%, mx%, my%
  233.         MouseButtonReleaseInfo LEFTBUTTON, numLeftReleases%, mx%, my%
  234.         MouseButtonReleaseInfo RIGHTBUTTON, numRightReleases%, mx%, my%
  235.         MouseButtonReleaseInfo CENTERBUTTON, numCenterReleases%, mx%, my%
  236.         MousePosition oldMouseX%, oldMouseY%
  237.         numLeftPresses% = 0
  238.         numRightPresses% = 0
  239.         numCenterPresses% = 0
  240.         numLeftReleases% = 0
  241.         numRightReleases% = 0
  242.         numCenterReleases% = 0
  243.         mx% = 0
  244.         my% = 0
  245.     END IF
  246.  
  247.     ' **
  248.     ' ** Initialize event flag
  249.     ' **
  250.     eventOccurred% = FALSE
  251.  
  252.     ' **
  253.     ' ** Sit in a loop waiting for an event.  If one occurs, set return value,
  254.     ' ** fill in OUT parameters, and get outta here.
  255.     ' **
  256.     WHILE (eventOccurred% = FALSE)
  257.  
  258.         ' **
  259.         ' ** If OK to do so, check mouse for events.
  260.         ' **
  261.         IF (checkMouse%) THEN
  262.  
  263.             ' **
  264.             ' ** First, see if mouse has moved.
  265.             ' **
  266.             MousePosition mx%, my%
  267.             IF (mx% <> oldMouseX%) OR (my% <> oldMouseY%) THEN
  268.                 mouseX% = (mx% \ 8) + 1
  269.                 mouseY% = (my% \ 8) + 1
  270.                 returnValue% = EMmoved
  271.                 eventOccurred% = TRUE
  272.             END IF
  273.  
  274.             ' **
  275.             ' ** If no event so far, check to see if mouse left button was pressed.
  276.             ' **
  277.             IF (eventOccurred% = FALSE) THEN
  278.                 MouseButtonPressInfo LEFTBUTTON, numLeftPresses%, mx%, my%
  279.                 IF (numLeftPresses% <> 0) THEN
  280.                     mouseX% = (mx% \ 8) + 1
  281.                     mouseY% = (my% \ 8) + 1
  282.                     returnValue% = EMpressedLeft
  283.                     eventOccurred% = TRUE
  284.                 END IF
  285.             END IF
  286.  
  287.             ' **
  288.             ' ** If no event so far, check to see if mouse right button was pressed.
  289.             ' **
  290.             IF (eventOccurred% = FALSE) THEN
  291.                 MouseButtonPressInfo RIGHTBUTTON, numRightPresses%, mx%, my%
  292.                 IF (numRightPresses% <> 0) THEN
  293.                     mouseX% = (mx% \ 8) + 1
  294.                     mouseY% = (my% \ 8) + 1
  295.                     returnValue% = EMpressedRight
  296.                     eventOccurred% = TRUE
  297.                 END IF
  298.             END IF
  299.  
  300.             ' **
  301.             ' ** If no event so far, check to see if mouse left button was
  302.             ' ** released.
  303.             ' **
  304.             IF (eventOccurred% = FALSE) THEN
  305.                 MouseButtonReleaseInfo LEFTBUTTON, numLeftReleases%, mx%, my%
  306.                 IF (numLeftReleases% <> 0) THEN
  307.                     mouseX% = (mx% \ 8) + 1
  308.                     mouseY% = (my% \ 8) + 1
  309.                     returnValue% = EMreleasedLeft
  310.                     eventOccurred% = TRUE
  311.                 END IF
  312.             END IF
  313.  
  314.             ' **
  315.             ' ** If no event so far, check to see if mouse right button was
  316.             ' ** released.
  317.             ' **
  318.             IF (eventOccurred% = FALSE) THEN
  319.                 MouseButtonReleaseInfo RIGHTBUTTON, numRightReleases%, mx%, my%
  320.                 IF (numRightReleases% <> 0) THEN
  321.                     mouseX% = (mx% \ 8) + 1
  322.                     mouseY% = (my% \ 8) + 1
  323.                     returnValue% = EMreleasedRight
  324.                     eventOccurred% = TRUE
  325.                 END IF
  326.             END IF
  327.         END IF
  328.          
  329.         ' **
  330.         ' ** If no event so far, check the keyboard for press.
  331.         ' **
  332.         IF (eventOccurred% = FALSE) THEN
  333.  
  334.             key$ = INKEY$
  335.          
  336.             IF (key$ <> "") THEN    ' If key was hit then fill in keyCode.
  337.                 IF (MID$(key$, 1, 1) = CHR$(0)) THEN
  338.                     keyCode% = CVI(LEFT$(key$ + "  ", 2))
  339.                 ELSE
  340.                     keyCode% = ASC(key$)
  341.                 END IF
  342.                 returnValue% = EKpressed
  343.                 eventOccurred% = TRUE
  344.             END IF
  345.  
  346.         END IF  ' ** No event has occurred **
  347.  
  348.     WEND
  349.  
  350.     getEvent% = returnValue%
  351.  
  352. END FUNCTION
  353.  
  354. SUB PressButton (buttonType%, x1%, y1%, x2%, y2%, fg%, bg%, txt$, buttonStyle%)
  355.  
  356.     ' ────────────────────────────────────────────────────────────────────────
  357.     '  This routine simulates the actual visual pressing of a screen button.
  358.     '  If the button is 3D, it "presses" the button by reversing the shading,
  359.     '  thus causing it to appear depressed into the screen instead of raised
  360.     '  from it.  This routine assumes the mouse is being used to activate the
  361.     '  the button.  It will wait until the mouse button is released before
  362.     '  exiting and thus once again raising the button.  The whole effect is
  363.     '  that the user clicks the button with the mouse, it stays depressed
  364.     '  until they let go of it (the mouse button).
  365.     ' ────────────────────────────────────────────────────────────────────────
  366.  
  367.     ' ────────────────────────────────────────────────────────────────────────
  368.     '  Hide the mouse cursor while we draw on the screen.
  369.     ' ────────────────────────────────────────────────────────────────────────
  370.     MouseHide
  371.  
  372.     ' ────────────────────────────────────────────────────────────────────────
  373.     '  Draw in a depressed rendition of the button.
  374.     ' ────────────────────────────────────────────────────────────────────────
  375.     PressedButton buttonType%, x1%, y1%, x2%, y2%, fg%, bg%, txt$, buttonStyle%
  376.  
  377.     ' ────────────────────────────────────────────────────────────────────────
  378.     '  Now show the mouse and wait until we get a button release event.
  379.     ' ────────────────────────────────────────────────────────────────────────
  380.     MouseShow
  381.     MouseButtonReleaseInfo LEFTBUTTON, numReleases%, x%, y%
  382.     numReleases% = 0
  383.     WHILE (numReleases% = 0)
  384.         MouseButtonReleaseInfo LEFTBUTTON, numReleases%, x%, y%
  385.     WEND
  386.  
  387.     ' ────────────────────────────────────────────────────────────────────────
  388.     '  Now that they've let go of the button, redisplay it in its normal,
  389.     '  raised position.
  390.     ' ────────────────────────────────────────────────────────────────────────
  391.     MouseHide
  392.     DrawButton buttonType%, x1%, y1%, x2%, y2%, fg%, bg%, txt$, buttonStyle%
  393.     MouseShow
  394.  
  395. END SUB
  396.  
  397. SUB PressedButton (buttonType%, x1%, y1%, x2%, y2%, fg%, bg%, txt$, buttonStyle%)
  398.  
  399.     ' ────────────────────────────────────────────────────────────────────────
  400.     '  This routine draws a button on the screen with a text label inside it.
  401.     '  The buttonType% is either SINGLEBORDER or DOUBLEORDER, and the button-
  402.     '  Style%  is either STYLE3D or STYLE2D.  All these constants are defined
  403.     '  in QBSCR.INC.  It will appear to be depressed into the screen.
  404.     ' ────────────────────────────────────────────────────────────────────────
  405.  
  406.     ' ────────────────────────────────────────────────────────────────────────
  407.     '  Use the DepressedBox routine to draw the basic button border.
  408.     ' ────────────────────────────────────────────────────────────────────────
  409.     DepressedBox buttonType%, x1%, y1%, x2%, y2%, fg%, bg%, buttonStyle%
  410.  
  411.     ' ────────────────────────────────────────────────────────────────────────
  412.     '  Add the button title centered between the sides of the button.
  413.     ' ────────────────────────────────────────────────────────────────────────
  414.     LOCATE y1% + 1, (((x2% - x1%) - LEN(txt$)) \ 2) + x1% + 1, 0
  415.     COLOR fg%, bg%
  416.     PRINT txt$
  417.  
  418. END SUB
  419.  
  420. SUB RaisedBox (boxType%, x1%, y1%, x2%, y2%, fg%, bg%, buttonStyle%)
  421.  
  422.     ' ────────────────────────────────────────────────────────────────────────
  423.     '  This function displays a 3D box that appears to be raised from the
  424.     '  screen. The boxType% parameter is either SINGLEBORDER or DOUBLEBORDER,
  425.     '  both of which are defined in QBSCR.INC.  The buttonStyle% parameter is
  426.     '  either STYLE3D or STYLE2D, both of which are defined in QBSCR.INC. The
  427.     '  button style STYLE3D is used for color displays or 3D interfaces,
  428.     '  while STYLE2D is used for monochrome or non-3D interfaces.
  429.     ' ────────────────────────────────────────────────────────────────────────
  430.  
  431.     ' ────────────────────────────────────────────────────────────────────────
  432.     '  Define the box drawing characters based on the boxType%.
  433.     ' ────────────────────────────────────────────────────────────────────────
  434.     IF boxType% = SINGLEBORDER THEN
  435.         ulc$ = CHR$(218)
  436.         urc$ = CHR$(191)
  437.         ver$ = CHR$(179)
  438.         hor$ = CHR$(196)
  439.         llc$ = CHR$(192)
  440.         lrc$ = CHR$(217)
  441.     END IF
  442.     IF boxType% = DOUBLEBORDER THEN
  443.         ulc$ = CHR$(201)
  444.         urc$ = CHR$(187)
  445.         ver$ = CHR$(186)
  446.         hor$ = CHR$(205)
  447.         llc$ = CHR$(200)
  448.         lrc$ = CHR$(188)
  449.     END IF
  450.  
  451.     ' ────────────────────────────────────────────────────────────────────────
  452.     '  If buttonStyle% is STYLE2D, draw a simple box.
  453.     ' ────────────────────────────────────────────────────────────────────────
  454.     IF (buttonStyle% = STYLE2D) THEN
  455.         COLOR fg%, bg%
  456.         LOCATE y1%, x1%, 0: PRINT ulc$; STRING$(x2% - x1% - 1, hor$); urc$;
  457.         FOR i% = y1% + 1 TO y2% - 1
  458.             LOCATE i%, x1%, 0: PRINT ver$;
  459.             LOCATE i%, x2%, 0: PRINT ver$;
  460.         NEXT i%
  461.         LOCATE y2%, x1%, 0: PRINT llc$; STRING$(x2% - x1% - 1, hor$); lrc$;
  462.         EXIT SUB
  463.     END IF
  464.  
  465.     ' ────────────────────────────────────────────────────────────────────────
  466.     '  The rest of the code is dedicated to drawing a 3D shaded box.  The
  467.     '  top and left sides are drawn in a white foreground, and the bottom and
  468.     '  right sides are drawn in a black foreground.  This gives the appearance
  469.     '  of a shaded box that is raised from the screen.
  470.     ' ────────────────────────────────────────────────────────────────────────
  471.     COLOR 15, bg%                        ' Draw the top of the box.
  472.     LOCATE y1%, x1%, 0: PRINT ulc$;
  473.     PRINT STRING$(x2% - x1% - 1, hor$);
  474.     COLOR 0, bg%
  475.     PRINT urc$;
  476.  
  477.     FOR i% = y1% + 1 TO y2% - 1          ' Draw the sides of the box.
  478.         LOCATE i%, x1%, 0: COLOR 15, bg%: PRINT ver$;
  479.         LOCATE i%, x2%, 0: COLOR 0, bg%: PRINT ver$;
  480.     NEXT i%
  481.  
  482.     COLOR 15, bg%                        ' Draw the bottom of the box.
  483.     LOCATE y2%, x1%, 0: PRINT llc$;
  484.     COLOR 0, bg%
  485.     PRINT STRING$(x2% - x1% - 1, hor$);
  486.     PRINT lrc$;
  487.  
  488. END SUB
  489.  
  490.